mirror of
https://github.com/Fishwaldo/build.git
synced 2025-07-05 12:38:26 +00:00
Odroid C2 4.12 NEXT kernel patches, enable back kernel target
This commit is contained in:
parent
e388aa9665
commit
7a08a679b8
170 changed files with 8508 additions and 22409 deletions
|
@ -6,7 +6,7 @@ BOOTCONFIG="odroidc2_config"
|
|||
MODULES="bonding"
|
||||
MODULES_NEXT=""
|
||||
#
|
||||
KERNEL_TARGET="default,dev"
|
||||
KERNEL_TARGET="default,next,dev"
|
||||
CLI_TARGET="jessie,xenial:default"
|
||||
DESKTOP_TARGET="xenial:default"
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,7 +22,7 @@ case $BRANCH in
|
|||
;;
|
||||
next)
|
||||
KERNELSOURCE=$MAINLINE_KERNEL_SOURCE
|
||||
KERNELBRANCH='branch:linux-4.10.y'
|
||||
KERNELBRANCH='branch:linux-4.12.y'
|
||||
KERNELDIR=$MAINLINE_KERNEL_DIR
|
||||
;;
|
||||
dev)
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
From 86f0b91719a9d97095187af6ddaade3b34dc1257 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 16 Mar 2017 09:38:10 +0100
|
||||
Subject: [PATCH 01/93] ARM64: dts: meson-gxbb: Add gpio-ranges
|
||||
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index b353073..2be29a3 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -186,6 +186,7 @@
|
||||
reg-names = "mux", "pull", "gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
+ gpio-ranges = <&pinctrl_aobus 0 0 14>;
|
||||
};
|
||||
|
||||
uart_ao_a_pins: uart_ao_a {
|
||||
@@ -279,6 +280,7 @@
|
||||
reg-names = "mux", "pull", "pull-enable", "gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
+ gpio-ranges = <&pinctrl_periphs 0 14 120>;
|
||||
};
|
||||
|
||||
emmc_pins: emmc {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
From d074af897d4547d239f93b55c7baa4cf47a9f535 Mon Sep 17 00:00:00 2001
|
||||
From 8ede929172f118c43ef1664fe66b56dadff3310f Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 28 Feb 2017 15:22:54 +0100
|
||||
Subject: [PATCH 57/93] Add HDMI support for Odroid-C2
|
||||
Subject: [PATCH 01/79] Add HDMI support for Odroid-C2
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
.../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 23 ++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
index 492ac35..ee77c3d 100644
|
||||
index 54a9c6a..0066b1a 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
@@ -135,6 +135,17 @@
|
||||
|
@ -29,7 +30,7 @@ index 492ac35..ee77c3d 100644
|
|||
};
|
||||
|
||||
&scpi_clocks {
|
||||
@@ -240,3 +251,15 @@
|
||||
@@ -309,3 +320,15 @@
|
||||
vmmc-supply = <&vcc3v3>;
|
||||
vqmmc-supply = <&vcc1v8>;
|
||||
};
|
|
@ -1,9 +1,10 @@
|
|||
From d3527920b1ab4959557bda86974b143228746ce9 Mon Sep 17 00:00:00 2001
|
||||
From aa7bd7ebd01c4a7a1e7f1cdca431e5447313fefc Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Tue, 14 Feb 2017 19:18:04 +0100
|
||||
Subject: [PATCH 88/93] drm/meson: select dw-hdmi i2s audio for meson hdmi
|
||||
Subject: [PATCH 02/79] drm/meson: select dw-hdmi i2s audio for meson hdmi
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/gpu/drm/meson/Kconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
|
@ -1,40 +0,0 @@
|
|||
From be24356f2a4214a9efbb28441f58cfd91aefb4b4 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 16 Mar 2017 09:40:16 +0100
|
||||
Subject: [PATCH 02/93] pinctrl: meson: use gpio-ranges from DT
|
||||
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson.c | 14 +-------------
|
||||
1 file changed, 1 insertion(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
|
||||
index 620c231a..3372ce9 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
|
||||
@@ -557,22 +557,10 @@ static int meson_gpiolib_register(struct meson_pinctrl *pc)
|
||||
if (ret) {
|
||||
dev_err(pc->dev, "can't add gpio chip %s\n",
|
||||
pc->data->name);
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- ret = gpiochip_add_pin_range(&pc->chip, dev_name(pc->dev),
|
||||
- 0, pc->data->pin_base,
|
||||
- pc->chip.ngpio);
|
||||
- if (ret) {
|
||||
- dev_err(pc->dev, "can't add pin range\n");
|
||||
- goto fail;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
-fail:
|
||||
- gpiochip_remove(&pc->chip);
|
||||
-
|
||||
- return ret;
|
||||
}
|
||||
|
||||
static struct regmap_config meson_regmap_config = {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From 58d7c939ec531f768b03b0be2a714805a6aac3cf Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 16 Mar 2017 09:40:48 +0100
|
||||
Subject: [PATCH 03/93] ARM64: dts: meson-gxbb: Add USB Hub GPIO hog
|
||||
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
index c59403a..492ac35 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
|
||||
@@ -177,6 +177,15 @@
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
+&gpio_ao {
|
||||
+ usb-hub {
|
||||
+ gpio-hog;
|
||||
+ gpios = <GPIOAO_4 GPIO_ACTIVE_HIGH>;
|
||||
+ output-high;
|
||||
+ line-name = "usb-hub-reset";
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&usb0_phy {
|
||||
status = "okay";
|
||||
phy-supply = <&usb_otg_pwr>;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,15 +1,16 @@
|
|||
From 4dc44c40b6a55b15c2ce5189ce6b9d328b8b4344 Mon Sep 17 00:00:00 2001
|
||||
From 095d92c205f588fbeb207a124eb860ea57dd568a Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 27 Mar 2017 11:08:24 +0200
|
||||
Subject: [PATCH 92/93] drm: bridge: dw-hdmi: Use AUTO CTS setup mode when
|
||||
Subject: [PATCH 03/79] 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 | 43 +++++++++++++++++++------------
|
||||
1 file changed, 27 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index 910d579..ad8d62a 100644
|
||||
index 4e1f54a..ee788ca 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -420,8 +420,12 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
|
|
@ -1,75 +0,0 @@
|
|||
From cbe0dba01d39c008cff6460bfcb1366801b4a41c Mon Sep 17 00:00:00 2001
|
||||
From: Xinliang Liu <xinliang.liu@linaro.org>
|
||||
Date: Wed, 15 Feb 2017 17:19:08 +0100
|
||||
Subject: [PATCH 04/93] drm/fb-helper: Add multi buffer support for cma fbdev
|
||||
|
||||
This patch add a config to support to create multi buffer for cma fbdev.
|
||||
Such as double buffer and triple buffer.
|
||||
|
||||
Cma fbdev is convient to add a legency fbdev. And still many Android
|
||||
devices use fbdev now and at least double buffer is needed for these
|
||||
Android devices, so that a buffer flip can be operated. It will need
|
||||
some time for Android device vendors to abondon legency fbdev. So multi
|
||||
buffer for fbdev is needed.
|
||||
|
||||
Signed-off-by: Xinliang Liu <xinliang.liu@linaro.org>
|
||||
[s.christ@phytec.de: Picking patch from
|
||||
https://lkml.org/lkml/2015/9/14/188]
|
||||
Signed-off-by: Stefan Christ <s.christ@phytec.de>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||
---
|
||||
drivers/gpu/drm/Kconfig | 9 +++++++++
|
||||
drivers/gpu/drm/drm_fb_helper.c | 10 ++++++++++
|
||||
2 files changed, 19 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
|
||||
index ebfe840..700c8b8 100644
|
||||
--- a/drivers/gpu/drm/Kconfig
|
||||
+++ b/drivers/gpu/drm/Kconfig
|
||||
@@ -84,6 +84,15 @@ config DRM_FBDEV_EMULATION
|
||||
|
||||
If in doubt, say "Y".
|
||||
|
||||
+config DRM_FBDEV_OVERALLOC
|
||||
+ int "Overallocation of the fbdev buffer"
|
||||
+ depends on DRM_FBDEV_EMULATION
|
||||
+ default 100
|
||||
+ help
|
||||
+ Defines the fbdev buffer overallocation in percent. Default
|
||||
+ is 100. Typical values for double buffering will be 200,
|
||||
+ triple buffering 300.
|
||||
+
|
||||
config DRM_LOAD_EDID_FIRMWARE
|
||||
bool "Allow to specify an EDID data set instead of probing for it"
|
||||
depends on DRM_KMS_HELPER
|
||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||
index e934b54..c6de87a 100644
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -48,6 +48,12 @@
|
||||
MODULE_PARM_DESC(fbdev_emulation,
|
||||
"Enable legacy fbdev emulation [default=true]");
|
||||
|
||||
+static int drm_fbdev_overalloc = CONFIG_DRM_FBDEV_OVERALLOC;
|
||||
+module_param(drm_fbdev_overalloc, int, 0444);
|
||||
+MODULE_PARM_DESC(drm_fbdev_overalloc,
|
||||
+ "Overallocation of the fbdev buffer (%) [default="
|
||||
+ __MODULE_STRING(CONFIG_DRM_FBDEV_OVERALLOC) "]");
|
||||
+
|
||||
static LIST_HEAD(kernel_fb_helper_list);
|
||||
static DEFINE_MUTEX(kernel_fb_helper_lock);
|
||||
|
||||
@@ -1573,6 +1579,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
sizes.fb_height = sizes.surface_height = 768;
|
||||
}
|
||||
|
||||
+ /* Handle our overallocation */
|
||||
+ sizes.surface_height *= drm_fbdev_overalloc;
|
||||
+ sizes.surface_height /= 100;
|
||||
+
|
||||
/* push down into drivers */
|
||||
ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
|
||||
if (ret < 0)
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
From 4923e7dd3aa1d072bb63ee46bdfc59f82de89a9c Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 30 May 2017 16:45:06 +0200
|
||||
Subject: [PATCH 04/79] dt-bindings: clock: gxbb-aoclk: Add CEC 32k clock
|
||||
|
||||
This patchadds the clock binding entry for the CEC 32K AO Clock.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
include/dt-bindings/clock/gxbb-aoclkc.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/include/dt-bindings/clock/gxbb-aoclkc.h b/include/dt-bindings/clock/gxbb-aoclkc.h
|
||||
index 3175148..9d15e22 100644
|
||||
--- a/include/dt-bindings/clock/gxbb-aoclkc.h
|
||||
+++ b/include/dt-bindings/clock/gxbb-aoclkc.h
|
||||
@@ -62,5 +62,6 @@
|
||||
#define CLKID_AO_UART1 3
|
||||
#define CLKID_AO_UART2 4
|
||||
#define CLKID_AO_IR_BLASTER 5
|
||||
+#define CLKID_AO_CEC_32K 6
|
||||
|
||||
#endif
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,376 @@
|
|||
From 7e59aa215674f39cebb870b68bc0dc54c73cd407 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 30 May 2017 16:45:28 +0200
|
||||
Subject: [PATCH 05/79] clk: meson: gxbb-aoclk: Add CEC 32k clock
|
||||
|
||||
The CEC 32K AO Clock is a dual divider with dual counter to provide a more
|
||||
precise 32768Hz clock for the CEC subsystem from the external xtal.
|
||||
|
||||
The AO clocks management registers are spread among the AO register space,
|
||||
so this patch also adds management of these registers mappings then uses them
|
||||
for the CEC 32K AO clock management.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/Makefile | 2 +-
|
||||
drivers/clk/meson/gxbb-aoclk-32k.c | 188 +++++++++++++++++++++++++++++++++++++
|
||||
drivers/clk/meson/gxbb-aoclk.c | 59 ++++++++++--
|
||||
drivers/clk/meson/gxbb-aoclk.h | 23 +++++
|
||||
4 files changed, 265 insertions(+), 7 deletions(-)
|
||||
create mode 100644 drivers/clk/meson/gxbb-aoclk-32k.c
|
||||
create mode 100644 drivers/clk/meson/gxbb-aoclk.h
|
||||
|
||||
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
|
||||
index 83b6d9d..e315057 100644
|
||||
--- a/drivers/clk/meson/Makefile
|
||||
+++ b/drivers/clk/meson/Makefile
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o
|
||||
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
|
||||
-obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
|
||||
+obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o
|
||||
diff --git a/drivers/clk/meson/gxbb-aoclk-32k.c b/drivers/clk/meson/gxbb-aoclk-32k.c
|
||||
new file mode 100644
|
||||
index 0000000..3c06413
|
||||
--- /dev/null
|
||||
+++ b/drivers/clk/meson/gxbb-aoclk-32k.c
|
||||
@@ -0,0 +1,188 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 BayLibre, SAS.
|
||||
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk-provider.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include "gxbb-aoclk.h"
|
||||
+
|
||||
+/*
|
||||
+ * The AO Domain embeds a dual/divider to generate a more precise
|
||||
+ * 32,768KHz clock for low-power suspend mode and CEC.
|
||||
+ */
|
||||
+
|
||||
+#define AO_RTC_ALT_CLK_CNTL0 0x0
|
||||
+#define AO_RTC_ALT_CLK_CNTL1 0x4
|
||||
+#define AO_CRT_CLK_CNTL1 0x0
|
||||
+#define AO_RTI_PWR_CNTL_REG0 0x4
|
||||
+
|
||||
+#define CLK_CNTL0_N1_MASK GENMASK(11, 0)
|
||||
+#define CLK_CNTL0_N2_MASK GENMASK(23, 12)
|
||||
+#define CLK_CNTL0_DUALDIV_EN BIT(28)
|
||||
+#define CLK_CNTL0_OUT_GATE_EN BIT(30)
|
||||
+#define CLK_CNTL0_IN_GATE_EN BIT(31)
|
||||
+
|
||||
+#define CLK_CNTL1_M1_MASK GENMASK(11, 0)
|
||||
+#define CLK_CNTL1_M2_MASK GENMASK(23, 12)
|
||||
+#define CLK_CNTL1_BYPASS_EN BIT(24)
|
||||
+#define CLK_CNTL1_SELECT_OSC BIT(27)
|
||||
+
|
||||
+#define PWR_CNTL_ALT_32K_SEL GENMASK(13, 10)
|
||||
+
|
||||
+struct cec_32k_freq_table {
|
||||
+ unsigned long parent_rate;
|
||||
+ unsigned long target_rate;
|
||||
+ bool dualdiv;
|
||||
+ unsigned int n1;
|
||||
+ unsigned int n2;
|
||||
+ unsigned int m1;
|
||||
+ unsigned int m2;
|
||||
+};
|
||||
+
|
||||
+static const struct cec_32k_freq_table aoclk_cec_32k_table[] = {
|
||||
+ [0] = {
|
||||
+ .parent_rate = 24000000,
|
||||
+ .target_rate = 32768,
|
||||
+ .dualdiv = true,
|
||||
+ .n1 = 733,
|
||||
+ .n2 = 732,
|
||||
+ .m1 = 8,
|
||||
+ .m2 = 11,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * If CLK_CNTL0_DUALDIV_EN == 0
|
||||
+ * - will use N1 divider only
|
||||
+ * If CLK_CNTL0_DUALDIV_EN == 1
|
||||
+ * - hold M1 cycles of N1 divider then changes to N2
|
||||
+ * - hold M2 cycles of N2 divider then changes to N1
|
||||
+ * Then we can get more accurate division.
|
||||
+ */
|
||||
+static unsigned long aoclk_cec_32k_recalc_rate(struct clk_hw *hw,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw);
|
||||
+ u32 reg0, reg1;
|
||||
+
|
||||
+ reg0 = readl_relaxed(cec_32k->rtc_base + AO_RTC_ALT_CLK_CNTL0);
|
||||
+ reg1 = readl_relaxed(cec_32k->rtc_base + AO_RTC_ALT_CLK_CNTL1);
|
||||
+
|
||||
+ if (reg1 & CLK_CNTL1_BYPASS_EN)
|
||||
+ return parent_rate;
|
||||
+
|
||||
+ if (reg0 & CLK_CNTL0_DUALDIV_EN) {
|
||||
+ unsigned long n1, n2, m1, m2, f1, f2, p1, p2;
|
||||
+
|
||||
+ n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1;
|
||||
+ n2 = FIELD_GET(CLK_CNTL0_N2_MASK, reg0) + 1;
|
||||
+
|
||||
+ m1 = FIELD_GET(CLK_CNTL1_M1_MASK, reg1) + 1;
|
||||
+ m2 = FIELD_GET(CLK_CNTL1_M2_MASK, reg1) + 1;
|
||||
+
|
||||
+ f1 = DIV_ROUND_CLOSEST(parent_rate, n1);
|
||||
+ f2 = DIV_ROUND_CLOSEST(parent_rate, n2);
|
||||
+
|
||||
+ p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2));
|
||||
+ p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2));
|
||||
+
|
||||
+ return DIV_ROUND_UP(100000000, p1 + p2);
|
||||
+ }
|
||||
+ else {
|
||||
+ unsigned long n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1;
|
||||
+
|
||||
+ return DIV_ROUND_CLOSEST(parent_rate, n1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static const struct cec_32k_freq_table *find_cec_32k_freq(unsigned long rate,
|
||||
+ unsigned long prate)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0 ; i < ARRAY_SIZE(aoclk_cec_32k_table) ; ++i)
|
||||
+ if (aoclk_cec_32k_table[i].parent_rate == prate &&
|
||||
+ aoclk_cec_32k_table[i].target_rate == rate)
|
||||
+ return &aoclk_cec_32k_table[i];
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static long aoclk_cec_32k_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long *prate)
|
||||
+{
|
||||
+ const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate,
|
||||
+ *prate);
|
||||
+
|
||||
+ /* If invalid return first one */
|
||||
+ if (!freq)
|
||||
+ return freq[0].target_rate;
|
||||
+
|
||||
+ return freq->target_rate;
|
||||
+}
|
||||
+
|
||||
+static int aoclk_cec_32k_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate,
|
||||
+ parent_rate);
|
||||
+ struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw);
|
||||
+ u32 reg = 0;
|
||||
+
|
||||
+ if (!freq)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Disable clock */
|
||||
+ reg = readl(cec_32k->rtc_base + AO_RTC_ALT_CLK_CNTL0);
|
||||
+ reg &= ~(CLK_CNTL0_IN_GATE_EN | CLK_CNTL0_OUT_GATE_EN);
|
||||
+ writel(reg, cec_32k->rtc_base + AO_RTC_ALT_CLK_CNTL0);
|
||||
+
|
||||
+ if (freq->dualdiv)
|
||||
+ reg = CLK_CNTL0_DUALDIV_EN |
|
||||
+ FIELD_PREP(CLK_CNTL0_N1_MASK, freq->n1 - 1) |
|
||||
+ FIELD_PREP(CLK_CNTL0_N2_MASK, freq->n2 - 1);
|
||||
+ else
|
||||
+ reg = FIELD_PREP(CLK_CNTL0_N1_MASK, freq->n1 - 1);
|
||||
+
|
||||
+ writel_relaxed(reg, cec_32k->rtc_base + AO_RTC_ALT_CLK_CNTL0);
|
||||
+
|
||||
+ if (freq->dualdiv)
|
||||
+ reg = FIELD_PREP(CLK_CNTL1_M1_MASK, freq->m1 - 1) |
|
||||
+ FIELD_PREP(CLK_CNTL1_M2_MASK, freq->m2 - 1);
|
||||
+ else
|
||||
+ reg = FIELD_PREP(CLK_CNTL1_M1_MASK, freq->m1 - 1);
|
||||
+
|
||||
+ writel_relaxed(reg, cec_32k->rtc_base + AO_RTC_ALT_CLK_CNTL1);
|
||||
+
|
||||
+ /* Enable clock */
|
||||
+ reg = readl(cec_32k->rtc_base + AO_RTC_ALT_CLK_CNTL0);
|
||||
+ reg |= CLK_CNTL0_IN_GATE_EN;
|
||||
+ writel(reg, cec_32k->rtc_base + AO_RTC_ALT_CLK_CNTL0);
|
||||
+
|
||||
+ udelay(200);
|
||||
+
|
||||
+ reg |= CLK_CNTL0_OUT_GATE_EN;
|
||||
+ writel(reg, cec_32k->rtc_base + AO_RTC_ALT_CLK_CNTL0);
|
||||
+
|
||||
+ reg = readl(cec_32k->crt_base + AO_CRT_CLK_CNTL1);
|
||||
+ reg |= CLK_CNTL1_SELECT_OSC; /* select cts_rtc_oscin_clk */
|
||||
+ writel(reg, cec_32k->crt_base + AO_CRT_CLK_CNTL1);
|
||||
+
|
||||
+ /* Select 32k from XTAL */
|
||||
+ regmap_write_bits(cec_32k->pwr_regmap,
|
||||
+ AO_RTI_PWR_CNTL_REG0,
|
||||
+ PWR_CNTL_ALT_32K_SEL,
|
||||
+ FIELD_PREP(PWR_CNTL_ALT_32K_SEL, 4));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+const struct clk_ops meson_aoclk_cec_32k_ops = {
|
||||
+ .recalc_rate = aoclk_cec_32k_recalc_rate,
|
||||
+ .round_rate = aoclk_cec_32k_round_rate,
|
||||
+ .set_rate = aoclk_cec_32k_set_rate,
|
||||
+};
|
||||
diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
|
||||
index b45c5fb..e47f021 100644
|
||||
--- a/drivers/clk/meson/gxbb-aoclk.c
|
||||
+++ b/drivers/clk/meson/gxbb-aoclk.c
|
||||
@@ -56,9 +56,13 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <linux/init.h>
|
||||
+#include <linux/delay.h>
|
||||
#include <dt-bindings/clock/gxbb-aoclkc.h>
|
||||
#include <dt-bindings/reset/gxbb-aoclkc.h>
|
||||
+#include "gxbb-aoclk.h"
|
||||
|
||||
static DEFINE_SPINLOCK(gxbb_aoclk_lock);
|
||||
|
||||
@@ -104,6 +108,17 @@ static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev,
|
||||
GXBB_AO_GATE(uart2, 5);
|
||||
GXBB_AO_GATE(ir_blaster, 6);
|
||||
|
||||
+static struct aoclk_cec_32k cec_32k_ao = {
|
||||
+ .lock = &gxbb_aoclk_lock,
|
||||
+ .hw.init = &(struct clk_init_data) {
|
||||
+ .name = "cec_32k_ao",
|
||||
+ .ops = &meson_aoclk_cec_32k_ops,
|
||||
+ .parent_names = (const char *[]){ "xtal" },
|
||||
+ .num_parents = 1,
|
||||
+ .flags = CLK_IGNORE_UNUSED,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static unsigned int gxbb_aoclk_reset[] = {
|
||||
[RESET_AO_REMOTE] = 16,
|
||||
[RESET_AO_I2C_MASTER] = 18,
|
||||
@@ -130,28 +145,52 @@ static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev,
|
||||
[CLKID_AO_UART1] = &uart1_ao.hw,
|
||||
[CLKID_AO_UART2] = &uart2_ao.hw,
|
||||
[CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
|
||||
+ [CLKID_AO_CEC_32K] = &cec_32k_ao.hw,
|
||||
},
|
||||
- .num = ARRAY_SIZE(gxbb_aoclk_gate),
|
||||
+ .num = 7,
|
||||
};
|
||||
|
||||
static int gxbb_aoclkc_probe(struct platform_device *pdev)
|
||||
{
|
||||
- struct resource *res;
|
||||
+ struct gxbb_aoclk_reset_controller *rstc;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct regmap *regmap_pwr;
|
||||
+ void __iomem *base_crt;
|
||||
+ void __iomem *base_rtc;
|
||||
void __iomem *base;
|
||||
+ struct resource *res;
|
||||
int ret, clkid;
|
||||
- struct device *dev = &pdev->dev;
|
||||
- struct gxbb_aoclk_reset_controller *rstc;
|
||||
|
||||
rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL);
|
||||
if (!rstc)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Generic clocks */
|
||||
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aoclk");
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
+ /* CRT base */
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aocrt");
|
||||
+ base_crt = devm_ioremap_resource(dev, res);
|
||||
+ if (IS_ERR(base_crt))
|
||||
+ return PTR_ERR(base_crt);
|
||||
+
|
||||
+ /* RTC base */
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aortc");
|
||||
+ base_rtc = devm_ioremap_resource(dev, res);
|
||||
+ if (IS_ERR(base_rtc))
|
||||
+ return PTR_ERR(base_rtc);
|
||||
+
|
||||
+ /* PWR regmap */
|
||||
+ regmap_pwr = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||
+ "amlogic,pwr-ctrl");
|
||||
+ if (IS_ERR(regmap_pwr)) {
|
||||
+ dev_err(dev, "failed to get PWR regmap\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
/* Reset Controller */
|
||||
rstc->base = base;
|
||||
rstc->data = gxbb_aoclk_reset;
|
||||
@@ -163,7 +202,7 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev)
|
||||
/*
|
||||
* Populate base address and register all clks
|
||||
*/
|
||||
- for (clkid = 0; clkid < gxbb_aoclk_onecell_data.num; clkid++) {
|
||||
+ for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) {
|
||||
gxbb_aoclk_gate[clkid]->reg = base;
|
||||
|
||||
ret = devm_clk_hw_register(dev,
|
||||
@@ -172,6 +211,14 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ /* Specific clocks */
|
||||
+ cec_32k_ao.crt_base = base_crt;
|
||||
+ cec_32k_ao.rtc_base = base_rtc;
|
||||
+ cec_32k_ao.pwr_regmap = regmap_pwr;
|
||||
+ ret = devm_clk_hw_register(dev, &cec_32k_ao.hw);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
|
||||
&gxbb_aoclk_onecell_data);
|
||||
}
|
||||
diff --git a/drivers/clk/meson/gxbb-aoclk.h b/drivers/clk/meson/gxbb-aoclk.h
|
||||
new file mode 100644
|
||||
index 0000000..5925a6b
|
||||
--- /dev/null
|
||||
+++ b/drivers/clk/meson/gxbb-aoclk.h
|
||||
@@ -0,0 +1,23 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 BayLibre, SAS
|
||||
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#ifndef __GXBB_AOCLKC_H
|
||||
+#define __GXBB_AOCLKC_H
|
||||
+
|
||||
+struct aoclk_cec_32k {
|
||||
+ struct clk_hw hw;
|
||||
+ void __iomem *crt_base;
|
||||
+ void __iomem *rtc_base;
|
||||
+ struct regmap *pwr_regmap;
|
||||
+ spinlock_t *lock;
|
||||
+};
|
||||
+
|
||||
+#define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw)
|
||||
+
|
||||
+extern const struct clk_ops meson_aoclk_cec_32k_ops;
|
||||
+
|
||||
+#endif /* __GXBB_AOCLKC_H */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
From c48872078789c6911e47e1c74d2024407c4daa8d Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Christ <s.christ@phytec.de>
|
||||
Date: Wed, 15 Feb 2017 17:19:09 +0100
|
||||
Subject: [PATCH 05/93] drm/fb-helper: implement ioctl FBIO_WAITFORVSYNC
|
||||
|
||||
Implement legacy framebuffer ioctl FBIO_WAITFORVSYNC in the generic
|
||||
framebuffer emulation driver. Legacy framebuffer users like non kms/drm
|
||||
based OpenGL(ES)/EGL implementations may require the ioctl to
|
||||
synchronize drawing or buffer flip for double buffering. It is tested on
|
||||
the i.MX6.
|
||||
|
||||
Code is based on
|
||||
https://github.com/Xilinx/linux-xlnx/blob/master/drivers/gpu/drm/xilinx/xilinx_drm_fb.c#L196
|
||||
|
||||
Signed-off-by: Stefan Christ <s.christ@phytec.de>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||
---
|
||||
drivers/gpu/drm/drm_fb_helper.c | 63 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/drm/drm_fb_helper.h | 12 +++++++-
|
||||
2 files changed, 74 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||
index c6de87a..15ee964 100644
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -1240,6 +1240,69 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
|
||||
EXPORT_SYMBOL(drm_fb_helper_setcmap);
|
||||
|
||||
/**
|
||||
+ * drm_fb_helper_ioctl - legacy ioctl implementation
|
||||
+ * @info: fbdev registered by the helper
|
||||
+ * @cmd: ioctl command
|
||||
+ * @arg: ioctl argument
|
||||
+ *
|
||||
+ * A helper to implement the standard fbdev ioctl. Only
|
||||
+ * FBIO_WAITFORVSYNC is implemented for now.
|
||||
+ */
|
||||
+int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
+ unsigned long arg)
|
||||
+{
|
||||
+ struct drm_fb_helper *fb_helper = info->par;
|
||||
+ struct drm_device *dev = fb_helper->dev;
|
||||
+ struct drm_mode_set *mode_set;
|
||||
+ struct drm_crtc *crtc;
|
||||
+ u32 karg;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ mutex_lock(&dev->mode_config.mutex);
|
||||
+ if (!drm_fb_helper_is_bound(fb_helper)) {
|
||||
+ ret = -EBUSY;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case FBIO_WAITFORVSYNC:
|
||||
+ if (get_user(karg, (__u32 __user *)arg)) {
|
||||
+ ret = -EFAULT;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
+ if (karg >= fb_helper->crtc_count) {
|
||||
+ ret = -EINVAL;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
+ mode_set = &fb_helper->crtc_info[karg].mode_set;
|
||||
+ crtc = mode_set->crtc;
|
||||
+
|
||||
+ /*
|
||||
+ * Only wait for a vblank event if the CRTC is
|
||||
+ * enabled, otherwise just don't do anythintg,
|
||||
+ * not even report an error.
|
||||
+ */
|
||||
+ ret = drm_crtc_vblank_get(crtc);
|
||||
+ if (!ret) {
|
||||
+ drm_crtc_wait_one_vblank(crtc);
|
||||
+ drm_crtc_vblank_put(crtc);
|
||||
+ }
|
||||
+
|
||||
+ ret = 0;
|
||||
+ goto unlock;
|
||||
+ default:
|
||||
+ ret = -ENOTTY;
|
||||
+ }
|
||||
+
|
||||
+unlock:
|
||||
+ mutex_unlock(&dev->mode_config.mutex);
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL(drm_fb_helper_ioctl);
|
||||
+
|
||||
+/**
|
||||
* drm_fb_helper_check_var - implementation for ->fb_check_var
|
||||
* @var: screeninfo to check
|
||||
* @info: fbdev registered by the helper
|
||||
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
|
||||
index 975deed..2891888 100644
|
||||
--- a/include/drm/drm_fb_helper.h
|
||||
+++ b/include/drm/drm_fb_helper.h
|
||||
@@ -230,7 +230,8 @@ struct drm_fb_helper {
|
||||
.fb_blank = drm_fb_helper_blank, \
|
||||
.fb_pan_display = drm_fb_helper_pan_display, \
|
||||
.fb_debug_enter = drm_fb_helper_debug_enter, \
|
||||
- .fb_debug_leave = drm_fb_helper_debug_leave
|
||||
+ .fb_debug_leave = drm_fb_helper_debug_leave, \
|
||||
+ .fb_ioctl = drm_fb_helper_ioctl
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
|
||||
@@ -286,6 +287,9 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
|
||||
|
||||
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
|
||||
|
||||
+int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
+ unsigned long arg);
|
||||
+
|
||||
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
|
||||
int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
|
||||
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
|
||||
@@ -377,6 +381,12 @@ static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
+ unsigned long arg)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
From 9fa0d1f1e56768773b58eb486bf59561b1cc6e18 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 23 Jun 2017 15:27:38 +0200
|
||||
Subject: [PATCH 06/79] ARM64: dts: meson-gx: Add PWR and CRT/RTC nodes and
|
||||
adresses
|
||||
|
||||
The AO 32KHz generation registers are split among multiple registers :
|
||||
- The CRT Control
|
||||
- The RTC Clock Control
|
||||
- The AO Domain PWR Control
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
index 436b875..4fd2926 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
@@ -358,11 +358,20 @@
|
||||
#size-cells = <2>;
|
||||
ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
|
||||
|
||||
+ pwr_AO: power-control@00c {
|
||||
+ compatible = "amlogic,gx-pwr-ctrl", "syscon";
|
||||
+ reg = <0x0 0x0000c 0x0 0x8>;
|
||||
+ };
|
||||
+
|
||||
clkc_AO: clock-controller@040 {
|
||||
compatible = "amlogic,gx-aoclkc", "amlogic,gxbb-aoclkc";
|
||||
- reg = <0x0 0x00040 0x0 0x4>;
|
||||
+ reg = <0x0 0x00040 0x0 0x4>,
|
||||
+ <0x0 0x00068 0x0 0x4>,
|
||||
+ <0x0 0x00094 0x0 0x8>;
|
||||
+ reg-names = "aoclk", "aocrt", "aortc";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
+ amlogic,pwr-ctrl = <&pwr_AO>;
|
||||
};
|
||||
|
||||
uart_AO: serial@4c0 {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
From e0c4b1d6b1ac850cb22d574bb485b3cc2ed36903 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 28 Feb 2017 15:23:14 +0100
|
||||
Subject: [PATCH 06/93] Disable DRM fbdev FBIO_WAITFORVSYNC to achieve full FPS
|
||||
|
||||
---
|
||||
drivers/gpu/drm/drm_fb_helper.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||
index 15ee964..7b739a8 100644
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -1266,6 +1266,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
|
||||
switch (cmd) {
|
||||
case FBIO_WAITFORVSYNC:
|
||||
+ goto unlock;
|
||||
if (get_user(karg, (__u32 __user *)arg)) {
|
||||
ret = -EFAULT;
|
||||
goto unlock;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
From abcaac146da294f437f1a8589b27aced142b4da5 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 30 May 2017 16:46:16 +0200
|
||||
Subject: [PATCH 07/79] ARM64: dts: meson-gx: Add AO CEC nodes
|
||||
|
||||
This patch adds the AO CEC node in all the HDMI enabled boards DTS.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi | 7 +++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 6 ++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts | 7 +++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 7 +++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts | 7 +++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts | 7 +++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts | 7 +++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 6 ++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts | 7 +++++++
|
||||
10 files changed, 67 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 a84e276..54718ee 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
|
||||
@@ -210,6 +210,13 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+&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>;
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
index 4fd2926..8901eeb 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
@@ -374,6 +374,12 @@
|
||||
amlogic,pwr-ctrl = <&pwr_AO>;
|
||||
};
|
||||
|
||||
+ cec_AO: cec@100 {
|
||||
+ compatible = "amlogic,meson-gx-ao-cec";
|
||||
+ reg = <0x0 0x00100 0x0 0x14>;
|
||||
+ interrupts = <GIC_SPI 199 IRQ_TYPE_EDGE_RISING>;
|
||||
+ };
|
||||
+
|
||||
uart_AO: serial@4c0 {
|
||||
compatible = "amlogic,meson-uart";
|
||||
reg = <0x0 0x004c0 0x0 0x14>;
|
||||
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 87198ea..9af807e 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
|
||||
@@ -171,6 +171,13 @@
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
+&cec_AO {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&ao_cec_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ hdmi-phandle = <&hdmi_tx>;
|
||||
+};
|
||||
+
|
||||
ðmac {
|
||||
status = "okay";
|
||||
pinctrl-0 = <ð_rmii_pins>;
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
index 3c6c0b7..3ed5c99 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
@@ -250,6 +250,13 @@
|
||||
clock-names = "clkin0";
|
||||
};
|
||||
|
||||
+&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>;
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index 86105a6..d760d93 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -97,6 +97,12 @@
|
||||
};
|
||||
};
|
||||
|
||||
+
|
||||
+&cec_AO {
|
||||
+ clocks = <&clkc_AO CLKID_AO_CEC_32K>;
|
||||
+ clock-names = "core";
|
||||
+};
|
||||
+
|
||||
ðmac {
|
||||
clocks = <&clkc CLKID_ETH>,
|
||||
<&clkc CLKID_FCLK_DIV2>,
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
index f9fbfda..49e19aa 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
@@ -86,6 +86,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&cec_AO {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&ao_cec_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ hdmi-phandle = <&hdmi_tx>;
|
||||
+};
|
||||
+
|
||||
/* P230 has exclusive choice between internal or external PHY */
|
||||
ðmac {
|
||||
pinctrl-0 = <ð_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 8873c05..55ec11a 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
|
||||
@@ -225,6 +225,13 @@
|
||||
clock-names = "clkin0";
|
||||
};
|
||||
|
||||
+&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>;
|
||||
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 db31e09..99a01ff 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
|
||||
@@ -60,6 +60,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&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>;
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
index d8e096d..3a1ccf5 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#include "meson-gx.dtsi"
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
+#include <dt-bindings/clock/gxbb-aoclkc.h>
|
||||
#include <dt-bindings/gpio/meson-gxl-gpio.h>
|
||||
#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
|
||||
|
||||
@@ -564,6 +565,11 @@
|
||||
compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu";
|
||||
};
|
||||
|
||||
+&cec_AO {
|
||||
+ clocks = <&clkc_AO CLKID_AO_CEC_32K>;
|
||||
+ clock-names = "core";
|
||||
+};
|
||||
+
|
||||
&hdmi_tx {
|
||||
compatible = "amlogic,meson-gxl-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
|
||||
resets = <&reset RESET_HDMITX_CAPB3>,
|
||||
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 11b0bf4..3a327dd 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
|
||||
@@ -191,6 +191,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&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>;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,442 +0,0 @@
|
|||
From bc80d5294931d37c19ef76d0a1bb144ad51b66f9 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 1 Feb 2017 11:45:04 +0100
|
||||
Subject: [PATCH 07/93] clk: meson-gxbb: Add MALI clocks and fix GP0 pll
|
||||
support
|
||||
|
||||
The Mali is clocked by two identical clock paths behind a glitch free mux
|
||||
to safely change frequency while running.
|
||||
|
||||
The optimal clock frequency is provided by the GP0 PLL, but unlike Meson8 the
|
||||
GXBB GP0 PLL needs some tweaking and need some SoC specific values to be set
|
||||
in order to setup the PLL.
|
||||
|
||||
Since these values will change for GXL and GXM, add an init table that will
|
||||
be changed for GXL or GXM.
|
||||
|
||||
For the MALI clocks, introduce them as Composite clocks to simplify the
|
||||
management.
|
||||
To handle composite clocks, a gxbb_composite structure is added to dynamically
|
||||
create the composite clock at probe and fill accordingly the DT table.
|
||||
|
||||
Finally the glitch free mux is added and other muxes and dividers are also
|
||||
grouped in initialization tables.
|
||||
---
|
||||
drivers/clk/meson/clk-pll.c | 34 ++++--
|
||||
drivers/clk/meson/clkc.h | 3 +
|
||||
drivers/clk/meson/gxbb.c | 211 +++++++++++++++++++++++++++++++++-
|
||||
drivers/clk/meson/gxbb.h | 7 +-
|
||||
include/dt-bindings/clock/gxbb-clkc.h | 4 +
|
||||
5 files changed, 245 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
|
||||
index 4adc1e8..b5ff81b 100644
|
||||
--- a/drivers/clk/meson/clk-pll.c
|
||||
+++ b/drivers/clk/meson/clk-pll.c
|
||||
@@ -132,6 +132,24 @@ static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
+static void meson_clk_pll_init(struct meson_clk_pll *pll)
|
||||
+{
|
||||
+ if (pll->init_count && pll->init_regs && pll->init_data) {
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < pll->init_count; ++i)
|
||||
+ writel(pll->init_data[i], pll->init_regs[i]);
|
||||
+ } else {
|
||||
+ struct parm *p;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ /* PLL reset */
|
||||
+ p = &pll->n;
|
||||
+ reg = readl(pll->base + p->reg_off);
|
||||
+ writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@@ -151,19 +169,18 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
if (!rate_set)
|
||||
return -EINVAL;
|
||||
|
||||
- /* PLL reset */
|
||||
- p = &pll->n;
|
||||
- reg = readl(pll->base + p->reg_off);
|
||||
- writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
|
||||
-
|
||||
- reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
|
||||
- writel(reg, pll->base + p->reg_off);
|
||||
+ meson_clk_pll_init(pll);
|
||||
|
||||
p = &pll->m;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
|
||||
writel(reg, pll->base + p->reg_off);
|
||||
|
||||
+ p = &pll->n;
|
||||
+ reg = readl(pll->base + p->reg_off);
|
||||
+ reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
|
||||
+ writel(reg, pll->base + p->reg_off);
|
||||
+
|
||||
p = &pll->od;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
|
||||
@@ -184,6 +201,9 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
}
|
||||
|
||||
p = &pll->n;
|
||||
+ reg = readl(pll->base + p->reg_off);
|
||||
+ writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off);
|
||||
+
|
||||
ret = meson_clk_pll_wait_lock(pll, p);
|
||||
if (ret) {
|
||||
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
|
||||
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
|
||||
index 9bb70e7..22a6335 100644
|
||||
--- a/drivers/clk/meson/clkc.h
|
||||
+++ b/drivers/clk/meson/clkc.h
|
||||
@@ -70,6 +70,9 @@ struct meson_clk_pll {
|
||||
struct parm frac;
|
||||
struct parm od;
|
||||
struct parm od2;
|
||||
+ void __iomem **init_regs;
|
||||
+ u32 *init_data;
|
||||
+ unsigned int init_count;
|
||||
const struct pll_rate_table *rate_table;
|
||||
unsigned int rate_count;
|
||||
spinlock_t *lock;
|
||||
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
|
||||
index 9d9af44..d1dac0f 100644
|
||||
--- a/drivers/clk/meson/gxbb.c
|
||||
+++ b/drivers/clk/meson/gxbb.c
|
||||
@@ -352,6 +352,20 @@
|
||||
},
|
||||
};
|
||||
|
||||
+static void __iomem *gxbb_gp0_init_regs[] = {
|
||||
+ (void *)HHI_GP0_PLL_CNTL,
|
||||
+ (void *)HHI_GP0_PLL_CNTL2,
|
||||
+ (void *)HHI_GP0_PLL_CNTL3,
|
||||
+ (void *)HHI_GP0_PLL_CNTL4,
|
||||
+};
|
||||
+
|
||||
+static u32 gxbb_gp0_init_data[] = {
|
||||
+ 0x6a000228,
|
||||
+ 0x69c80000,
|
||||
+ 0x0a5590c4,
|
||||
+ 0x0000500d,
|
||||
+};
|
||||
+
|
||||
static struct meson_clk_pll gxbb_gp0_pll = {
|
||||
.m = {
|
||||
.reg_off = HHI_GP0_PLL_CNTL,
|
||||
@@ -368,6 +382,9 @@
|
||||
.shift = 16,
|
||||
.width = 2,
|
||||
},
|
||||
+ .init_regs = gxbb_gp0_init_regs,
|
||||
+ .init_data = gxbb_gp0_init_data,
|
||||
+ .init_count = 4,
|
||||
.rate_table = gp0_pll_rate_table,
|
||||
.rate_count = ARRAY_SIZE(gp0_pll_rate_table),
|
||||
.lock = &clk_lock,
|
||||
@@ -550,6 +567,75 @@
|
||||
},
|
||||
};
|
||||
|
||||
+/* Mali Clock components */
|
||||
+static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
+const char *gxbb_mali_0_1_parent_names[] = {
|
||||
+ "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
|
||||
+ "fclk_div4", "fclk_div3", "fclk_div5"
|
||||
+};
|
||||
+
|
||||
+static struct clk_mux gxbb_mali_0_sel = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .mask = 0x3,
|
||||
+ .shift = 9,
|
||||
+ .table = mux_table_mali_0_1,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_divider gxbb_mali_0_div = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .shift = 0,
|
||||
+ .width = 7,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_gate gxbb_mali_0_en = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .bit_idx = 8,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_mux gxbb_mali_1_sel = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .mask = 0x3,
|
||||
+ .shift = 25,
|
||||
+ .table = mux_table_mali_0_1,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_divider gxbb_mali_1_div = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .shift = 16,
|
||||
+ .width = 7,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static struct clk_gate gxbb_mali_1_en = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .bit_idx = 24,
|
||||
+ .lock = &clk_lock,
|
||||
+};
|
||||
+
|
||||
+static u32 mux_table_mali[] = {0, 1};
|
||||
+const char *gxbb_mali_parent_names[] = {
|
||||
+ "mali_0", "mali_1"
|
||||
+};
|
||||
+
|
||||
+static struct clk_mux gxbb_mali = {
|
||||
+ .reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
+ .mask = 1,
|
||||
+ .shift = 31,
|
||||
+ .table = mux_table_mali,
|
||||
+ .lock = &clk_lock,
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "mali",
|
||||
+ .ops = &clk_mux_ops,
|
||||
+ .parent_names = gxbb_mali_parent_names,
|
||||
+ .num_parents = 2,
|
||||
+ .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
/* the mother of dragons^W gates */
|
||||
static struct clk_gate gxbb_clk81 = {
|
||||
.reg = (void *)HHI_MPEG_CLK_CNTL,
|
||||
@@ -754,6 +840,9 @@
|
||||
[CLKID_SD_EMMC_A] = &gxbb_emmc_a.hw,
|
||||
[CLKID_SD_EMMC_B] = &gxbb_emmc_b.hw,
|
||||
[CLKID_SD_EMMC_C] = &gxbb_emmc_c.hw,
|
||||
+ [CLKID_MALI] = &gxbb_mali.hw,
|
||||
+ /* This sentinel entry makes sure the table is large enough */
|
||||
+ [NR_CLKS] = NULL, /* Sentinel */
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
};
|
||||
@@ -856,6 +945,66 @@
|
||||
&gxbb_emmc_a,
|
||||
&gxbb_emmc_b,
|
||||
&gxbb_emmc_c,
|
||||
+ &gxbb_mali_0_en,
|
||||
+ &gxbb_mali_1_en,
|
||||
+};
|
||||
+
|
||||
+static struct clk_mux *gxbb_clk_muxes[] = {
|
||||
+ &gxbb_mpeg_clk_sel,
|
||||
+ &gxbb_mali_0_sel,
|
||||
+ &gxbb_mali_1_sel,
|
||||
+ &gxbb_mali,
|
||||
+};
|
||||
+
|
||||
+static struct clk_divider *gxbb_clk_dividers[] = {
|
||||
+ &gxbb_mpeg_clk_div,
|
||||
+ &gxbb_mali_0_div,
|
||||
+ &gxbb_mali_1_div,
|
||||
+};
|
||||
+
|
||||
+struct gxbb_composite_clk {
|
||||
+ unsigned int id;
|
||||
+ const char *name;
|
||||
+ const char * const *parent_names;
|
||||
+ int num_parents;
|
||||
+ struct clk_hw *mux_hw;
|
||||
+ const struct clk_ops *mux_ops;
|
||||
+ struct clk_hw *rate_hw;
|
||||
+ const struct clk_ops *rate_ops;
|
||||
+ struct clk_hw *gate_hw;
|
||||
+ const struct clk_ops *gate_ops;
|
||||
+ unsigned long flags;
|
||||
+};
|
||||
+
|
||||
+/* Convenient table to register the composite clocks */
|
||||
+
|
||||
+static struct gxbb_composite_clk gxbb_composite_clks[] = {
|
||||
+ {
|
||||
+ .id = CLKID_MALI_0,
|
||||
+ .name = "mali_0",
|
||||
+ .parent_names = gxbb_mali_0_1_parent_names,
|
||||
+ .num_parents = ARRAY_SIZE(gxbb_mali_0_1_parent_names),
|
||||
+ .mux_hw = &gxbb_mali_0_sel.hw,
|
||||
+ .mux_ops = &clk_mux_ops,
|
||||
+ .rate_hw = &gxbb_mali_0_div.hw,
|
||||
+ .rate_ops = &clk_divider_ops,
|
||||
+ .gate_hw = &gxbb_mali_0_en.hw,
|
||||
+ .gate_ops = &clk_gate_ops,
|
||||
+ .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
|
||||
+ },
|
||||
+ {
|
||||
+ .id = CLKID_MALI_1,
|
||||
+ .name = "mali_1",
|
||||
+ .parent_names = gxbb_mali_0_1_parent_names,
|
||||
+ .num_parents = ARRAY_SIZE(gxbb_mali_0_1_parent_names),
|
||||
+ .mux_hw = &gxbb_mali_1_sel.hw,
|
||||
+ .mux_ops = &clk_mux_ops,
|
||||
+ .rate_hw = &gxbb_mali_1_div.hw,
|
||||
+ .rate_ops = &clk_divider_ops,
|
||||
+ .gate_hw = &gxbb_mali_1_en.hw,
|
||||
+ .gate_ops = &clk_gate_ops,
|
||||
+ .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
|
||||
+ },
|
||||
};
|
||||
|
||||
static int gxbb_clkc_probe(struct platform_device *pdev)
|
||||
@@ -884,24 +1033,61 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
|
||||
/* Populate the base address for CPU clk */
|
||||
gxbb_cpu_clk.base = clk_base;
|
||||
|
||||
- /* Populate the base address for the MPEG clks */
|
||||
- gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg;
|
||||
- gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg;
|
||||
+ /* Populate base address for muxes */
|
||||
+ for (i = 0; i < ARRAY_SIZE(gxbb_clk_muxes); i++)
|
||||
+ gxbb_clk_muxes[i]->reg = clk_base +
|
||||
+ (u64)gxbb_clk_muxes[i]->reg;
|
||||
+
|
||||
+ /* Populate base address for dividers */
|
||||
+ for (i = 0; i < ARRAY_SIZE(gxbb_clk_dividers); i++)
|
||||
+ gxbb_clk_dividers[i]->reg = clk_base +
|
||||
+ (u64)gxbb_clk_dividers[i]->reg;
|
||||
|
||||
/* Populate base address for gates */
|
||||
for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++)
|
||||
gxbb_clk_gates[i]->reg = clk_base +
|
||||
(u64)gxbb_clk_gates[i]->reg;
|
||||
|
||||
+ /* Populate base for GP0 init table */
|
||||
+ for (i = 0; i < ARRAY_SIZE(gxbb_gp0_init_regs); ++i)
|
||||
+ gxbb_gp0_init_regs[i] = clk_base +
|
||||
+ (u64)gxbb_gp0_init_regs[i];
|
||||
+
|
||||
/*
|
||||
* register all clks
|
||||
*/
|
||||
for (clkid = 0; clkid < NR_CLKS; clkid++) {
|
||||
+ if (!gxbb_hw_onecell_data.hws[clkid])
|
||||
+ continue;
|
||||
+
|
||||
ret = devm_clk_hw_register(dev, gxbb_hw_onecell_data.hws[clkid]);
|
||||
if (ret)
|
||||
goto iounmap;
|
||||
}
|
||||
|
||||
+ /* Register Composite Clocks */
|
||||
+ for (i = 0 ; i < ARRAY_SIZE(gxbb_composite_clks); ++i) {
|
||||
+ struct gxbb_composite_clk *comp = &gxbb_composite_clks[i];
|
||||
+ struct clk_hw *hw;
|
||||
+
|
||||
+ hw = clk_hw_register_composite(dev, comp->name,
|
||||
+ comp->parent_names,
|
||||
+ comp->num_parents,
|
||||
+ comp->mux_hw, comp->mux_ops,
|
||||
+ comp->rate_hw, comp->rate_ops,
|
||||
+ comp->gate_hw, comp->gate_ops,
|
||||
+ comp->flags);
|
||||
+ if (IS_ERR(hw)) {
|
||||
+ ret = PTR_ERR(hw);
|
||||
+
|
||||
+ pr_err("%s: Failed to register composite clock %s\n",
|
||||
+ __func__, comp->name);
|
||||
+
|
||||
+ goto unregister_composites;
|
||||
+ }
|
||||
+ gxbb_hw_onecell_data.hws[comp->id] = hw;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Register CPU clk notifier
|
||||
*
|
||||
@@ -922,11 +1108,26 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
pr_err("%s: failed to register clock notifier for cpu_clk\n",
|
||||
__func__);
|
||||
- goto iounmap;
|
||||
+ goto unregister_composites;
|
||||
}
|
||||
|
||||
- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
|
||||
+ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
|
||||
&gxbb_hw_onecell_data);
|
||||
+ if (!ret)
|
||||
+ return ret;
|
||||
+
|
||||
+unregister_composites:
|
||||
+ for (i = 0 ; i < ARRAY_SIZE(gxbb_composite_clks); ++i) {
|
||||
+ struct gxbb_composite_clk *comp = &gxbb_composite_clks[i];
|
||||
+ struct clk *clk;
|
||||
+
|
||||
+ if (gxbb_hw_onecell_data.hws[comp->id]) {
|
||||
+ clk = gxbb_hw_onecell_data.hws[comp->id]->clk;
|
||||
+ clk_unregister_composite(clk);
|
||||
+ }
|
||||
+
|
||||
+ gxbb_hw_onecell_data.hws[comp->id] = NULL;
|
||||
+ }
|
||||
|
||||
iounmap:
|
||||
iounmap(clk_base);
|
||||
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
|
||||
index 0252939..f79ab57 100644
|
||||
--- a/drivers/clk/meson/gxbb.h
|
||||
+++ b/drivers/clk/meson/gxbb.h
|
||||
@@ -177,7 +177,7 @@
|
||||
/* CLKID_FCLK_DIV4 */
|
||||
#define CLKID_FCLK_DIV5 7
|
||||
#define CLKID_FCLK_DIV7 8
|
||||
-#define CLKID_GP0_PLL 9
|
||||
+/* CLKID_GP0_PLL */
|
||||
#define CLKID_MPEG_SEL 10
|
||||
#define CLKID_MPEG_DIV 11
|
||||
/* CLKID_CLK81 */
|
||||
@@ -265,8 +265,11 @@
|
||||
/* CLKID_SD_EMMC_A */
|
||||
/* CLKID_SD_EMMC_B */
|
||||
/* CLKID_SD_EMMC_C */
|
||||
+/* CLKID_MALI_0 */
|
||||
+/* CLKID_MALI_1 */
|
||||
+/* CLKID_MALI */
|
||||
|
||||
-#define NR_CLKS 97
|
||||
+#define NR_CLKS 100
|
||||
|
||||
/* include the CLKIDs that have been made part of the stable DT binding */
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
index baade6f..7bbc1d0 100644
|
||||
--- a/include/dt-bindings/clock/gxbb-clkc.h
|
||||
+++ b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
@@ -10,6 +10,7 @@
|
||||
#define CLKID_FCLK_DIV2 4
|
||||
#define CLKID_FCLK_DIV3 5
|
||||
#define CLKID_FCLK_DIV4 6
|
||||
+#define CLKID_GP0_PLL 9
|
||||
#define CLKID_CLK81 12
|
||||
#define CLKID_MPLL2 15
|
||||
#define CLKID_SPI 34
|
||||
@@ -24,5 +25,8 @@
|
||||
#define CLKID_SD_EMMC_A 94
|
||||
#define CLKID_SD_EMMC_B 95
|
||||
#define CLKID_SD_EMMC_C 96
|
||||
+#define CLKID_MALI_0 97
|
||||
+#define CLKID_MALI_1 98
|
||||
+#define CLKID_MALI 99
|
||||
|
||||
#endif /* __GXBB_CLKC_H */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
From 992ae3b904d0ace47dcf33f8cc117a17f1cff0c2 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 1 Feb 2017 11:45:40 +0100
|
||||
Subject: [PATCH 08/93] ARM64: dts: meson-gxbb: Add Mali node
|
||||
|
||||
Add the Mali-450 MP3 node for GXBB.
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 37 +++++++++++++++++++++++++++++
|
||||
1 file changed, 37 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index 2be29a3..bbb034d 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -476,6 +476,43 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&apb {
|
||||
+ mali: gpu@c0000 {
|
||||
+ compatible = "amlogic,meson-gxbb-mali", "arm,mali-450";
|
||||
+ reg = <0x0 0xc0000 0x0 0x40000>;
|
||||
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupt-names = "gp", "gpmmu", "pp", "pmu",
|
||||
+ "pp0", "ppmmu0", "pp1", "ppmmu1",
|
||||
+ "pp2", "ppmmu2";
|
||||
+ clocks = <&clkc CLKID_CLK81>, <&clkc CLKID_MALI>;
|
||||
+ clock-names = "bus", "core";
|
||||
+
|
||||
+ /*
|
||||
+ * Mali clocking is provided by two identical clock paths
|
||||
+ * MALI_0 and MALI_1 muxed to a single clock by a glitch
|
||||
+ * free mux to safely change frequency while running.
|
||||
+ */
|
||||
+ assigned-clocks = <&clkc CLKID_GP0_PLL>,
|
||||
+ <&clkc CLKID_MALI_0>,
|
||||
+ <&clkc CLKID_MALI>; /* Glitch free mux */
|
||||
+ assigned-clock-parents = <0>, /* Do Nothing */
|
||||
+ <&clkc CLKID_GP0_PLL>,
|
||||
+ <&clkc CLKID_MALI_0>;
|
||||
+ assigned-clock-rates = <744000000>,
|
||||
+ <744000000>,
|
||||
+ <0>; /* Do Nothing */
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&i2c_A {
|
||||
clocks = <&clkc CLKID_I2C>;
|
||||
};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
From ab3f6488b7ea751456324f57d27179599c151136 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 4 Dec 2015 10:47:35 +0000
|
||||
Subject: [PATCH 08/79] drm/bridge: dw_hdmi: add cec notifier support
|
||||
|
||||
Add CEC notifier support to the HDMI bridge driver, so that the CEC
|
||||
part of the IP can receive its physical address.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index ee788ca..5eff1e5 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -33,6 +33,8 @@
|
||||
#include <uapi/linux/media-bus-format.h>
|
||||
#include <uapi/linux/videodev2.h>
|
||||
|
||||
+#include <media/cec-notifier.h>
|
||||
+
|
||||
#include "dw-hdmi.h"
|
||||
#include "dw-hdmi-audio.h"
|
||||
|
||||
@@ -173,6 +175,8 @@ struct dw_hdmi {
|
||||
|
||||
unsigned int reg_shift;
|
||||
struct regmap *regm;
|
||||
+
|
||||
+ struct cec_notifier *cec_notifier;
|
||||
};
|
||||
|
||||
#define HDMI_IH_PHY_STAT0_RX_SENSE \
|
||||
@@ -1881,6 +1885,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
|
||||
hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
|
||||
drm_mode_connector_update_edid_property(connector, edid);
|
||||
+ cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
|
||||
ret = drm_add_edid_modes(connector, edid);
|
||||
/* Store the ELD */
|
||||
drm_edid_to_eld(connector, edid);
|
||||
@@ -2077,6 +2082,10 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
|
||||
dw_hdmi_update_phy_mask(hdmi);
|
||||
}
|
||||
mutex_unlock(&hdmi->mutex);
|
||||
+
|
||||
+ if (!rx_sense && !hpd)
|
||||
+ cec_notifier_set_phys_addr(hdmi->cec_notifier,
|
||||
+ CEC_PHYS_ADDR_INVALID);
|
||||
}
|
||||
|
||||
void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense)
|
||||
@@ -2376,6 +2385,12 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
+ hdmi->cec_notifier = cec_notifier_get(dev);
|
||||
+ if (!hdmi->cec_notifier) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_iahb;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
|
||||
* N and cts values before enabling phy
|
||||
@@ -2448,6 +2463,9 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
hdmi->ddc = NULL;
|
||||
}
|
||||
|
||||
+ if (hdmi->cec_notifier)
|
||||
+ cec_notifier_put(hdmi->cec_notifier);
|
||||
+
|
||||
clk_disable_unprepare(hdmi->iahb_clk);
|
||||
err_isfr:
|
||||
clk_disable_unprepare(hdmi->isfr_clk);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
From d7efc514cff47e958849fa122bc81839541b3dba Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 18 Jan 2017 10:33:04 +0100
|
||||
Subject: [PATCH 09/93] ARM64: dts: meson-gxbb: Add support for WeTek Hub and
|
||||
Play
|
||||
|
||||
Adds support for the WeTek Hub and Play2 boards.
|
||||
The Hub is an extremely small IPTv Set-Top-Box and the Play2 is a more
|
||||
traditionnal Satellite or Terrestrial and IPTv Set-Top-Box.
|
||||
|
||||
Both are based on the p200 Reference Design and out-of-tree support is
|
||||
based on OpenELEC kernel at [1].
|
||||
|
||||
[1] https://github.com/wetek-enigma/linux-amlogic
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/Makefile | 2 +
|
||||
.../boot/dts/amlogic/meson-gxbb-wetek-hub.dts | 66 +++++++++++++++
|
||||
.../boot/dts/amlogic/meson-gxbb-wetek-play2.dts | 94 ++++++++++++++++++++++
|
||||
3 files changed, 162 insertions(+)
|
||||
create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
|
||||
create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
|
||||
index 0d7bfbf..cc2e2dd 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/Makefile
|
||||
+++ b/arch/arm64/boot/dts/amlogic/Makefile
|
||||
@@ -5,6 +5,8 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p201.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-pro.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb
|
||||
+dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-hub.dtb
|
||||
+dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-play2.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb
|
||||
dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p231.dtb
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
|
||||
new file mode 100644
|
||||
index 0000000..56f8559
|
||||
--- /dev/null
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
|
||||
@@ -0,0 +1,66 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2016 BayLibre, Inc.
|
||||
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
+ *
|
||||
+ * This file is dual-licensed: you can use it either under the terms
|
||||
+ * of the GPL or the X11 license, at your option. Note that this dual
|
||||
+ * licensing only applies to this file, and not this project as a
|
||||
+ * whole.
|
||||
+ *
|
||||
+ * a) This library 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 library 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.
|
||||
+ *
|
||||
+ * Or, alternatively,
|
||||
+ *
|
||||
+ * b) Permission is hereby granted, free of charge, to any person
|
||||
+ * obtaining a copy of this software and associated documentation
|
||||
+ * files (the "Software"), to deal in the Software without
|
||||
+ * restriction, including without limitation the rights to use,
|
||||
+ * copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
+ * sell copies of the Software, and to permit persons to whom the
|
||||
+ * Software is furnished to do so, subject to the following
|
||||
+ * conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
+ * OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "meson-gxbb-p20x.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ compatible = "wetek,hub", "amlogic,meson-gxbb";
|
||||
+ model = "WeTek Hub";
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ system {
|
||||
+ label = "wetek-play:system-status";
|
||||
+ gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>;
|
||||
+ default-state = "on";
|
||||
+ panic-indicator;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ cvbs-connector {
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
|
||||
new file mode 100644
|
||||
index 0000000..ea79fdd
|
||||
--- /dev/null
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
|
||||
@@ -0,0 +1,94 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2016 BayLibre, Inc.
|
||||
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
+ *
|
||||
+ * This file is dual-licensed: you can use it either under the terms
|
||||
+ * of the GPL or the X11 license, at your option. Note that this dual
|
||||
+ * licensing only applies to this file, and not this project as a
|
||||
+ * whole.
|
||||
+ *
|
||||
+ * a) This library 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 library 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.
|
||||
+ *
|
||||
+ * Or, alternatively,
|
||||
+ *
|
||||
+ * b) Permission is hereby granted, free of charge, to any person
|
||||
+ * obtaining a copy of this software and associated documentation
|
||||
+ * files (the "Software"), to deal in the Software without
|
||||
+ * restriction, including without limitation the rights to use,
|
||||
+ * copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
+ * sell copies of the Software, and to permit persons to whom the
|
||||
+ * Software is furnished to do so, subject to the following
|
||||
+ * conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
+ * OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "meson-gxbb-p20x.dtsi"
|
||||
+#include <dt-bindings/input/input.h>
|
||||
+
|
||||
+/ {
|
||||
+ compatible = "wetek,play2", "amlogic,meson-gxbb";
|
||||
+ model = "WeTek Play 2";
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ system {
|
||||
+ label = "wetek-play:system-status";
|
||||
+ gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>;
|
||||
+ default-state = "on";
|
||||
+ panic-indicator;
|
||||
+ };
|
||||
+
|
||||
+ wifi {
|
||||
+ label = "wetek-play:wifi-status";
|
||||
+ gpios = <&gpio GPIODV_26 GPIO_ACTIVE_HIGH>;
|
||||
+ default-state = "off";
|
||||
+ };
|
||||
+
|
||||
+ ethernet {
|
||||
+ label = "wetek-play:ethernet-status";
|
||||
+ gpios = <&gpio GPIODV_27 GPIO_ACTIVE_HIGH>;
|
||||
+ default-state = "off";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ gpio-keys-polled {
|
||||
+ compatible = "gpio-keys-polled";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ poll-interval = <100>;
|
||||
+
|
||||
+ button@0 {
|
||||
+ label = "reset";
|
||||
+ linux,code = <KEY_RESTART>;
|
||||
+ gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&i2c_A {
|
||||
+ status = "okay";
|
||||
+ pinctrl-0 = <&i2c_a_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,724 @@
|
|||
From c3be57d7fef20314fffd81e74b70ea75e35a4d26 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 30 May 2017 15:50:21 +0200
|
||||
Subject: [PATCH 09/79] platform: Add Amlogic Meson AO CEC Controller driver
|
||||
|
||||
The Amlogic SoC embeds a standalone CEC controller, this patch adds a driver
|
||||
for such controller.
|
||||
The controller does not need HPD to be active, and could support up to max
|
||||
5 logical addresses, but only 1 is handled since the Suspend firmware can
|
||||
make use of this unique logical address to wake up the device.
|
||||
|
||||
The Suspend firmware configuration will be added in an other patchset.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/media/platform/Kconfig | 11 +
|
||||
drivers/media/platform/Makefile | 2 +
|
||||
drivers/media/platform/meson/Makefile | 1 +
|
||||
drivers/media/platform/meson/ao-cec.c | 653 ++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 667 insertions(+)
|
||||
create mode 100644 drivers/media/platform/meson/Makefile
|
||||
create mode 100644 drivers/media/platform/meson/ao-cec.c
|
||||
|
||||
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
|
||||
index 041cb80..857e068 100644
|
||||
--- a/drivers/media/platform/Kconfig
|
||||
+++ b/drivers/media/platform/Kconfig
|
||||
@@ -499,6 +499,17 @@ menuconfig CEC_PLATFORM_DRIVERS
|
||||
|
||||
if CEC_PLATFORM_DRIVERS
|
||||
|
||||
+config VIDEO_MESON_AO_CEC
|
||||
+ tristate "Amlogic Meson AO CEC driver"
|
||||
+ depends on ARCH_MESON || COMPILE_TEST
|
||||
+ select CEC_CORE
|
||||
+ select CEC_NOTIFIER
|
||||
+ ---help---
|
||||
+ This is a driver for Amlogic Meson SoCs AO CEC interface. It uses the
|
||||
+ generic CEC framework interface.
|
||||
+ CEC bus is present in the HDMI connector and enables communication
|
||||
+ between compatible devices.
|
||||
+
|
||||
config VIDEO_SAMSUNG_S5P_CEC
|
||||
tristate "Samsung S5P CEC driver"
|
||||
depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
|
||||
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
|
||||
index 63303d6..db15c59 100644
|
||||
--- a/drivers/media/platform/Makefile
|
||||
+++ b/drivers/media/platform/Makefile
|
||||
@@ -77,3 +77,5 @@ obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec/
|
||||
obj-$(CONFIG_VIDEO_MEDIATEK_MDP) += mtk-mdp/
|
||||
|
||||
obj-$(CONFIG_VIDEO_MEDIATEK_JPEG) += mtk-jpeg/
|
||||
+
|
||||
+obj-y += meson/
|
||||
diff --git a/drivers/media/platform/meson/Makefile b/drivers/media/platform/meson/Makefile
|
||||
new file mode 100644
|
||||
index 0000000..597beb8
|
||||
--- /dev/null
|
||||
+++ b/drivers/media/platform/meson/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+obj-$(CONFIG_VIDEO_MESON_AO_CEC) += ao-cec.o
|
||||
diff --git a/drivers/media/platform/meson/ao-cec.c b/drivers/media/platform/meson/ao-cec.c
|
||||
new file mode 100644
|
||||
index 0000000..26d7c3e8
|
||||
--- /dev/null
|
||||
+++ b/drivers/media/platform/meson/ao-cec.c
|
||||
@@ -0,0 +1,653 @@
|
||||
+/*
|
||||
+ * Driver for Amlogic Meson AO CEC Controller
|
||||
+ *
|
||||
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved
|
||||
+ * Copyright (C) 2017 BayLibre, SAS
|
||||
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/reset.h>
|
||||
+#include <media/cec.h>
|
||||
+#include <media/cec-notifier.h>
|
||||
+
|
||||
+/* CEC Registers */
|
||||
+
|
||||
+/*
|
||||
+ * [2:1] cntl_clk
|
||||
+ * - 0 = Disable clk (Power-off mode)
|
||||
+ * - 1 = Enable gated clock (Normal mode)
|
||||
+ * - 2 = Enable free-run clk (Debug mode)
|
||||
+ */
|
||||
+#define CEC_GEN_CNTL_REG 0x00
|
||||
+
|
||||
+#define CEC_GEN_CNTL_RESET BIT(0)
|
||||
+#define CEC_GEN_CNTL_CLK_DISABLE 0
|
||||
+#define CEC_GEN_CNTL_CLK_ENABLE 1
|
||||
+#define CEC_GEN_CNTL_CLK_ENABLE_DBG 2
|
||||
+#define CEC_GEN_CNTL_CLK_CTRL_MASK GENMASK(2, 1)
|
||||
+
|
||||
+/*
|
||||
+ * [7:0] cec_reg_addr
|
||||
+ * [15:8] cec_reg_wrdata
|
||||
+ * [16] cec_reg_wr
|
||||
+ * - 0 = Read
|
||||
+ * - 1 = Write
|
||||
+ * [23] bus free
|
||||
+ * [31:24] cec_reg_rddata
|
||||
+ */
|
||||
+#define CEC_RW_REG 0x04
|
||||
+
|
||||
+#define CEC_RW_ADDR GENMASK(7, 0)
|
||||
+#define CEC_RW_WR_DATA GENMASK(15, 8)
|
||||
+#define CEC_RW_WRITE_EN BIT(16)
|
||||
+#define CEC_RW_BUS_BUSY BIT(23)
|
||||
+#define CEC_RW_RD_DATA GENMASK(31, 24)
|
||||
+
|
||||
+/*
|
||||
+ * [1] tx intr
|
||||
+ * [2] rx intr
|
||||
+ */
|
||||
+#define CEC_INTR_MASKN_REG 0x08
|
||||
+#define CEC_INTR_CLR_REG 0x0c
|
||||
+#define CEC_INTR_STAT_REG 0x10
|
||||
+
|
||||
+#define CEC_INTR_TX BIT(1)
|
||||
+#define CEC_INTR_RX BIT(2)
|
||||
+
|
||||
+/* CEC Commands */
|
||||
+
|
||||
+#define CEC_TX_MSG_0_HEADER 0x00
|
||||
+#define CEC_TX_MSG_1_OPCODE 0x01
|
||||
+#define CEC_TX_MSG_2_OP1 0x02
|
||||
+#define CEC_TX_MSG_3_OP2 0x03
|
||||
+#define CEC_TX_MSG_4_OP3 0x04
|
||||
+#define CEC_TX_MSG_5_OP4 0x05
|
||||
+#define CEC_TX_MSG_6_OP5 0x06
|
||||
+#define CEC_TX_MSG_7_OP6 0x07
|
||||
+#define CEC_TX_MSG_8_OP7 0x08
|
||||
+#define CEC_TX_MSG_9_OP8 0x09
|
||||
+#define CEC_TX_MSG_A_OP9 0x0A
|
||||
+#define CEC_TX_MSG_B_OP10 0x0B
|
||||
+#define CEC_TX_MSG_C_OP11 0x0C
|
||||
+#define CEC_TX_MSG_D_OP12 0x0D
|
||||
+#define CEC_TX_MSG_E_OP13 0x0E
|
||||
+#define CEC_TX_MSG_F_OP14 0x0F
|
||||
+#define CEC_TX_MSG_LENGTH 0x10
|
||||
+#define CEC_TX_MSG_CMD 0x11
|
||||
+#define CEC_TX_WRITE_BUF 0x12
|
||||
+#define CEC_TX_CLEAR_BUF 0x13
|
||||
+#define CEC_RX_MSG_CMD 0x14
|
||||
+#define CEC_RX_CLEAR_BUF 0x15
|
||||
+#define CEC_LOGICAL_ADDR0 0x16
|
||||
+#define CEC_LOGICAL_ADDR1 0x17
|
||||
+#define CEC_LOGICAL_ADDR2 0x18
|
||||
+#define CEC_LOGICAL_ADDR3 0x19
|
||||
+#define CEC_LOGICAL_ADDR4 0x1A
|
||||
+#define CEC_CLOCK_DIV_H 0x1B
|
||||
+#define CEC_CLOCK_DIV_L 0x1C
|
||||
+#define CEC_QUIESCENT_25MS_BIT7_0 0x20
|
||||
+#define CEC_QUIESCENT_25MS_BIT11_8 0x21
|
||||
+#define CEC_STARTBITMINL2H_3MS5_BIT7_0 0x22
|
||||
+#define CEC_STARTBITMINL2H_3MS5_BIT8 0x23
|
||||
+#define CEC_STARTBITMAXL2H_3MS9_BIT7_0 0x24
|
||||
+#define CEC_STARTBITMAXL2H_3MS9_BIT8 0x25
|
||||
+#define CEC_STARTBITMINH_0MS6_BIT7_0 0x26
|
||||
+#define CEC_STARTBITMINH_0MS6_BIT8 0x27
|
||||
+#define CEC_STARTBITMAXH_1MS0_BIT7_0 0x28
|
||||
+#define CEC_STARTBITMAXH_1MS0_BIT8 0x29
|
||||
+#define CEC_STARTBITMINTOT_4MS3_BIT7_0 0x2A
|
||||
+#define CEC_STARTBITMINTOT_4MS3_BIT9_8 0x2B
|
||||
+#define CEC_STARTBITMAXTOT_4MS7_BIT7_0 0x2C
|
||||
+#define CEC_STARTBITMAXTOT_4MS7_BIT9_8 0x2D
|
||||
+#define CEC_LOGIC1MINL2H_0MS4_BIT7_0 0x2E
|
||||
+#define CEC_LOGIC1MINL2H_0MS4_BIT8 0x2F
|
||||
+#define CEC_LOGIC1MAXL2H_0MS8_BIT7_0 0x30
|
||||
+#define CEC_LOGIC1MAXL2H_0MS8_BIT8 0x31
|
||||
+#define CEC_LOGIC0MINL2H_1MS3_BIT7_0 0x32
|
||||
+#define CEC_LOGIC0MINL2H_1MS3_BIT8 0x33
|
||||
+#define CEC_LOGIC0MAXL2H_1MS7_BIT7_0 0x34
|
||||
+#define CEC_LOGIC0MAXL2H_1MS7_BIT8 0x35
|
||||
+#define CEC_LOGICMINTOTAL_2MS05_BIT7_0 0x36
|
||||
+#define CEC_LOGICMINTOTAL_2MS05_BIT9_8 0x37
|
||||
+#define CEC_LOGICMAXHIGH_2MS8_BIT7_0 0x38
|
||||
+#define CEC_LOGICMAXHIGH_2MS8_BIT8 0x39
|
||||
+#define CEC_LOGICERRLOW_3MS4_BIT7_0 0x3A
|
||||
+#define CEC_LOGICERRLOW_3MS4_BIT8 0x3B
|
||||
+#define CEC_NOMSMPPOINT_1MS05 0x3C
|
||||
+#define CEC_DELCNTR_LOGICERR 0x3E
|
||||
+#define CEC_TXTIME_17MS_BIT7_0 0x40
|
||||
+#define CEC_TXTIME_17MS_BIT10_8 0x41
|
||||
+#define CEC_TXTIME_2BIT_BIT7_0 0x42
|
||||
+#define CEC_TXTIME_2BIT_BIT10_8 0x43
|
||||
+#define CEC_TXTIME_4BIT_BIT7_0 0x44
|
||||
+#define CEC_TXTIME_4BIT_BIT10_8 0x45
|
||||
+#define CEC_STARTBITNOML2H_3MS7_BIT7_0 0x46
|
||||
+#define CEC_STARTBITNOML2H_3MS7_BIT8 0x47
|
||||
+#define CEC_STARTBITNOMH_0MS8_BIT7_0 0x48
|
||||
+#define CEC_STARTBITNOMH_0MS8_BIT8 0x49
|
||||
+#define CEC_LOGIC1NOML2H_0MS6_BIT7_0 0x4A
|
||||
+#define CEC_LOGIC1NOML2H_0MS6_BIT8 0x4B
|
||||
+#define CEC_LOGIC0NOML2H_1MS5_BIT7_0 0x4C
|
||||
+#define CEC_LOGIC0NOML2H_1MS5_BIT8 0x4D
|
||||
+#define CEC_LOGIC1NOMH_1MS8_BIT7_0 0x4E
|
||||
+#define CEC_LOGIC1NOMH_1MS8_BIT8 0x4F
|
||||
+#define CEC_LOGIC0NOMH_0MS9_BIT7_0 0x50
|
||||
+#define CEC_LOGIC0NOMH_0MS9_BIT8 0x51
|
||||
+#define CEC_LOGICERRLOW_3MS6_BIT7_0 0x52
|
||||
+#define CEC_LOGICERRLOW_3MS6_BIT8 0x53
|
||||
+#define CEC_CHKCONTENTION_0MS1 0x54
|
||||
+#define CEC_PREPARENXTBIT_0MS05_BIT7_0 0x56
|
||||
+#define CEC_PREPARENXTBIT_0MS05_BIT8 0x57
|
||||
+#define CEC_NOMSMPACKPOINT_0MS45 0x58
|
||||
+#define CEC_ACK0NOML2H_1MS5_BIT7_0 0x5A
|
||||
+#define CEC_ACK0NOML2H_1MS5_BIT8 0x5B
|
||||
+#define CEC_BUGFIX_DISABLE_0 0x60
|
||||
+#define CEC_BUGFIX_DISABLE_1 0x61
|
||||
+#define CEC_RX_MSG_0_HEADER 0x80
|
||||
+#define CEC_RX_MSG_1_OPCODE 0x81
|
||||
+#define CEC_RX_MSG_2_OP1 0x82
|
||||
+#define CEC_RX_MSG_3_OP2 0x83
|
||||
+#define CEC_RX_MSG_4_OP3 0x84
|
||||
+#define CEC_RX_MSG_5_OP4 0x85
|
||||
+#define CEC_RX_MSG_6_OP5 0x86
|
||||
+#define CEC_RX_MSG_7_OP6 0x87
|
||||
+#define CEC_RX_MSG_8_OP7 0x88
|
||||
+#define CEC_RX_MSG_9_OP8 0x89
|
||||
+#define CEC_RX_MSG_A_OP9 0x8A
|
||||
+#define CEC_RX_MSG_B_OP10 0x8B
|
||||
+#define CEC_RX_MSG_C_OP11 0x8C
|
||||
+#define CEC_RX_MSG_D_OP12 0x8D
|
||||
+#define CEC_RX_MSG_E_OP13 0x8E
|
||||
+#define CEC_RX_MSG_F_OP14 0x8F
|
||||
+#define CEC_RX_MSG_LENGTH 0x90
|
||||
+#define CEC_RX_MSG_STATUS 0x91
|
||||
+#define CEC_RX_NUM_MSG 0x92
|
||||
+#define CEC_TX_MSG_STATUS 0x93
|
||||
+#define CEC_TX_NUM_MSG 0x94
|
||||
+
|
||||
+
|
||||
+/* CEC_TX_MSG_CMD definition */
|
||||
+#define TX_NO_OP 0 /* No transaction */
|
||||
+#define TX_REQ_CURRENT 1 /* Transmit earliest message in buffer */
|
||||
+#define TX_ABORT 2 /* Abort transmitting earliest message */
|
||||
+#define TX_REQ_NEXT 3 /* Overwrite earliest msg, transmit next */
|
||||
+
|
||||
+/* tx_msg_status definition */
|
||||
+#define TX_IDLE 0 /* No transaction */
|
||||
+#define TX_BUSY 1 /* Transmitter is busy */
|
||||
+#define TX_DONE 2 /* Message successfully transmitted */
|
||||
+#define TX_ERROR 3 /* Message transmitted with error */
|
||||
+
|
||||
+/* rx_msg_cmd */
|
||||
+#define RX_NO_OP 0 /* No transaction */
|
||||
+#define RX_ACK_CURRENT 1 /* Read earliest message in buffer */
|
||||
+#define RX_DISABLE 2 /* Disable receiving latest message */
|
||||
+#define RX_ACK_NEXT 3 /* Clear earliest msg, read next */
|
||||
+
|
||||
+/* rx_msg_status */
|
||||
+#define RX_IDLE 0 /* No transaction */
|
||||
+#define RX_BUSY 1 /* Receiver is busy */
|
||||
+#define RX_DONE 2 /* Message has been received successfully */
|
||||
+#define RX_ERROR 3 /* Message has been received with error */
|
||||
+
|
||||
+/* RX_CLEAR_BUF options */
|
||||
+#define CLEAR_START 1
|
||||
+#define CLEAR_STOP 0
|
||||
+
|
||||
+/* CEC_LOGICAL_ADDRx options */
|
||||
+#define LOGICAL_ADDR_MASK 0xf
|
||||
+#define LOGICAL_ADDR_VALID BIT(4)
|
||||
+#define LOGICAL_ADDR_DISABLE 0
|
||||
+
|
||||
+#define CEC_CLK_RATE 32768
|
||||
+
|
||||
+struct meson_ao_cec_device {
|
||||
+ struct platform_device *pdev;
|
||||
+ void __iomem *base;
|
||||
+ struct clk *core;
|
||||
+ spinlock_t cec_reg_lock;
|
||||
+ struct cec_notifier *notify;
|
||||
+ struct cec_adapter *adap;
|
||||
+ struct cec_msg rx_msg;
|
||||
+};
|
||||
+
|
||||
+#define writel_bits_relaxed(mask, val, addr) \
|
||||
+ writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr)
|
||||
+
|
||||
+static inline void meson_ao_cec_wait_busy(struct meson_ao_cec_device *ao_cec)
|
||||
+{
|
||||
+ while (readl_relaxed(ao_cec->base + CEC_RW_REG) &
|
||||
+ CEC_RW_BUS_BUSY)
|
||||
+ ;
|
||||
+}
|
||||
+
|
||||
+static u8 meson_ao_cec_read(struct meson_ao_cec_device *ao_cec,
|
||||
+ unsigned long address)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ u32 reg = FIELD_PREP(CEC_RW_ADDR, address);
|
||||
+ u8 data;
|
||||
+
|
||||
+ spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
|
||||
+
|
||||
+ meson_ao_cec_wait_busy(ao_cec);
|
||||
+
|
||||
+ writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
|
||||
+
|
||||
+ meson_ao_cec_wait_busy(ao_cec);
|
||||
+
|
||||
+ data = FIELD_GET(CEC_RW_RD_DATA,
|
||||
+ readl_relaxed(ao_cec->base + CEC_RW_REG));
|
||||
+
|
||||
+ spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
|
||||
+
|
||||
+ return data;
|
||||
+}
|
||||
+
|
||||
+static void meson_ao_cec_write(struct meson_ao_cec_device *ao_cec,
|
||||
+ unsigned long address, u8 data)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ u32 reg = FIELD_PREP(CEC_RW_ADDR, address) |
|
||||
+ FIELD_PREP(CEC_RW_WR_DATA, data) |
|
||||
+ CEC_RW_WRITE_EN;
|
||||
+
|
||||
+ spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
|
||||
+
|
||||
+ meson_ao_cec_wait_busy(ao_cec);
|
||||
+
|
||||
+ writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
|
||||
+}
|
||||
+
|
||||
+static inline void meson_ao_cec_irq_setup(struct meson_ao_cec_device *ao_cec,
|
||||
+ bool enable)
|
||||
+{
|
||||
+ u32 cfg = CEC_INTR_TX | CEC_INTR_RX;
|
||||
+
|
||||
+ writel_bits_relaxed(cfg, enable ? cfg : 0,
|
||||
+ ao_cec->base + CEC_INTR_MASKN_REG);
|
||||
+}
|
||||
+
|
||||
+static inline void meson_ao_cec_clear(struct meson_ao_cec_device *ao_cec)
|
||||
+{
|
||||
+ meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_DISABLE);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 1);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 1);
|
||||
+
|
||||
+ udelay(100);
|
||||
+
|
||||
+ meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 0);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 0);
|
||||
+
|
||||
+ udelay(100);
|
||||
+
|
||||
+ meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP);
|
||||
+}
|
||||
+
|
||||
+static void meson_ao_cec_arbit_bit_time_set(struct meson_ao_cec_device *ao_cec,
|
||||
+ unsigned int bit_set,
|
||||
+ unsigned int time_set)
|
||||
+{
|
||||
+ switch (bit_set) {
|
||||
+ case 3:
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT7_0,
|
||||
+ time_set & 0xff);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT10_8,
|
||||
+ (time_set >> 8) & 0x7);
|
||||
+ break;
|
||||
+
|
||||
+ case 5:
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT7_0,
|
||||
+ time_set & 0xff);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT10_8,
|
||||
+ (time_set >> 8) & 0x7);
|
||||
+ break;
|
||||
+
|
||||
+ case 7:
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT7_0,
|
||||
+ time_set & 0xff);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT10_8,
|
||||
+ (time_set >> 8) & 0x7);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t meson_ao_cec_irq(int irq, void *data)
|
||||
+{
|
||||
+ struct meson_ao_cec_device *ao_cec = data;
|
||||
+ u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
|
||||
+
|
||||
+ if (stat)
|
||||
+ return IRQ_WAKE_THREAD;
|
||||
+
|
||||
+ return IRQ_NONE;
|
||||
+}
|
||||
+
|
||||
+static void meson_ao_cec_irq_tx(struct meson_ao_cec_device *ao_cec)
|
||||
+{
|
||||
+ unsigned long tx_status = 0;
|
||||
+ u8 stat = meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS);
|
||||
+
|
||||
+ switch (stat) {
|
||||
+ case TX_DONE:
|
||||
+ tx_status = CEC_TX_STATUS_OK;
|
||||
+ break;
|
||||
+
|
||||
+ case TX_BUSY:
|
||||
+ tx_status = CEC_TX_STATUS_ARB_LOST;
|
||||
+ break;
|
||||
+
|
||||
+ case TX_IDLE:
|
||||
+ tx_status = CEC_TX_STATUS_LOW_DRIVE;
|
||||
+ break;
|
||||
+
|
||||
+ case TX_ERROR:
|
||||
+ default:
|
||||
+ tx_status = CEC_TX_STATUS_NACK;
|
||||
+ }
|
||||
+
|
||||
+ /* Clear Interruption */
|
||||
+ writel_relaxed(CEC_INTR_TX, ao_cec->base + CEC_INTR_CLR_REG);
|
||||
+
|
||||
+ /* Stop TX */
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP);
|
||||
+
|
||||
+ cec_transmit_attempt_done(ao_cec->adap, tx_status);
|
||||
+}
|
||||
+
|
||||
+static void meson_ao_cec_irq_rx(struct meson_ao_cec_device *ao_cec)
|
||||
+{
|
||||
+ u8 stat = meson_ao_cec_read(ao_cec, CEC_RX_MSG_STATUS);
|
||||
+ int i;
|
||||
+
|
||||
+ /* RX Error */
|
||||
+ if (stat != RX_DONE ||
|
||||
+ meson_ao_cec_read(ao_cec, CEC_RX_NUM_MSG) != 1)
|
||||
+ goto rx_out;
|
||||
+
|
||||
+ ao_cec->rx_msg.len = meson_ao_cec_read(ao_cec, CEC_RX_MSG_LENGTH) + 1;
|
||||
+ if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
|
||||
+ ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;
|
||||
+
|
||||
+ for (i = 0; i < ao_cec->rx_msg.len; i++)
|
||||
+ ao_cec->rx_msg.msg[i] =
|
||||
+ meson_ao_cec_read(ao_cec, CEC_RX_MSG_0_HEADER + i);
|
||||
+
|
||||
+ cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);
|
||||
+
|
||||
+rx_out:
|
||||
+ /* Clear Interruption */
|
||||
+ writel_relaxed(CEC_INTR_RX, ao_cec->base + CEC_INTR_CLR_REG);
|
||||
+
|
||||
+ /* Ack RX message */
|
||||
+ meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_ACK_CURRENT);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP);
|
||||
+
|
||||
+ /* Clear RX buffer */
|
||||
+ meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_START);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_STOP);
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t meson_ao_cec_irq_thread(int irq, void *data)
|
||||
+{
|
||||
+ struct meson_ao_cec_device *ao_cec = data;
|
||||
+ u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
|
||||
+
|
||||
+ if (stat & CEC_INTR_TX)
|
||||
+ meson_ao_cec_irq_tx(ao_cec);
|
||||
+
|
||||
+ meson_ao_cec_irq_rx(ao_cec);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int meson_ao_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
|
||||
+{
|
||||
+ struct meson_ao_cec_device *ao_cec = adap->priv;
|
||||
+
|
||||
+ meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0, LOGICAL_ADDR_DISABLE);
|
||||
+
|
||||
+ meson_ao_cec_clear(ao_cec);
|
||||
+
|
||||
+ if (logical_addr == CEC_LOG_ADDR_INVALID)
|
||||
+ return 0;
|
||||
+
|
||||
+ meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
|
||||
+ logical_addr & LOGICAL_ADDR_MASK);
|
||||
+
|
||||
+ udelay(100);
|
||||
+
|
||||
+ meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
|
||||
+ (logical_addr & LOGICAL_ADDR_MASK) |
|
||||
+ LOGICAL_ADDR_VALID);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int meson_ao_cec_transmit(struct cec_adapter *adap, u8 attempts,
|
||||
+ u32 signal_free_time, struct cec_msg *msg)
|
||||
+{
|
||||
+ struct meson_ao_cec_device *ao_cec = adap->priv;
|
||||
+ u8 reg;
|
||||
+ int i;
|
||||
+
|
||||
+ reg = meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS);
|
||||
+ if (reg == TX_BUSY) {
|
||||
+ dev_err(&ao_cec->pdev->dev, "%s: busy TX\n", __func__);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < msg->len; i++)
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TX_MSG_0_HEADER + i,
|
||||
+ msg->msg[i]);
|
||||
+
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TX_MSG_LENGTH, msg->len - 1);
|
||||
+ meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_REQ_CURRENT);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int meson_ao_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
+{
|
||||
+ struct meson_ao_cec_device *ao_cec = adap->priv;
|
||||
+
|
||||
+ meson_ao_cec_irq_setup(ao_cec, false);
|
||||
+
|
||||
+ writel_bits_relaxed(CEC_GEN_CNTL_RESET, CEC_GEN_CNTL_RESET,
|
||||
+ ao_cec->base + CEC_GEN_CNTL_REG);
|
||||
+
|
||||
+ if (!enable)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Enable gated clock (Normal mode). */
|
||||
+ writel_bits_relaxed(CEC_GEN_CNTL_CLK_CTRL_MASK,
|
||||
+ FIELD_PREP(CEC_GEN_CNTL_CLK_CTRL_MASK,
|
||||
+ CEC_GEN_CNTL_CLK_ENABLE),
|
||||
+ ao_cec->base + CEC_GEN_CNTL_REG);
|
||||
+
|
||||
+ udelay(100);
|
||||
+
|
||||
+ /* Release Reset */
|
||||
+ writel_bits_relaxed(CEC_GEN_CNTL_RESET, 0,
|
||||
+ ao_cec->base + CEC_GEN_CNTL_REG);
|
||||
+
|
||||
+ /* Clear buffers */
|
||||
+ meson_ao_cec_clear(ao_cec);
|
||||
+
|
||||
+ /* CEC arbitration 3/5/7 bit time set. */
|
||||
+ meson_ao_cec_arbit_bit_time_set(ao_cec, 3, 0x118);
|
||||
+ meson_ao_cec_arbit_bit_time_set(ao_cec, 5, 0x000);
|
||||
+ meson_ao_cec_arbit_bit_time_set(ao_cec, 7, 0x2aa);
|
||||
+
|
||||
+ meson_ao_cec_irq_setup(ao_cec, true);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct cec_adap_ops meson_ao_cec_ops = {
|
||||
+ .adap_enable = meson_ao_cec_adap_enable,
|
||||
+ .adap_log_addr = meson_ao_cec_set_log_addr,
|
||||
+ .adap_transmit = meson_ao_cec_transmit,
|
||||
+};
|
||||
+
|
||||
+static int meson_ao_cec_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct meson_ao_cec_device *ao_cec;
|
||||
+ struct platform_device *hdmi_dev;
|
||||
+ struct device_node *np;
|
||||
+ struct resource *res;
|
||||
+ int ret, irq;
|
||||
+
|
||||
+ np = of_parse_phandle(pdev->dev.of_node, "hdmi-phandle", 0);
|
||||
+ if (!np) {
|
||||
+ dev_err(&pdev->dev, "Failed to find hdmi node\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ hdmi_dev = of_find_device_by_node(np);
|
||||
+ if (hdmi_dev == NULL)
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
+ ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
|
||||
+ if (!ao_cec)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ spin_lock_init(&ao_cec->cec_reg_lock);
|
||||
+
|
||||
+ ao_cec->notify = cec_notifier_get(&hdmi_dev->dev);
|
||||
+ if (!ao_cec->notify)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
|
||||
+ "meson_ao_cec",
|
||||
+ CEC_CAP_LOG_ADDRS |
|
||||
+ CEC_CAP_TRANSMIT |
|
||||
+ CEC_CAP_RC,
|
||||
+ 1); /* Use 1 for now */
|
||||
+ if (IS_ERR(ao_cec->adap)) {
|
||||
+ ret = PTR_ERR(ao_cec->adap);
|
||||
+ goto out_probe_notify;
|
||||
+ }
|
||||
+
|
||||
+ ao_cec->adap->owner = THIS_MODULE;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ ao_cec->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(ao_cec->base)) {
|
||||
+ ret = PTR_ERR(ao_cec->base);
|
||||
+ goto out_probe_adapter;
|
||||
+ }
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev, irq,
|
||||
+ meson_ao_cec_irq,
|
||||
+ meson_ao_cec_irq_thread,
|
||||
+ 0, NULL, ao_cec);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "irq request failed\n");
|
||||
+ goto out_probe_adapter;
|
||||
+ }
|
||||
+
|
||||
+ ao_cec->core = devm_clk_get(&pdev->dev, "core");
|
||||
+ if (IS_ERR(ao_cec->core)) {
|
||||
+ dev_err(&pdev->dev, "core clock request failed\n");
|
||||
+ ret = PTR_ERR(ao_cec->core);
|
||||
+ goto out_probe_adapter;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(ao_cec->core);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "core clock enable failed\n");
|
||||
+ goto out_probe_adapter;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "core clock set rate failed\n");
|
||||
+ goto out_probe_clk;
|
||||
+ }
|
||||
+
|
||||
+ device_reset_optional(&pdev->dev);
|
||||
+
|
||||
+ ao_cec->pdev = pdev;
|
||||
+ platform_set_drvdata(pdev, ao_cec);
|
||||
+
|
||||
+ ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
|
||||
+ if (ret < 0) {
|
||||
+ cec_notifier_put(ao_cec->notify);
|
||||
+ goto out_probe_clk;
|
||||
+ }
|
||||
+
|
||||
+ /* Setup Hardware */
|
||||
+ writel_relaxed(CEC_GEN_CNTL_RESET,
|
||||
+ ao_cec->base + CEC_GEN_CNTL_REG);
|
||||
+
|
||||
+ cec_register_cec_notifier(ao_cec->adap, ao_cec->notify);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+out_probe_clk:
|
||||
+ clk_disable_unprepare(ao_cec->core);
|
||||
+
|
||||
+out_probe_adapter:
|
||||
+ cec_delete_adapter(ao_cec->adap);
|
||||
+
|
||||
+out_probe_notify:
|
||||
+ cec_notifier_put(ao_cec->notify);
|
||||
+
|
||||
+ dev_err(&pdev->dev, "CEC controller registration failed\n");
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int meson_ao_cec_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ clk_disable_unprepare(ao_cec->core);
|
||||
+
|
||||
+ cec_unregister_adapter(ao_cec->adap);
|
||||
+
|
||||
+ cec_notifier_put(ao_cec->notify);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id meson_ao_cec_of_match[] = {
|
||||
+ { .compatible = "amlogic,meson-gx-ao-cec", },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match);
|
||||
+
|
||||
+static struct platform_driver meson_ao_cec_driver = {
|
||||
+ .probe = meson_ao_cec_probe,
|
||||
+ .remove = meson_ao_cec_remove,
|
||||
+ .driver = {
|
||||
+ .name = "meson-ao-cec",
|
||||
+ .of_match_table = of_match_ptr(meson_ao_cec_of_match),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(meson_ao_cec_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Meson AO CEC Controller driver");
|
||||
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
From 6fd7485ab55a72cd7bce9e4f69dc95a6fe06e685 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 24 May 2017 09:41:12 +0200
|
||||
Subject: [PATCH 10/79] ARM64: dts: meson-gxbb: Add CEC pins nodes
|
||||
|
||||
Add the AO and EE domain CEC pins nodes for the Amlogic Meson GXBB SoCs.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index d760d93..daa49ae 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -255,6 +255,20 @@
|
||||
function = "spdif_out_ao";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ ao_cec_pins: ao_cec {
|
||||
+ mux {
|
||||
+ groups = "ao_cec";
|
||||
+ function = "cec_ao";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ ee_cec_pins: ee_cec {
|
||||
+ mux {
|
||||
+ groups = "ee_cec";
|
||||
+ function = "cec_ao";
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
};
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,639 +0,0 @@
|
|||
From b53f55423fe344ecdd5bc8b2437170013a0a46e4 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Mon, 28 Nov 2016 17:59:08 +0200
|
||||
Subject: [PATCH 10/93] drm: bridge: Link encoder and bridge in core code
|
||||
|
||||
Instead of linking encoders and bridges in every driver (and getting it
|
||||
wrong half of the time, as many drivers forget to set the drm_bridge
|
||||
encoder pointer), do so in core code. The drm_bridge_attach() function
|
||||
needs the encoder and optional previous bridge to perform that task,
|
||||
update all the callers.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Acked-by: Stefan Agner <stefan@agner.ch> # For DCU
|
||||
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com> # For atmel-hlcdc
|
||||
Acked-by: Vincent Abriou <vincent.abriou@st.com> # For STI
|
||||
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> # For sun4i
|
||||
Acked-by: Xinliang Liu <z.liuxinliang@hisilicon.com> # For hisilicon
|
||||
Acked-by: Jyri Sarha <jsarha@ti.com> # For tilcdc
|
||||
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1481709550-29226-4-git-send-email-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/arc/arcpgu_hdmi.c | 5 +--
|
||||
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 4 +-
|
||||
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 +-
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 3 +-
|
||||
drivers/gpu/drm/drm_bridge.c | 46 ++++++++++++++++------
|
||||
drivers/gpu/drm/drm_simple_kms_helper.c | 4 +-
|
||||
drivers/gpu/drm/exynos/exynos_dp.c | 5 +--
|
||||
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 6 +--
|
||||
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 5 +--
|
||||
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 5 +--
|
||||
drivers/gpu/drm/imx/imx-ldb.c | 6 +--
|
||||
drivers/gpu/drm/imx/parallel-display.c | 4 +-
|
||||
drivers/gpu/drm/mediatek/mtk_dpi.c | 8 ++--
|
||||
drivers/gpu/drm/mediatek/mtk_dsi.c | 24 ++---------
|
||||
drivers/gpu/drm/mediatek/mtk_hdmi.c | 11 +++---
|
||||
drivers/gpu/drm/msm/dsi/dsi_manager.c | 17 +++++---
|
||||
drivers/gpu/drm/msm/edp/edp_bridge.c | 2 +-
|
||||
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 2 +-
|
||||
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 5 +--
|
||||
drivers/gpu/drm/sti/sti_dvo.c | 3 +-
|
||||
drivers/gpu/drm/sti/sti_hda.c | 3 +-
|
||||
drivers/gpu/drm/sti/sti_hdmi.c | 3 +-
|
||||
drivers/gpu/drm/sun4i/sun4i_rgb.c | 13 +++---
|
||||
drivers/gpu/drm/tilcdc/tilcdc_external.c | 4 +-
|
||||
include/drm/drm_bridge.h | 3 +-
|
||||
25 files changed, 85 insertions(+), 110 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
|
||||
index b69c66b..0ce7f39 100644
|
||||
--- a/drivers/gpu/drm/arc/arcpgu_hdmi.c
|
||||
+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
|
||||
@@ -47,10 +47,7 @@ int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
|
||||
return ret;
|
||||
|
||||
/* Link drm_bridge to encoder */
|
||||
- bridge->encoder = encoder;
|
||||
- encoder->bridge = bridge;
|
||||
-
|
||||
- ret = drm_bridge_attach(drm, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret)
|
||||
drm_encoder_cleanup(encoder);
|
||||
|
||||
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
|
||||
index 6119b50..e7799b6 100644
|
||||
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
|
||||
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
|
||||
@@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
|
||||
of_node_put(np);
|
||||
|
||||
if (bridge) {
|
||||
- output->encoder.bridge = bridge;
|
||||
- bridge->encoder = &output->encoder;
|
||||
- ret = drm_bridge_attach(dev, bridge);
|
||||
+ ret = drm_bridge_attach(&output->encoder, bridge, NULL);
|
||||
if (!ret)
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
|
||||
index 18eefdc..dfae80f 100644
|
||||
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
|
||||
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
|
||||
@@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
|
||||
|
||||
dp->bridge = bridge;
|
||||
|
||||
- dp->encoder->bridge = bridge;
|
||||
bridge->driver_private = dp;
|
||||
- bridge->encoder = dp->encoder;
|
||||
bridge->funcs = &analogix_dp_bridge_funcs;
|
||||
|
||||
- ret = drm_bridge_attach(drm_dev, bridge);
|
||||
+ ret = drm_bridge_attach(dp->encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to attach drm bridge\n");
|
||||
return -EINVAL;
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 235ce7d..f5009ae 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
hdmi->bridge = bridge;
|
||||
bridge->driver_private = hdmi;
|
||||
bridge->funcs = &dw_hdmi_bridge_funcs;
|
||||
- ret = drm_bridge_attach(drm, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize bridge with drm\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- encoder->bridge = bridge;
|
||||
hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
drm_connector_helper_add(&hdmi->connector,
|
||||
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
|
||||
index 0ee052b..850bd65 100644
|
||||
--- a/drivers/gpu/drm/drm_bridge.c
|
||||
+++ b/drivers/gpu/drm/drm_bridge.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
+#include <drm/drm_encoder.h>
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
@@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
|
||||
EXPORT_SYMBOL(drm_bridge_remove);
|
||||
|
||||
/**
|
||||
- * drm_bridge_attach - associate given bridge to our DRM device
|
||||
+ * drm_bridge_attach - attach the bridge to an encoder's chain
|
||||
*
|
||||
- * @dev: DRM device
|
||||
- * @bridge: bridge control structure
|
||||
+ * @encoder: DRM encoder
|
||||
+ * @bridge: bridge to attach
|
||||
+ * @previous: previous bridge in the chain (optional)
|
||||
*
|
||||
- * Called by a kms driver to link one of our encoder/bridge to the given
|
||||
- * bridge.
|
||||
+ * Called by a kms driver to link the bridge to an encoder's chain. The previous
|
||||
+ * argument specifies the previous bridge in the chain. If NULL, the bridge is
|
||||
+ * linked directly at the encoder's output. Otherwise it is linked at the
|
||||
+ * previous bridge's output.
|
||||
*
|
||||
- * Note that setting up links between the bridge and our encoder/bridge
|
||||
- * objects needs to be handled by the kms driver itself.
|
||||
+ * If non-NULL the previous bridge must be already attached by a call to this
|
||||
+ * function.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure
|
||||
*/
|
||||
-int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
|
||||
+int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
|
||||
+ struct drm_bridge *previous)
|
||||
{
|
||||
- if (!dev || !bridge)
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!encoder || !bridge)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (previous && (!previous->dev || previous->encoder != encoder))
|
||||
return -EINVAL;
|
||||
|
||||
if (bridge->dev)
|
||||
return -EBUSY;
|
||||
|
||||
- bridge->dev = dev;
|
||||
+ bridge->dev = encoder->dev;
|
||||
+ bridge->encoder = encoder;
|
||||
+
|
||||
+ if (bridge->funcs->attach) {
|
||||
+ ret = bridge->funcs->attach(bridge);
|
||||
+ if (ret < 0) {
|
||||
+ bridge->dev = NULL;
|
||||
+ bridge->encoder = NULL;
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (bridge->funcs->attach)
|
||||
- return bridge->funcs->attach(bridge);
|
||||
+ if (previous)
|
||||
+ previous->next = bridge;
|
||||
+ else
|
||||
+ encoder->bridge = bridge;
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
index 7bae08c..ba7be61 100644
|
||||
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
@@ -182,9 +182,7 @@ static void drm_simple_kms_plane_cleanup_fb(struct drm_plane *plane,
|
||||
int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_bridge *bridge)
|
||||
{
|
||||
- bridge->encoder = &pipe->encoder;
|
||||
- pipe->encoder.bridge = bridge;
|
||||
- return drm_bridge_attach(pipe->encoder.dev, bridge);
|
||||
+ return drm_bridge_attach(&pipe->encoder, bridge, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
|
||||
|
||||
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
|
||||
index 528229f..1ef0be3 100644
|
||||
--- a/drivers/gpu/drm/exynos/exynos_dp.c
|
||||
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
|
||||
@@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct exynos_dp_device *dp = to_dp(plat_data);
|
||||
- struct drm_encoder *encoder = &dp->encoder;
|
||||
int ret;
|
||||
|
||||
drm_connector_register(connector);
|
||||
@@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
|
||||
|
||||
/* Pre-empt DP connector creation if there's a bridge */
|
||||
if (dp->ptn_bridge) {
|
||||
- bridge->next = dp->ptn_bridge;
|
||||
- dp->ptn_bridge->encoder = encoder;
|
||||
- ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
|
||||
+ ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to attach bridge to drm\n");
|
||||
bridge->next = NULL;
|
||||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
|
||||
index e07cb1f..812e2ec 100644
|
||||
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
|
||||
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
|
||||
@@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
|
||||
}
|
||||
|
||||
bridge = of_drm_find_bridge(dsi->bridge_node);
|
||||
- if (bridge) {
|
||||
- encoder->bridge = bridge;
|
||||
- drm_bridge_attach(drm_dev, bridge);
|
||||
- }
|
||||
+ if (bridge)
|
||||
+ drm_bridge_attach(encoder, bridge, NULL);
|
||||
|
||||
return mipi_dsi_host_register(&dsi->dsi_host);
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
|
||||
index 05a8ee1..c365145 100644
|
||||
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
|
||||
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
|
||||
@@ -160,10 +160,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
|
||||
if (!bridge)
|
||||
return -ENODEV;
|
||||
|
||||
- fsl_dev->encoder.bridge = bridge;
|
||||
- bridge->encoder = &fsl_dev->encoder;
|
||||
-
|
||||
- return drm_bridge_attach(fsl_dev->drm, bridge);
|
||||
+ return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
|
||||
}
|
||||
|
||||
int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
|
||||
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
|
||||
index 998452a..1737e98 100644
|
||||
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
|
||||
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
|
||||
@@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
|
||||
int ret;
|
||||
|
||||
/* associate the bridge to dsi encoder */
|
||||
- encoder->bridge = bridge;
|
||||
- bridge->encoder = encoder;
|
||||
-
|
||||
- ret = drm_bridge_attach(dev, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to attach external bridge\n");
|
||||
return ret;
|
||||
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
|
||||
index 516d064..ec49ea3 100644
|
||||
--- a/drivers/gpu/drm/imx/imx-ldb.c
|
||||
+++ b/drivers/gpu/drm/imx/imx-ldb.c
|
||||
@@ -454,10 +454,8 @@ static int imx_ldb_register(struct drm_device *drm,
|
||||
DRM_MODE_ENCODER_LVDS, NULL);
|
||||
|
||||
if (imx_ldb_ch->bridge) {
|
||||
- imx_ldb_ch->bridge->encoder = encoder;
|
||||
-
|
||||
- imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
|
||||
- ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
|
||||
+ ret = drm_bridge_attach(&imx_ldb_ch->encoder,
|
||||
+ imx_ldb_ch->bridge, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize bridge with drm\n");
|
||||
return ret;
|
||||
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
|
||||
index 8582a83..51d9f73 100644
|
||||
--- a/drivers/gpu/drm/imx/parallel-display.c
|
||||
+++ b/drivers/gpu/drm/imx/parallel-display.c
|
||||
@@ -191,9 +191,7 @@ static int imx_pd_register(struct drm_device *drm,
|
||||
drm_panel_attach(imxpd->panel, &imxpd->connector);
|
||||
|
||||
if (imxpd->bridge) {
|
||||
- imxpd->bridge->encoder = encoder;
|
||||
- encoder->bridge = imxpd->bridge;
|
||||
- ret = drm_bridge_attach(drm, imxpd->bridge);
|
||||
+ ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(imxpd->dev, "failed to attach bridge: %d\n",
|
||||
ret);
|
||||
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
|
||||
index 90fb831..3bd3bd6 100644
|
||||
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
|
||||
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
|
||||
@@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
|
||||
struct mtk_dpi {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
struct drm_encoder encoder;
|
||||
+ struct drm_bridge *bridge;
|
||||
void __iomem *regs;
|
||||
struct device *dev;
|
||||
struct clk *engine_clk;
|
||||
@@ -620,8 +621,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
|
||||
/* Currently DPI0 is fixed to be driven by OVL1 */
|
||||
dpi->encoder.possible_crtcs = BIT(1);
|
||||
|
||||
- dpi->encoder.bridge->encoder = &dpi->encoder;
|
||||
- ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
|
||||
+ ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to attach bridge: %d\n", ret);
|
||||
goto err_cleanup;
|
||||
@@ -718,9 +718,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
|
||||
|
||||
dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
|
||||
|
||||
- dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
|
||||
+ dpi->bridge = of_drm_find_bridge(bridge_node);
|
||||
of_node_put(bridge_node);
|
||||
- if (!dpi->encoder.bridge)
|
||||
+ if (!dpi->bridge)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
|
||||
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
|
||||
index 2c42f90..dd71cbb 100644
|
||||
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
|
||||
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
|
||||
@@ -622,26 +622,6 @@ static int mtk_dsi_connector_get_modes(struct drm_connector *connector)
|
||||
.get_modes = mtk_dsi_connector_get_modes,
|
||||
};
|
||||
|
||||
-static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
|
||||
- struct drm_encoder *encoder)
|
||||
-{
|
||||
- int ret;
|
||||
-
|
||||
- if (!bridge)
|
||||
- return -ENOENT;
|
||||
-
|
||||
- encoder->bridge = bridge;
|
||||
- bridge->encoder = encoder;
|
||||
- ret = drm_bridge_attach(encoder->dev, bridge);
|
||||
- if (ret) {
|
||||
- DRM_ERROR("Failed to attach bridge to drm\n");
|
||||
- encoder->bridge = NULL;
|
||||
- bridge->encoder = NULL;
|
||||
- }
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
|
||||
{
|
||||
int ret;
|
||||
@@ -692,8 +672,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
|
||||
dsi->encoder.possible_crtcs = 1;
|
||||
|
||||
/* If there's a bridge, attach to it and let it create the connector */
|
||||
- ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
|
||||
+ ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
|
||||
if (ret) {
|
||||
+ DRM_ERROR("Failed to attach bridge to drm\n");
|
||||
+
|
||||
/* Otherwise create our own connector and attach to a panel */
|
||||
ret = mtk_dsi_create_connector(drm, dsi);
|
||||
if (ret)
|
||||
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
|
||||
index 0e8c4d9..c262512 100644
|
||||
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
|
||||
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
|
||||
@@ -149,6 +149,7 @@ struct hdmi_audio_param {
|
||||
|
||||
struct mtk_hdmi {
|
||||
struct drm_bridge bridge;
|
||||
+ struct drm_bridge *next_bridge;
|
||||
struct drm_connector conn;
|
||||
struct device *dev;
|
||||
struct phy *phy;
|
||||
@@ -1314,9 +1315,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- if (bridge->next) {
|
||||
- bridge->next->encoder = bridge->encoder;
|
||||
- ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
|
||||
+ if (hdmi->next_bridge) {
|
||||
+ ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
|
||||
+ bridge);
|
||||
if (ret) {
|
||||
dev_err(hdmi->dev,
|
||||
"Failed to attach external bridge: %d\n", ret);
|
||||
@@ -1510,8 +1511,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
|
||||
of_node_put(ep);
|
||||
|
||||
if (!of_device_is_compatible(remote, "hdmi-connector")) {
|
||||
- hdmi->bridge.next = of_drm_find_bridge(remote);
|
||||
- if (!hdmi->bridge.next) {
|
||||
+ hdmi->next_bridge = of_drm_find_bridge(remote);
|
||||
+ if (!hdmi->next_bridge) {
|
||||
dev_err(dev, "Waiting for external bridge\n");
|
||||
of_node_put(remote);
|
||||
return -EPROBE_DEFER;
|
||||
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
|
||||
index c8d1f19..2bd8dad 100644
|
||||
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
|
||||
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
|
||||
@@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
|
||||
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
|
||||
struct drm_bridge *bridge = NULL;
|
||||
struct dsi_bridge *dsi_bridge;
|
||||
+ struct drm_encoder *encoder;
|
||||
int ret;
|
||||
|
||||
dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
|
||||
@@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
|
||||
|
||||
dsi_bridge->id = id;
|
||||
|
||||
+ /*
|
||||
+ * HACK: we may not know the external DSI bridge device's mode
|
||||
+ * flags here. We'll get to know them only when the device
|
||||
+ * attaches to the dsi host. For now, assume the bridge supports
|
||||
+ * DSI video mode
|
||||
+ */
|
||||
+ encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
|
||||
+
|
||||
bridge = &dsi_bridge->base;
|
||||
bridge->funcs = &dsi_mgr_bridge_funcs;
|
||||
|
||||
- ret = drm_bridge_attach(msm_dsi->dev, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
@@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
|
||||
encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
|
||||
|
||||
/* link the internal dsi bridge to the external bridge */
|
||||
- int_bridge->next = ext_bridge;
|
||||
- /* set the external bridge's encoder as dsi's encoder */
|
||||
- ext_bridge->encoder = encoder;
|
||||
-
|
||||
- drm_bridge_attach(dev, ext_bridge);
|
||||
+ drm_bridge_attach(encoder, ext_bridge, int_bridge);
|
||||
|
||||
/*
|
||||
* we need the drm_connector created by the external bridge
|
||||
diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
|
||||
index 2bc73f82..931a5c9 100644
|
||||
--- a/drivers/gpu/drm/msm/edp/edp_bridge.c
|
||||
+++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
|
||||
@@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
|
||||
bridge = &edp_bridge->base;
|
||||
bridge->funcs = &edp_bridge_funcs;
|
||||
|
||||
- ret = drm_bridge_attach(edp->dev, bridge);
|
||||
+ ret = drm_bridge_attach(edp->encoder, bridge, NULL);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
|
||||
index bacbd5d..4e6d1bf 100644
|
||||
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
|
||||
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
|
||||
@@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
|
||||
bridge = &hdmi_bridge->base;
|
||||
bridge->funcs = &msm_hdmi_bridge_funcs;
|
||||
|
||||
- ret = drm_bridge_attach(hdmi->dev, bridge);
|
||||
+ ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
|
||||
index f9515f5..c4c5d1ab 100644
|
||||
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
|
||||
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
|
||||
@@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
|
||||
hdmienc->renc = renc;
|
||||
|
||||
/* Link the bridge to the encoder. */
|
||||
- bridge->encoder = encoder;
|
||||
- encoder->bridge = bridge;
|
||||
-
|
||||
- ret = drm_bridge_attach(rcdu->ddev, bridge);
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
drm_encoder_cleanup(encoder);
|
||||
return ret;
|
||||
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
|
||||
index e8c1ed0..411dc6e 100644
|
||||
--- a/drivers/gpu/drm/sti/sti_dvo.c
|
||||
+++ b/drivers/gpu/drm/sti/sti_dvo.c
|
||||
@@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
|
||||
return err;
|
||||
}
|
||||
|
||||
- err = drm_bridge_attach(drm_dev, bridge);
|
||||
+ err = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to attach bridge\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
dvo->bridge = bridge;
|
||||
- encoder->bridge = bridge;
|
||||
connector->encoder = encoder;
|
||||
dvo->encoder = encoder;
|
||||
|
||||
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
|
||||
index 96f336d..66d37d78 100644
|
||||
--- a/drivers/gpu/drm/sti/sti_hda.c
|
||||
+++ b/drivers/gpu/drm/sti/sti_hda.c
|
||||
@@ -707,9 +707,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
bridge->driver_private = hda;
|
||||
bridge->funcs = &sti_hda_bridge_funcs;
|
||||
- drm_bridge_attach(drm_dev, bridge);
|
||||
+ drm_bridge_attach(encoder, bridge, NULL);
|
||||
|
||||
- encoder->bridge = bridge;
|
||||
connector->encoder = encoder;
|
||||
|
||||
drm_connector = (struct drm_connector *)connector;
|
||||
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
|
||||
index 376b076..f0af1ae 100644
|
||||
--- a/drivers/gpu/drm/sti/sti_hdmi.c
|
||||
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
|
||||
@@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
bridge->driver_private = hdmi;
|
||||
bridge->funcs = &sti_hdmi_bridge_funcs;
|
||||
- drm_bridge_attach(drm_dev, bridge);
|
||||
+ drm_bridge_attach(encoder, bridge, NULL);
|
||||
|
||||
- encoder->bridge = bridge;
|
||||
connector->encoder = encoder;
|
||||
|
||||
drm_connector = (struct drm_connector *)connector;
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
|
||||
index f5e86fe..757208f 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
|
||||
@@ -208,6 +208,7 @@ int sun4i_rgb_init(struct drm_device *drm)
|
||||
struct sun4i_drv *drv = drm->dev_private;
|
||||
struct sun4i_tcon *tcon = drv->tcon;
|
||||
struct drm_encoder *encoder;
|
||||
+ struct drm_bridge *bridge;
|
||||
struct sun4i_rgb *rgb;
|
||||
int ret;
|
||||
|
||||
@@ -218,8 +219,8 @@ int sun4i_rgb_init(struct drm_device *drm)
|
||||
encoder = &rgb->encoder;
|
||||
|
||||
tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
|
||||
- encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
|
||||
- if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
|
||||
+ bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
|
||||
+ if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
|
||||
dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -260,16 +261,12 @@ int sun4i_rgb_init(struct drm_device *drm)
|
||||
}
|
||||
}
|
||||
|
||||
- if (!IS_ERR(encoder->bridge)) {
|
||||
- encoder->bridge->encoder = &rgb->encoder;
|
||||
-
|
||||
- ret = drm_bridge_attach(drm, encoder->bridge);
|
||||
+ if (!IS_ERR(bridge)) {
|
||||
+ ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
dev_err(drm->dev, "Couldn't attach our bridge\n");
|
||||
goto err_cleanup_connector;
|
||||
}
|
||||
- } else {
|
||||
- encoder->bridge = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
|
||||
index c67d7cd..b0dd5e8 100644
|
||||
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
|
||||
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
|
||||
@@ -167,10 +167,8 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
|
||||
int ret;
|
||||
|
||||
priv->external_encoder->possible_crtcs = BIT(0);
|
||||
- priv->external_encoder->bridge = bridge;
|
||||
- bridge->encoder = priv->external_encoder;
|
||||
|
||||
- ret = drm_bridge_attach(ddev, bridge);
|
||||
+ ret = drm_bridge_attach(priv->external_encoder, bridge, NULL);
|
||||
if (ret) {
|
||||
dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret);
|
||||
return ret;
|
||||
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
|
||||
index 530a1d6..94e5ee9 100644
|
||||
--- a/include/drm/drm_bridge.h
|
||||
+++ b/include/drm/drm_bridge.h
|
||||
@@ -201,7 +201,8 @@ struct drm_bridge {
|
||||
int drm_bridge_add(struct drm_bridge *bridge);
|
||||
void drm_bridge_remove(struct drm_bridge *bridge);
|
||||
struct drm_bridge *of_drm_find_bridge(struct device_node *np);
|
||||
-int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
|
||||
+int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
|
||||
+ struct drm_bridge *previous);
|
||||
void drm_bridge_detach(struct drm_bridge *bridge);
|
||||
|
||||
bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
From 629ad838c870b17536666327dcedbd0f8762cae8 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 24 May 2017 09:41:48 +0200
|
||||
Subject: [PATCH 11/79] ARM64: dts: meson-gxl: Add CEC pins nodes
|
||||
|
||||
Add the AO and EE domain CEC pins nodes for the Amlogic Meson GXL SoCs.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
index 3a1ccf5..15539f9 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
@@ -191,6 +191,20 @@
|
||||
function = "spdif_out_ao";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ ao_cec_pins: ao_cec {
|
||||
+ mux {
|
||||
+ groups = "ao_cec";
|
||||
+ function = "cec_ao";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ ee_cec_pins: ee_cec {
|
||||
+ mux {
|
||||
+ groups = "ee_cec";
|
||||
+ function = "cec_ao";
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
};
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
From 4d69de06ed2934b45c0e6b2a5056ef2a7caa0b9a Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:51 +0200
|
||||
Subject: [PATCH 11/93] drm: bridge: dw-hdmi: Merge __hdmi_phy_i2c_write and
|
||||
hdmi_phy_i2c_write
|
||||
|
||||
The latter is just an int wrapper around the former void function that
|
||||
unconditionally returns 0. As the return value is never checked, merge
|
||||
the two functions into one.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-2-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 9 +--------
|
||||
1 file changed, 1 insertion(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index f5009ae..a668550 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -868,7 +868,7 @@ static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void __hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
+static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
unsigned char addr)
|
||||
{
|
||||
hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
|
||||
@@ -882,13 +882,6 @@ static void __hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
hdmi_phy_wait_i2c_done(hdmi, 1000);
|
||||
}
|
||||
|
||||
-static int hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
- unsigned char addr)
|
||||
-{
|
||||
- __hdmi_phy_i2c_write(hdmi, data, addr);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
|
||||
{
|
||||
hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
From 69c139fa21249718dfd9d6f14a7b374ae28c8215 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 24 May 2017 09:44:45 +0200
|
||||
Subject: [PATCH 12/79] ARM64: dts: meson-gxl: Add Ethernet PHY LEDS pins nodes
|
||||
|
||||
The Amlogic Meson GXL SoCs embeds an 10/100 Ethernet PHY, this patchs adds
|
||||
the Link and Activity LEDs signals pins nodes.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
index 15539f9..dc7c53f 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
@@ -369,6 +369,20 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ eth_link_led_pins: eth_link_led {
|
||||
+ mux {
|
||||
+ groups = "eth_link_led";
|
||||
+ function = "eth_led";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ eth_act_led_pins: eth_act_led {
|
||||
+ mux {
|
||||
+ groups = "eth_act_led";
|
||||
+ function = "eth_led";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
pwm_a_pins: pwm_a {
|
||||
mux {
|
||||
groups = "pwm_a";
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
From fefa6576d7b085c7712fdc2b5af10e61f3fa1841 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:52 +0200
|
||||
Subject: [PATCH 12/93] drm: bridge: dw-hdmi: Remove unneeded arguments to
|
||||
bind/unbind functions
|
||||
|
||||
The master argument isn't used. The data argument, a void pointer, is
|
||||
used by the bind function only where it's cast to a drm_device pointer,
|
||||
which can easily be obtained from the encoder argument instead. Remove
|
||||
them.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-3-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 8 +++-----
|
||||
drivers/gpu/drm/imx/dw_hdmi-imx.c | 4 ++--
|
||||
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 ++--
|
||||
include/drm/bridge/dw_hdmi.h | 5 ++---
|
||||
4 files changed, 9 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index a668550..f868946 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1854,12 +1854,10 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
- void *data, struct drm_encoder *encoder,
|
||||
+int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
struct resource *iores, int irq,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
{
|
||||
- struct drm_device *drm = data;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct platform_device_info pdevinfo;
|
||||
struct device_node *ddc_node;
|
||||
@@ -1992,7 +1990,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
- ret = dw_hdmi_register(drm, hdmi);
|
||||
+ ret = dw_hdmi_register(encoder->dev, hdmi);
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
@@ -2059,7 +2057,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_bind);
|
||||
|
||||
-void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
|
||||
+void dw_hdmi_unbind(struct device *dev)
|
||||
{
|
||||
struct dw_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
|
||||
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
index 359cd27..f796658 100644
|
||||
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
@@ -249,7 +249,7 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
- ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
|
||||
+ ret = dw_hdmi_bind(dev, encoder, iores, irq, plat_data);
|
||||
|
||||
/*
|
||||
* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
|
||||
@@ -264,7 +264,7 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
static void dw_hdmi_imx_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
- return dw_hdmi_unbind(dev, master, data);
|
||||
+ return dw_hdmi_unbind(dev);
|
||||
}
|
||||
|
||||
static const struct component_ops dw_hdmi_imx_ops = {
|
||||
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
index 0665fb9..e8fb5c5 100644
|
||||
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
@@ -301,7 +301,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
- ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
|
||||
+ ret = dw_hdmi_bind(dev, encoder, iores, irq, plat_data);
|
||||
|
||||
/*
|
||||
* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
|
||||
@@ -316,7 +316,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
- return dw_hdmi_unbind(dev, master, data);
|
||||
+ return dw_hdmi_unbind(dev);
|
||||
}
|
||||
|
||||
static const struct component_ops dw_hdmi_rockchip_ops = {
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index bae79f3..11edda6 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -56,9 +56,8 @@ struct dw_hdmi_plat_data {
|
||||
struct drm_display_mode *mode);
|
||||
};
|
||||
|
||||
-void dw_hdmi_unbind(struct device *dev, struct device *master, void *data);
|
||||
-int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
- void *data, struct drm_encoder *encoder,
|
||||
+void dw_hdmi_unbind(struct device *dev);
|
||||
+int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
struct resource *iores, int irq,
|
||||
const struct dw_hdmi_plat_data *plat_data);
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
From f620469d663615a805ca21169013ba79089e2339 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 22 May 2017 15:14:45 +0200
|
||||
Subject: [PATCH 13/79] ARM64: dts: meson-gxbb: Add SPI pinctrl nodes
|
||||
|
||||
This patch adds the SPICC Controller pins nodes for Amlogic GXBB SoCs.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index daa49ae..1d4c861 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -310,6 +310,22 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ spi_pins: spi {
|
||||
+ mux {
|
||||
+ groups = "spi_miso",
|
||||
+ "spi_mosi",
|
||||
+ "spi_sclk";
|
||||
+ function = "spi";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ spi_ss0_pins: spi-ss0 {
|
||||
+ mux {
|
||||
+ groups = "spi_ss0";
|
||||
+ function = "spi";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
sdcard_pins: sdcard {
|
||||
mux {
|
||||
groups = "sdcard_d0",
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
From 4c8725b2de2a5b87850fb7cfa9d2ecf4499e05fb Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:53 +0200
|
||||
Subject: [PATCH 13/93] drm: bridge: dw-hdmi: Remove unused function parameter
|
||||
|
||||
The 'prep' parameter passed to hdmi_phy_configure() is useless. It is
|
||||
hardcoded as 0, and if set, simply prevents the configure function from
|
||||
executing.
|
||||
|
||||
Remove it.
|
||||
|
||||
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-4-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index f868946..5f8044a 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -931,7 +931,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
||||
}
|
||||
|
||||
-static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
|
||||
+static int hdmi_phy_configure(struct dw_hdmi *hdmi,
|
||||
unsigned char res, int cscon)
|
||||
{
|
||||
unsigned res_idx;
|
||||
@@ -941,9 +941,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
|
||||
|
||||
- if (prep)
|
||||
- return -EINVAL;
|
||||
-
|
||||
switch (res) {
|
||||
case 0: /* color resolution 0 is 8 bit colour depth */
|
||||
case 8:
|
||||
@@ -1072,7 +1069,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
|
||||
/* Enable CSC */
|
||||
- ret = hdmi_phy_configure(hdmi, 0, 8, cscon);
|
||||
+ ret = hdmi_phy_configure(hdmi, 8, cscon);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
From d83151a6b97f039c3efa13d70d9697ef1fd887ac Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Mon, 22 May 2017 15:15:13 +0200
|
||||
Subject: [PATCH 14/79] ARM64: dts: meson-gxl: Add SPI pinctrl nodes
|
||||
|
||||
This patch adds the SPICC Controller pins nodes for Amlogic GXL SoCs.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
index dc7c53f..6584e46 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
@@ -246,6 +246,22 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ spi_pins: spi {
|
||||
+ mux {
|
||||
+ groups = "spi_miso",
|
||||
+ "spi_mosi",
|
||||
+ "spi_sclk";
|
||||
+ function = "spi";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ spi_ss0_pins: spi-ss0 {
|
||||
+ mux {
|
||||
+ groups = "spi_ss0";
|
||||
+ function = "spi";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
sdcard_pins: sdcard {
|
||||
mux {
|
||||
groups = "sdcard_d0",
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
From 891854dbb712fe784cc0553c05bd05a8734d6a3e Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:54 +0200
|
||||
Subject: [PATCH 14/93] drm: bridge: dw-hdmi: Embed drm_bridge in struct
|
||||
dw_hdmi
|
||||
|
||||
The drm_bridge instance is always needed, there's no point in allocating
|
||||
it separately.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-5-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 13 +++----------
|
||||
1 file changed, 3 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 5f8044a..2c85b6c 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -116,7 +116,7 @@ struct dw_hdmi_i2c {
|
||||
struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
struct drm_encoder *encoder;
|
||||
- struct drm_bridge *bridge;
|
||||
+ struct drm_bridge bridge;
|
||||
|
||||
struct platform_device *audio;
|
||||
enum dw_hdmi_devtype dev_type;
|
||||
@@ -1806,7 +1806,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
|
||||
dev_dbg(hdmi->dev, "EVENT=%s\n",
|
||||
phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
|
||||
- drm_helper_hpd_irq_event(hdmi->bridge->dev);
|
||||
+ drm_helper_hpd_irq_event(hdmi->bridge.dev);
|
||||
}
|
||||
|
||||
hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
|
||||
@@ -1819,16 +1819,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
{
|
||||
struct drm_encoder *encoder = hdmi->encoder;
|
||||
- struct drm_bridge *bridge;
|
||||
+ struct drm_bridge *bridge = &hdmi->bridge;
|
||||
int ret;
|
||||
|
||||
- bridge = devm_kzalloc(drm->dev, sizeof(*bridge), GFP_KERNEL);
|
||||
- if (!bridge) {
|
||||
- DRM_ERROR("Failed to allocate drm bridge\n");
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
-
|
||||
- hdmi->bridge = bridge;
|
||||
bridge->driver_private = hdmi;
|
||||
bridge->funcs = &dw_hdmi_bridge_funcs;
|
||||
ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
From 9fef18b9a29bb46c33bd724b1f66296b69fa65df Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:55 +0200
|
||||
Subject: [PATCH 15/93] drm: bridge: dw-hdmi: Remove encoder field from struct
|
||||
dw_hdmi
|
||||
|
||||
The field isn't needed, remove it.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-6-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 2c85b6c..ef10bb8 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -115,7 +115,6 @@ struct dw_hdmi_i2c {
|
||||
|
||||
struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
- struct drm_encoder *encoder;
|
||||
struct drm_bridge bridge;
|
||||
|
||||
struct platform_device *audio;
|
||||
@@ -1816,9 +1815,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
+static int dw_hdmi_register(struct drm_encoder *encoder, struct dw_hdmi *hdmi)
|
||||
{
|
||||
- struct drm_encoder *encoder = hdmi->encoder;
|
||||
struct drm_bridge *bridge = &hdmi->bridge;
|
||||
int ret;
|
||||
|
||||
@@ -1835,7 +1833,7 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
|
||||
drm_connector_helper_add(&hdmi->connector,
|
||||
&dw_hdmi_connector_helper_funcs);
|
||||
|
||||
- drm_connector_init(drm, &hdmi->connector,
|
||||
+ drm_connector_init(encoder->dev, &hdmi->connector,
|
||||
&dw_hdmi_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_HDMIA);
|
||||
|
||||
@@ -1867,7 +1865,6 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
hdmi->dev = dev;
|
||||
hdmi->dev_type = plat_data->dev_type;
|
||||
hdmi->sample_rate = 48000;
|
||||
- hdmi->encoder = encoder;
|
||||
hdmi->disabled = true;
|
||||
hdmi->rxsense = true;
|
||||
hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
|
||||
@@ -1980,7 +1977,7 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
- ret = dw_hdmi_register(encoder->dev, hdmi);
|
||||
+ ret = dw_hdmi_register(encoder, hdmi);
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From 0f14939959a72d4cec1ed3343af441fe930aedf7 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 23 May 2017 17:57:34 +0200
|
||||
Subject: [PATCH 15/79] pinctrl: meson-gxl: Fix typo in AO I2S pins
|
||||
|
||||
The AO I2S pins were incorrectly defined with the EE pin offset.
|
||||
|
||||
Cc: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Fixes: 2899adf0422 ("pinctrl: meson: gxl: add i2s output pins")
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxl.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
index 998210e..0673115 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
@@ -271,8 +271,8 @@
|
||||
static const unsigned int pwm_ao_b_pins[] = { PIN(GPIOAO_9, 0) };
|
||||
static const unsigned int pwm_ao_b_6_pins[] = { PIN(GPIOAO_6, 0) };
|
||||
|
||||
-static const unsigned int i2s_out_ch23_ao_pins[] = { PIN(GPIOAO_8, EE_OFF) };
|
||||
-static const unsigned int i2s_out_ch45_ao_pins[] = { PIN(GPIOAO_9, EE_OFF) };
|
||||
+static const unsigned int i2s_out_ch23_ao_pins[] = { PIN(GPIOAO_8, 0) };
|
||||
+static const unsigned int i2s_out_ch45_ao_pins[] = { PIN(GPIOAO_9, 0) };
|
||||
|
||||
static const unsigned int spdif_out_ao_6_pins[] = { PIN(GPIOAO_6, EE_OFF) };
|
||||
static const unsigned int spdif_out_ao_9_pins[] = { PIN(GPIOAO_9, EE_OFF) };
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
From 259254dabd150067bf932e192dd9ed8b3d545755 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:56 +0200
|
||||
Subject: [PATCH 16/93] drm: bridge: dw-hdmi: Don't forward HPD events to DRM
|
||||
core before attach
|
||||
|
||||
Hotplug events should only be forwarded to the DRM core by the interrupt
|
||||
handler when the bridge has been attached, otherwise the DRM device
|
||||
pointer will be NULL, resulting in a crash.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-7-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index ef10bb8..488dc1a 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1805,7 +1805,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
|
||||
dev_dbg(hdmi->dev, "EVENT=%s\n",
|
||||
phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
|
||||
- drm_helper_hpd_irq_event(hdmi->bridge.dev);
|
||||
+ if (hdmi->bridge.dev)
|
||||
+ drm_helper_hpd_irq_event(hdmi->bridge.dev);
|
||||
}
|
||||
|
||||
hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From 846811f8445bb82b54aac0b102c3d29f278cb587 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 24 May 2017 09:35:13 +0200
|
||||
Subject: [PATCH 16/79] pinctrl: meson-gxl: Fix typo in AO SPDIF pins
|
||||
|
||||
The AO SPDIF pins were incorrectly defined with the EE pin offset.
|
||||
|
||||
Cc: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Fixes: b840d649f9ec ("pinctrl: meson: gxl: add spdif output pins")
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxl.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
index 0673115..c59e377 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
@@ -274,8 +274,8 @@
|
||||
static const unsigned int i2s_out_ch23_ao_pins[] = { PIN(GPIOAO_8, 0) };
|
||||
static const unsigned int i2s_out_ch45_ao_pins[] = { PIN(GPIOAO_9, 0) };
|
||||
|
||||
-static const unsigned int spdif_out_ao_6_pins[] = { PIN(GPIOAO_6, EE_OFF) };
|
||||
-static const unsigned int spdif_out_ao_9_pins[] = { PIN(GPIOAO_9, EE_OFF) };
|
||||
+static const unsigned int spdif_out_ao_6_pins[] = { PIN(GPIOAO_6, 0) };
|
||||
+static const unsigned int spdif_out_ao_9_pins[] = { PIN(GPIOAO_9, 0) };
|
||||
|
||||
static struct meson_pmx_group meson_gxl_periphs_groups[] = {
|
||||
GPIO_GROUP(GPIOZ_0, EE_OFF),
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
From 1de2e27b041a944da876ec10a530991d82dfd991 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:57 +0200
|
||||
Subject: [PATCH 17/93] drm: bridge: dw-hdmi: Move IRQ and IO resource
|
||||
allocation to common code
|
||||
|
||||
There's no need to duplicate identical code in multiple drivers (two at
|
||||
the moment, one more to come soon). Move it to the dw-hdmi core where it
|
||||
can be shared. If resource allocation ever becomes device-specific later
|
||||
we'll always have the option of splitting it out again.
|
||||
|
||||
While it at pass the platform device to the bind function to avoid
|
||||
having to cast struct device to struct platform_device.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-8-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 13 ++++++++++---
|
||||
drivers/gpu/drm/imx/dw_hdmi-imx.c | 12 +-----------
|
||||
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 12 +-----------
|
||||
include/drm/bridge/dw_hdmi.h | 3 +--
|
||||
4 files changed, 13 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 488dc1a..563cbec 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1843,14 +1843,16 @@ static int dw_hdmi_register(struct drm_encoder *encoder, struct dw_hdmi *hdmi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
- struct resource *iores, int irq,
|
||||
+int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct platform_device_info pdevinfo;
|
||||
struct device_node *ddc_node;
|
||||
struct dw_hdmi *hdmi;
|
||||
+ struct resource *iores;
|
||||
+ int irq;
|
||||
int ret;
|
||||
u32 val = 1;
|
||||
u8 config0;
|
||||
@@ -1903,6 +1905,7 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
dev_dbg(hdmi->dev, "no ddc property found\n");
|
||||
}
|
||||
|
||||
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hdmi->regs = devm_ioremap_resource(dev, iores);
|
||||
if (IS_ERR(hdmi->regs)) {
|
||||
ret = PTR_ERR(hdmi->regs);
|
||||
@@ -1945,6 +1948,10 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0)
|
||||
+ goto err_iahb;
|
||||
+
|
||||
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
|
||||
dw_hdmi_irq, IRQF_SHARED,
|
||||
dev_name(dev), hdmi);
|
||||
@@ -2025,7 +2032,7 @@ int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
if (hdmi->i2c)
|
||||
dw_hdmi_i2c_init(hdmi);
|
||||
|
||||
- dev_set_drvdata(dev, hdmi);
|
||||
+ platform_set_drvdata(pdev, hdmi);
|
||||
|
||||
return 0;
|
||||
|
||||
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
index f796658..f645275 100644
|
||||
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
@@ -207,8 +207,6 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
struct drm_device *drm = data;
|
||||
struct drm_encoder *encoder;
|
||||
struct imx_hdmi *hdmi;
|
||||
- struct resource *iores;
|
||||
- int irq;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
@@ -223,14 +221,6 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
hdmi->dev = &pdev->dev;
|
||||
encoder = &hdmi->encoder;
|
||||
|
||||
- irq = platform_get_irq(pdev, 0);
|
||||
- if (irq < 0)
|
||||
- return irq;
|
||||
-
|
||||
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- if (!iores)
|
||||
- return -ENXIO;
|
||||
-
|
||||
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
|
||||
/*
|
||||
* If we failed to find the CRTC(s) which this encoder is
|
||||
@@ -249,7 +239,7 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
- ret = dw_hdmi_bind(dev, encoder, iores, irq, plat_data);
|
||||
+ ret = dw_hdmi_bind(pdev, encoder, plat_data);
|
||||
|
||||
/*
|
||||
* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
|
||||
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
index e8fb5c5..a6d4a02 100644
|
||||
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
@@ -257,8 +257,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
struct drm_device *drm = data;
|
||||
struct drm_encoder *encoder;
|
||||
struct rockchip_hdmi *hdmi;
|
||||
- struct resource *iores;
|
||||
- int irq;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
@@ -273,14 +271,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
hdmi->dev = &pdev->dev;
|
||||
encoder = &hdmi->encoder;
|
||||
|
||||
- irq = platform_get_irq(pdev, 0);
|
||||
- if (irq < 0)
|
||||
- return irq;
|
||||
-
|
||||
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- if (!iores)
|
||||
- return -ENXIO;
|
||||
-
|
||||
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
|
||||
/*
|
||||
* If we failed to find the CRTC(s) which this encoder is
|
||||
@@ -301,7 +291,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
- ret = dw_hdmi_bind(dev, encoder, iores, irq, plat_data);
|
||||
+ ret = dw_hdmi_bind(pdev, encoder, plat_data);
|
||||
|
||||
/*
|
||||
* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 11edda6..94ff6ed 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -57,8 +57,7 @@ struct dw_hdmi_plat_data {
|
||||
};
|
||||
|
||||
void dw_hdmi_unbind(struct device *dev);
|
||||
-int dw_hdmi_bind(struct device *dev, struct drm_encoder *encoder,
|
||||
- struct resource *iores, int irq,
|
||||
+int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
const struct dw_hdmi_plat_data *plat_data);
|
||||
|
||||
void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
From b39031e8d8ba32cb03a500c82f2d9c05784a6747 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 23 May 2017 17:56:18 +0200
|
||||
Subject: [PATCH 17/79] pinctrl: meson-gxbb: Add CEC pins
|
||||
|
||||
Add the AO and EE domain CEC pins for the Amlogic Meson GXBB SoCs.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
index 9b00be1..114e690 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
@@ -290,6 +290,9 @@
|
||||
static const unsigned int spdif_out_ao_6_pins[] = { PIN(GPIOAO_6, 0) };
|
||||
static const unsigned int spdif_out_ao_13_pins[] = { PIN(GPIOAO_13, 0) };
|
||||
|
||||
+static const unsigned int ao_cec_pins[] = { PIN(GPIOAO_12, 0) };
|
||||
+static const unsigned int ee_cec_pins[] = { PIN(GPIOAO_12, 0) };
|
||||
+
|
||||
static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
|
||||
GPIO_GROUP(GPIOZ_0, EE_OFF),
|
||||
GPIO_GROUP(GPIOZ_1, EE_OFF),
|
||||
@@ -551,6 +554,8 @@
|
||||
GROUP(i2s_out_ch45_ao, 1, 1),
|
||||
GROUP(spdif_out_ao_6, 0, 16),
|
||||
GROUP(spdif_out_ao_13, 0, 4),
|
||||
+ GROUP(ao_cec, 0, 15),
|
||||
+ GROUP(ee_cec, 0, 14),
|
||||
};
|
||||
|
||||
static const char * const gpio_periphs_groups[] = {
|
||||
@@ -739,6 +744,10 @@
|
||||
"spdif_out_ao_6", "spdif_out_ao_13",
|
||||
};
|
||||
|
||||
+static const char * const cec_ao_groups[] = {
|
||||
+ "ao_cec", "ee_cec",
|
||||
+};
|
||||
+
|
||||
static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
|
||||
FUNCTION(gpio_periphs),
|
||||
FUNCTION(emmc),
|
||||
@@ -779,6 +788,7 @@
|
||||
FUNCTION(pwm_ao_b),
|
||||
FUNCTION(i2s_out_ao),
|
||||
FUNCTION(spdif_out_ao),
|
||||
+ FUNCTION(cec_ao),
|
||||
};
|
||||
|
||||
static struct meson_bank meson_gxbb_periphs_banks[] = {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
From 78e502a47988bfdb298e8416444c0f1f6e7e93a4 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:58 +0200
|
||||
Subject: [PATCH 18/93] drm: bridge: dw-hdmi: Reorder functions to prepare for
|
||||
next commit
|
||||
|
||||
The next commit will reference structures and functions in a way that
|
||||
currently requires forward declarations. Reorder the functions to avoid
|
||||
that. No functional change to the code is performed.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-9-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 72 ++++++++++++++++++++--------------------
|
||||
1 file changed, 36 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 563cbec..92ce9e5 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1575,42 +1575,6 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
|
||||
hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
}
|
||||
|
||||
-static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
- struct drm_display_mode *orig_mode,
|
||||
- struct drm_display_mode *mode)
|
||||
-{
|
||||
- struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
-
|
||||
- mutex_lock(&hdmi->mutex);
|
||||
-
|
||||
- /* Store the display mode for plugin/DKMS poweron events */
|
||||
- memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
|
||||
-
|
||||
- mutex_unlock(&hdmi->mutex);
|
||||
-}
|
||||
-
|
||||
-static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
|
||||
-{
|
||||
- struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
-
|
||||
- mutex_lock(&hdmi->mutex);
|
||||
- hdmi->disabled = true;
|
||||
- dw_hdmi_update_power(hdmi);
|
||||
- dw_hdmi_update_phy_mask(hdmi);
|
||||
- mutex_unlock(&hdmi->mutex);
|
||||
-}
|
||||
-
|
||||
-static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
|
||||
-{
|
||||
- struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
-
|
||||
- mutex_lock(&hdmi->mutex);
|
||||
- hdmi->disabled = false;
|
||||
- dw_hdmi_update_power(hdmi);
|
||||
- dw_hdmi_update_phy_mask(hdmi);
|
||||
- mutex_unlock(&hdmi->mutex);
|
||||
-}
|
||||
-
|
||||
static enum drm_connector_status
|
||||
dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
@@ -1703,6 +1667,42 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)
|
||||
.best_encoder = drm_atomic_helper_best_encoder,
|
||||
};
|
||||
|
||||
+static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
+ struct drm_display_mode *orig_mode,
|
||||
+ struct drm_display_mode *mode)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
+
|
||||
+ mutex_lock(&hdmi->mutex);
|
||||
+
|
||||
+ /* Store the display mode for plugin/DKMS poweron events */
|
||||
+ memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
|
||||
+
|
||||
+ mutex_unlock(&hdmi->mutex);
|
||||
+}
|
||||
+
|
||||
+static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
+
|
||||
+ mutex_lock(&hdmi->mutex);
|
||||
+ hdmi->disabled = true;
|
||||
+ dw_hdmi_update_power(hdmi);
|
||||
+ dw_hdmi_update_phy_mask(hdmi);
|
||||
+ mutex_unlock(&hdmi->mutex);
|
||||
+}
|
||||
+
|
||||
+static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
+
|
||||
+ mutex_lock(&hdmi->mutex);
|
||||
+ hdmi->disabled = false;
|
||||
+ dw_hdmi_update_power(hdmi);
|
||||
+ dw_hdmi_update_phy_mask(hdmi);
|
||||
+ mutex_unlock(&hdmi->mutex);
|
||||
+}
|
||||
+
|
||||
static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
|
||||
.enable = dw_hdmi_bridge_enable,
|
||||
.disable = dw_hdmi_bridge_disable,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
From 4f867c391de6437aeeb725bf5beab4f88366ef34 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 23 May 2017 17:50:47 +0200
|
||||
Subject: [PATCH 18/79] pinctrl: meson-gxl: Add CEC pins
|
||||
|
||||
Add the AO and EE domain CEC pins for the Amlogic Meson GXL SoCs.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxl.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
index c59e377..da7f3e9 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
@@ -277,6 +277,9 @@
|
||||
static const unsigned int spdif_out_ao_6_pins[] = { PIN(GPIOAO_6, 0) };
|
||||
static const unsigned int spdif_out_ao_9_pins[] = { PIN(GPIOAO_9, 0) };
|
||||
|
||||
+static const unsigned int ao_cec_pins[] = { PIN(GPIOAO_8, 0) };
|
||||
+static const unsigned int ee_cec_pins[] = { PIN(GPIOAO_8, 0) };
|
||||
+
|
||||
static struct meson_pmx_group meson_gxl_periphs_groups[] = {
|
||||
GPIO_GROUP(GPIOZ_0, EE_OFF),
|
||||
GPIO_GROUP(GPIOZ_1, EE_OFF),
|
||||
@@ -518,6 +521,8 @@
|
||||
GROUP(i2s_out_ch45_ao, 1, 1),
|
||||
GROUP(spdif_out_ao_6, 0, 16),
|
||||
GROUP(spdif_out_ao_9, 0, 4),
|
||||
+ GROUP(ao_cec, 0, 15),
|
||||
+ GROUP(ee_cec, 0, 14),
|
||||
};
|
||||
|
||||
static const char * const gpio_periphs_groups[] = {
|
||||
@@ -689,6 +694,10 @@
|
||||
"spdif_out_ao_6", "spdif_out_ao_9",
|
||||
};
|
||||
|
||||
+static const char * const cec_ao_groups[] = {
|
||||
+ "ao_cec", "ee_cec",
|
||||
+};
|
||||
+
|
||||
static struct meson_pmx_func meson_gxl_periphs_functions[] = {
|
||||
FUNCTION(gpio_periphs),
|
||||
FUNCTION(emmc),
|
||||
@@ -726,6 +735,7 @@
|
||||
FUNCTION(pwm_ao_b),
|
||||
FUNCTION(i2s_out_ao),
|
||||
FUNCTION(spdif_out_ao),
|
||||
+ FUNCTION(cec_ao),
|
||||
};
|
||||
|
||||
static struct meson_bank meson_gxl_periphs_banks[] = {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
From 8b9fed5697ca5dad3197822eb34ae317f45a16a5 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:28:59 +0200
|
||||
Subject: [PATCH 19/93] drm: bridge: dw-hdmi: Create connector in the bridge
|
||||
attach operation
|
||||
|
||||
The DRM device is not guaranteed by the bridge API to be available
|
||||
before the attach callback. The driver performs properly at the moment
|
||||
as it doesn't use the drm_bridge_add() registration method. As this will
|
||||
be changed later, move connector creation to attach time to ensure
|
||||
compatibility with the API.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-10-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 33 ++++++++++++++++++++-------------
|
||||
1 file changed, 20 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 92ce9e5..88cd40a 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1667,6 +1667,25 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)
|
||||
.best_encoder = drm_atomic_helper_best_encoder,
|
||||
};
|
||||
|
||||
+static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
+ struct drm_encoder *encoder = bridge->encoder;
|
||||
+ struct drm_connector *connector = &hdmi->connector;
|
||||
+
|
||||
+ connector->interlace_allowed = 1;
|
||||
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
+
|
||||
+ drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);
|
||||
+
|
||||
+ drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
|
||||
+ DRM_MODE_CONNECTOR_HDMIA);
|
||||
+
|
||||
+ drm_mode_connector_attach_encoder(connector, encoder);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
struct drm_display_mode *orig_mode,
|
||||
struct drm_display_mode *mode)
|
||||
@@ -1704,6 +1723,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
|
||||
+ .attach = dw_hdmi_bridge_attach,
|
||||
.enable = dw_hdmi_bridge_enable,
|
||||
.disable = dw_hdmi_bridge_disable,
|
||||
.mode_set = dw_hdmi_bridge_mode_set,
|
||||
@@ -1829,17 +1849,6 @@ static int dw_hdmi_register(struct drm_encoder *encoder, struct dw_hdmi *hdmi)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
|
||||
-
|
||||
- drm_connector_helper_add(&hdmi->connector,
|
||||
- &dw_hdmi_connector_helper_funcs);
|
||||
-
|
||||
- drm_connector_init(encoder->dev, &hdmi->connector,
|
||||
- &dw_hdmi_connector_funcs,
|
||||
- DRM_MODE_CONNECTOR_HDMIA);
|
||||
-
|
||||
- drm_mode_connector_attach_encoder(&hdmi->connector, encoder);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1862,8 +1871,6 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
if (!hdmi)
|
||||
return -ENOMEM;
|
||||
|
||||
- hdmi->connector.interlace_allowed = 1;
|
||||
-
|
||||
hdmi->plat_data = plat_data;
|
||||
hdmi->dev = dev;
|
||||
hdmi->dev_type = plat_data->dev_type;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
From d68ddd72a278abaeeec0ebccd7146f50fce9a4af Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 23 May 2017 17:53:43 +0200
|
||||
Subject: [PATCH 19/79] pinctrl: meson-gxl: Add Ethernet PHY LEDS pins
|
||||
|
||||
The Amlogic Meson GXL SoCs embeds an 10/100 Ethernet PHY, this patchs enables
|
||||
the Link and Activity LEDs signals.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxl.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
index da7f3e9..7adc7c2 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
@@ -234,6 +234,9 @@
|
||||
|
||||
static const unsigned int spdif_out_h_pins[] = { PIN(GPIOH_4, EE_OFF) };
|
||||
|
||||
+static const unsigned int eth_link_led_pins[] = { PIN(GPIOZ_14, EE_OFF) };
|
||||
+static const unsigned int eth_act_led_pins[] = { PIN(GPIOZ_15, EE_OFF) };
|
||||
+
|
||||
static const struct pinctrl_pin_desc meson_gxl_aobus_pins[] = {
|
||||
MESON_PIN(GPIOAO_0, 0),
|
||||
MESON_PIN(GPIOAO_1, 0),
|
||||
@@ -428,6 +431,8 @@
|
||||
GROUP(i2s_out_ch23_z, 3, 26),
|
||||
GROUP(i2s_out_ch45_z, 3, 25),
|
||||
GROUP(i2s_out_ch67_z, 3, 24),
|
||||
+ GROUP(eth_link_led, 4, 25),
|
||||
+ GROUP(eth_act_led, 4, 24),
|
||||
|
||||
/* Bank H */
|
||||
GROUP(hdmi_hpd, 6, 31),
|
||||
@@ -652,6 +657,10 @@
|
||||
"spdif_out_h",
|
||||
};
|
||||
|
||||
+static const char * const eth_led_groups[] = {
|
||||
+ "eth_link_led", "eth_act_led",
|
||||
+};
|
||||
+
|
||||
static const char * const gpio_aobus_groups[] = {
|
||||
"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
|
||||
"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
|
||||
@@ -722,6 +731,7 @@
|
||||
FUNCTION(hdmi_i2c),
|
||||
FUNCTION(i2s_out),
|
||||
FUNCTION(spdif_out),
|
||||
+ FUNCTION(eth_led),
|
||||
};
|
||||
|
||||
static struct meson_pmx_func meson_gxl_aobus_functions[] = {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,220 +0,0 @@
|
|||
From 200c0b9edb6b1203d6db6391d940f69b6f56e1d6 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:00 +0200
|
||||
Subject: [PATCH 20/93] drm: bridge: dw-hdmi: Implement DRM bridge registration
|
||||
|
||||
As an option for drivers not based on the component framework, register
|
||||
the bridge with the DRM core with the DRM bridge API. Existing drivers
|
||||
based on dw_hdmi_bind() and dw_hdmi_unbind() are not affected as those
|
||||
functions are preserved with their current behaviour.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-11-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 112 ++++++++++++++++++++++++++++-----------
|
||||
include/drm/bridge/dw_hdmi.h | 3 ++
|
||||
2 files changed, 83 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 88cd40a..107fea4 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1836,24 +1836,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static int dw_hdmi_register(struct drm_encoder *encoder, struct dw_hdmi *hdmi)
|
||||
-{
|
||||
- struct drm_bridge *bridge = &hdmi->bridge;
|
||||
- int ret;
|
||||
-
|
||||
- bridge->driver_private = hdmi;
|
||||
- bridge->funcs = &dw_hdmi_bridge_funcs;
|
||||
- ret = drm_bridge_attach(encoder, bridge, NULL);
|
||||
- if (ret) {
|
||||
- DRM_ERROR("Failed to initialize bridge with drm\n");
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
- const struct dw_hdmi_plat_data *plat_data)
|
||||
+static struct dw_hdmi *
|
||||
+__dw_hdmi_probe(struct platform_device *pdev,
|
||||
+ const struct dw_hdmi_plat_data *plat_data)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
@@ -1869,7 +1854,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
|
||||
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
|
||||
if (!hdmi)
|
||||
- return -ENOMEM;
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
|
||||
hdmi->plat_data = plat_data;
|
||||
hdmi->dev = dev;
|
||||
@@ -1896,7 +1881,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "reg-io-width must be 1 or 4\n");
|
||||
- return -EINVAL;
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
|
||||
@@ -1905,7 +1890,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
of_node_put(ddc_node);
|
||||
if (!hdmi->ddc) {
|
||||
dev_dbg(hdmi->dev, "failed to read ddc node\n");
|
||||
- return -EPROBE_DEFER;
|
||||
+ return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -1956,8 +1941,10 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
- if (irq < 0)
|
||||
+ if (irq < 0) {
|
||||
+ ret = irq;
|
||||
goto err_iahb;
|
||||
+ }
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
|
||||
dw_hdmi_irq, IRQF_SHARED,
|
||||
@@ -1988,11 +1975,11 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
HDMI_IH_PHY_STAT0);
|
||||
|
||||
- ret = dw_hdmi_fb_registered(hdmi);
|
||||
- if (ret)
|
||||
- goto err_iahb;
|
||||
+ hdmi->bridge.driver_private = hdmi;
|
||||
+ hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
|
||||
+ hdmi->bridge.of_node = pdev->dev.of_node;
|
||||
|
||||
- ret = dw_hdmi_register(encoder, hdmi);
|
||||
+ ret = dw_hdmi_fb_registered(hdmi);
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
|
||||
@@ -2041,7 +2028,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
|
||||
platform_set_drvdata(pdev, hdmi);
|
||||
|
||||
- return 0;
|
||||
+ return hdmi;
|
||||
|
||||
err_iahb:
|
||||
if (hdmi->i2c) {
|
||||
@@ -2055,14 +2042,11 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
err_res:
|
||||
i2c_put_adapter(hdmi->ddc);
|
||||
|
||||
- return ret;
|
||||
+ return ERR_PTR(ret);
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(dw_hdmi_bind);
|
||||
|
||||
-void dw_hdmi_unbind(struct device *dev)
|
||||
+static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- struct dw_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
-
|
||||
if (hdmi->audio && !IS_ERR(hdmi->audio))
|
||||
platform_device_unregister(hdmi->audio);
|
||||
|
||||
@@ -2077,6 +2061,70 @@ void dw_hdmi_unbind(struct device *dev)
|
||||
else
|
||||
i2c_put_adapter(hdmi->ddc);
|
||||
}
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * Probe/remove API, used from platforms based on the DRM bridge API.
|
||||
+ */
|
||||
+int dw_hdmi_probe(struct platform_device *pdev,
|
||||
+ const struct dw_hdmi_plat_data *plat_data)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi;
|
||||
+ int ret;
|
||||
+
|
||||
+ hdmi = __dw_hdmi_probe(pdev, plat_data);
|
||||
+ if (IS_ERR(hdmi))
|
||||
+ return PTR_ERR(hdmi);
|
||||
+
|
||||
+ ret = drm_bridge_add(&hdmi->bridge);
|
||||
+ if (ret < 0) {
|
||||
+ __dw_hdmi_remove(hdmi);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_probe);
|
||||
+
|
||||
+void dw_hdmi_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ drm_bridge_remove(&hdmi->bridge);
|
||||
+
|
||||
+ __dw_hdmi_remove(hdmi);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_remove);
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * Bind/unbind API, used from platforms based on the component framework.
|
||||
+ */
|
||||
+int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
+ const struct dw_hdmi_plat_data *plat_data)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi;
|
||||
+ int ret;
|
||||
+
|
||||
+ hdmi = __dw_hdmi_probe(pdev, plat_data);
|
||||
+ if (IS_ERR(hdmi))
|
||||
+ return PTR_ERR(hdmi);
|
||||
+
|
||||
+ ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL);
|
||||
+ if (ret) {
|
||||
+ dw_hdmi_remove(pdev);
|
||||
+ DRM_ERROR("Failed to initialize bridge with drm\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_bind);
|
||||
+
|
||||
+void dw_hdmi_unbind(struct device *dev)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
+
|
||||
+ __dw_hdmi_remove(hdmi);
|
||||
+}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
|
||||
|
||||
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 94ff6ed..3bb22a8 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -56,6 +56,9 @@ struct dw_hdmi_plat_data {
|
||||
struct drm_display_mode *mode);
|
||||
};
|
||||
|
||||
+int dw_hdmi_probe(struct platform_device *pdev,
|
||||
+ const struct dw_hdmi_plat_data *plat_data);
|
||||
+void dw_hdmi_remove(struct platform_device *pdev);
|
||||
void dw_hdmi_unbind(struct device *dev);
|
||||
int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
const struct dw_hdmi_plat_data *plat_data);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
From 20c88cc6c1c4d6fb3903be634b54fd0659f2e364 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 23 May 2017 11:53:57 +0200
|
||||
Subject: [PATCH 20/79] pinctrl: meson-gxl: Add missing GPIODV_18 pin entry
|
||||
|
||||
GPIODV_18 entry was missing in the original driver push.
|
||||
|
||||
Fixes: 0f15f500ff2c ("pinctrl: meson: Add GXL pinctrl definitions")
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxl.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
index 7adc7c2..6a486cb 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
|
||||
@@ -89,6 +89,7 @@
|
||||
MESON_PIN(GPIODV_15, EE_OFF),
|
||||
MESON_PIN(GPIODV_16, EE_OFF),
|
||||
MESON_PIN(GPIODV_17, EE_OFF),
|
||||
+ MESON_PIN(GPIODV_18, EE_OFF),
|
||||
MESON_PIN(GPIODV_19, EE_OFF),
|
||||
MESON_PIN(GPIODV_20, EE_OFF),
|
||||
MESON_PIN(GPIODV_21, EE_OFF),
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
From 8fb0058965b30a39f1e0e3820b96013cfbf6bfc6 Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:01 +0200
|
||||
Subject: [PATCH 21/93] drm: bridge: dw-hdmi: Remove PHY configuration
|
||||
resolution parameter
|
||||
|
||||
The current code hard codes the call of hdmi_phy_configure() to be 8bpp
|
||||
and provides extraneous error checking to verify that this hardcoded
|
||||
value is correct. Simplify the implementation by removing the argument.
|
||||
|
||||
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-12-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 27 +++++----------------------
|
||||
1 file changed, 5 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 107fea4..b4fb0bd 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -930,31 +930,14 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
||||
}
|
||||
|
||||
-static int hdmi_phy_configure(struct dw_hdmi *hdmi,
|
||||
- unsigned char res, int cscon)
|
||||
+static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
{
|
||||
- unsigned res_idx;
|
||||
u8 val, msec;
|
||||
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
|
||||
|
||||
- switch (res) {
|
||||
- case 0: /* color resolution 0 is 8 bit colour depth */
|
||||
- case 8:
|
||||
- res_idx = DW_HDMI_RES_8;
|
||||
- break;
|
||||
- case 10:
|
||||
- res_idx = DW_HDMI_RES_10;
|
||||
- break;
|
||||
- case 12:
|
||||
- res_idx = DW_HDMI_RES_12;
|
||||
- break;
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
/* PLL/MPLL Cfg - always match on final entry */
|
||||
for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
|
||||
if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||
@@ -1004,11 +987,11 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi,
|
||||
HDMI_PHY_I2CM_SLAVE_ADDR);
|
||||
hdmi_phy_test_clear(hdmi, 0);
|
||||
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].cpce, 0x06);
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].gmp, 0x15);
|
||||
+ hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, 0x06);
|
||||
+ hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, 0x15);
|
||||
|
||||
/* CURRCTRL */
|
||||
- hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[res_idx], 0x10);
|
||||
+ hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], 0x10);
|
||||
|
||||
hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
|
||||
hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
|
||||
@@ -1068,7 +1051,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
|
||||
/* Enable CSC */
|
||||
- ret = hdmi_phy_configure(hdmi, 8, cscon);
|
||||
+ ret = hdmi_phy_configure(hdmi, cscon);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
From 8dc15df570ea27434fa31704ca2bf2684471c2b4 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Tue, 23 May 2017 16:03:44 +0200
|
||||
Subject: [PATCH 21/79] pinctrl: meson-gxbb: Add missing GPIODV_18 pin entry
|
||||
|
||||
GPIODV_18 entry was missing in the original driver push.
|
||||
|
||||
Fixes: 468c234f9ed7 ("pinctrl: amlogic: Add support for Amlogic Meson GXBB SoC")
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
index 114e690..2ccd776 100644
|
||||
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
|
||||
@@ -85,6 +85,7 @@
|
||||
MESON_PIN(GPIODV_15, EE_OFF),
|
||||
MESON_PIN(GPIODV_16, EE_OFF),
|
||||
MESON_PIN(GPIODV_17, EE_OFF),
|
||||
+ MESON_PIN(GPIODV_18, EE_OFF),
|
||||
MESON_PIN(GPIODV_19, EE_OFF),
|
||||
MESON_PIN(GPIODV_20, EE_OFF),
|
||||
MESON_PIN(GPIODV_21, EE_OFF),
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
From 1c11d32e68aa3591701810fc88fb1ed0e12d730d Mon Sep 17 00:00:00 2001
|
||||
From: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
Date: Wed, 7 Jun 2017 11:46:08 -0300
|
||||
Subject: [PATCH 22/79] cec: add cec_s_phys_addr_from_edid helper function
|
||||
|
||||
This function simplifies the integration of CEC in DRM drivers.
|
||||
|
||||
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
Documentation/media/kapi/cec-core.rst | 8 ++++++++
|
||||
drivers/media/cec/cec-adap.c | 14 ++++++++++++++
|
||||
include/media/cec.h | 9 +++++++++
|
||||
3 files changed, 31 insertions(+)
|
||||
|
||||
diff --git a/Documentation/media/kapi/cec-core.rst b/Documentation/media/kapi/cec-core.rst
|
||||
index 7a04c53..278b358 100644
|
||||
--- a/Documentation/media/kapi/cec-core.rst
|
||||
+++ b/Documentation/media/kapi/cec-core.rst
|
||||
@@ -307,6 +307,14 @@ to another valid physical address, then this function will first set the
|
||||
address to CEC_PHYS_ADDR_INVALID before enabling the new physical address.
|
||||
|
||||
.. c:function::
|
||||
+ void cec_s_phys_addr_from_edid(struct cec_adapter *adap,
|
||||
+ const struct edid *edid);
|
||||
+
|
||||
+A helper function that extracts the physical address from the edid struct
|
||||
+and calls cec_s_phys_addr() with that address, or CEC_PHYS_ADDR_INVALID
|
||||
+if the EDID did not contain a physical address or edid was a NULL pointer.
|
||||
+
|
||||
+.. c:function::
|
||||
int cec_s_log_addrs(struct cec_adapter *adap,
|
||||
struct cec_log_addrs *log_addrs, bool block);
|
||||
|
||||
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
|
||||
index 9dfc798..8a4417f 100644
|
||||
--- a/drivers/media/cec/cec-adap.c
|
||||
+++ b/drivers/media/cec/cec-adap.c
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
+#include <drm/drm_edid.h>
|
||||
+
|
||||
#include "cec-priv.h"
|
||||
|
||||
static void cec_fill_msg_report_features(struct cec_adapter *adap,
|
||||
@@ -1404,6 +1406,18 @@ void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_s_phys_addr);
|
||||
|
||||
+void cec_s_phys_addr_from_edid(struct cec_adapter *adap,
|
||||
+ const struct edid *edid)
|
||||
+{
|
||||
+ u16 pa = CEC_PHYS_ADDR_INVALID;
|
||||
+
|
||||
+ if (edid && edid->extensions)
|
||||
+ pa = cec_get_edid_phys_addr((const u8 *)edid,
|
||||
+ EDID_LENGTH * (edid->extensions + 1), NULL);
|
||||
+ cec_s_phys_addr(adap, pa, false);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(cec_s_phys_addr_from_edid);
|
||||
+
|
||||
/*
|
||||
* Called from either the ioctl or a driver to set the logical addresses.
|
||||
*
|
||||
diff --git a/include/media/cec.h b/include/media/cec.h
|
||||
index 201f060..ae206e2 100644
|
||||
--- a/include/media/cec.h
|
||||
+++ b/include/media/cec.h
|
||||
@@ -206,6 +206,8 @@ static inline bool cec_is_sink(const struct cec_adapter *adap)
|
||||
#define cec_phys_addr_exp(pa) \
|
||||
((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf
|
||||
|
||||
+struct edid;
|
||||
+
|
||||
#if IS_REACHABLE(CONFIG_CEC_CORE)
|
||||
struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
|
||||
void *priv, const char *name, u32 caps, u8 available_las);
|
||||
@@ -217,6 +219,8 @@ int cec_s_log_addrs(struct cec_adapter *adap, struct cec_log_addrs *log_addrs,
|
||||
bool block);
|
||||
void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr,
|
||||
bool block);
|
||||
+void cec_s_phys_addr_from_edid(struct cec_adapter *adap,
|
||||
+ const struct edid *edid);
|
||||
int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
|
||||
bool block);
|
||||
|
||||
@@ -326,6 +330,11 @@ static inline void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr,
|
||||
{
|
||||
}
|
||||
|
||||
+static inline void cec_s_phys_addr_from_edid(struct cec_adapter *adap,
|
||||
+ const struct edid *edid)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
static inline u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
|
||||
unsigned int *offset)
|
||||
{
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
From c7604b72b3695ee449d16916aa474b23c53af425 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:02 +0200
|
||||
Subject: [PATCH 22/93] drm: bridge: dw-hdmi: Rename CONF0 SPARECTRL bit to
|
||||
SVSRET
|
||||
|
||||
The bit is documented in a Rockchip BSP as
|
||||
|
||||
#define m_SVSRET_SIG (1 << 5) /* depend on PHY_MHL_COMB0=1 */
|
||||
|
||||
This is confirmed by a Renesas platform, which uses a 2.0 DWC HDMI TX as
|
||||
the RK3288. Rename the bit accordingly.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-13-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 8 ++++----
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 4 ++--
|
||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index b4fb0bd..06c252f 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -895,11 +895,11 @@ static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_ENTMDS_MASK);
|
||||
}
|
||||
|
||||
-static void dw_hdmi_phy_enable_spare(struct dw_hdmi *hdmi, u8 enable)
|
||||
+static void dw_hdmi_phy_enable_svsret(struct dw_hdmi *hdmi, u8 enable)
|
||||
{
|
||||
hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
|
||||
- HDMI_PHY_CONF0_SPARECTRL_OFFSET,
|
||||
- HDMI_PHY_CONF0_SPARECTRL_MASK);
|
||||
+ HDMI_PHY_CONF0_SVSRET_OFFSET,
|
||||
+ HDMI_PHY_CONF0_SVSRET_MASK);
|
||||
}
|
||||
|
||||
static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable)
|
||||
@@ -1014,7 +1014,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
|
||||
if (hdmi->dev_type == RK3288_HDMI)
|
||||
- dw_hdmi_phy_enable_spare(hdmi, 1);
|
||||
+ dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
|
||||
/*Wait for PHY PLL lock */
|
||||
msec = 5;
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index 55135bb..08235ae 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -847,8 +847,8 @@ enum {
|
||||
HDMI_PHY_CONF0_PDZ_OFFSET = 7,
|
||||
HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
|
||||
HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
|
||||
- HDMI_PHY_CONF0_SPARECTRL_MASK = 0x20,
|
||||
- HDMI_PHY_CONF0_SPARECTRL_OFFSET = 5,
|
||||
+ HDMI_PHY_CONF0_SVSRET_MASK = 0x20,
|
||||
+ HDMI_PHY_CONF0_SVSRET_OFFSET = 5,
|
||||
HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
|
||||
HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
|
||||
HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
From f853954636579085c6c21bf7df08af2c44f77042 Mon Sep 17 00:00:00 2001
|
||||
From: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
Date: Wed, 7 Jun 2017 11:46:09 -0300
|
||||
Subject: [PATCH 23/79] cec: add cec_phys_addr_invalidate() helper function
|
||||
|
||||
Simplifies setting the physical address to CEC_PHYS_ADDR_INVALID.
|
||||
|
||||
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
Signed-off-by: Hans Verkuil <hansverk@cisco.com>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
include/media/cec.h | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/include/media/cec.h b/include/media/cec.h
|
||||
index ae206e2..fc69588 100644
|
||||
--- a/include/media/cec.h
|
||||
+++ b/include/media/cec.h
|
||||
@@ -360,4 +360,17 @@ static inline int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
|
||||
|
||||
#endif
|
||||
|
||||
+/**
|
||||
+ * cec_phys_addr_invalidate() - set the physical address to INVALID
|
||||
+ *
|
||||
+ * @adap: the CEC adapter
|
||||
+ *
|
||||
+ * This is a simple helper function to invalidate the physical
|
||||
+ * address.
|
||||
+ */
|
||||
+static inline void cec_phys_addr_invalidate(struct cec_adapter *adap)
|
||||
+{
|
||||
+ cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
|
||||
+}
|
||||
+
|
||||
#endif /* _MEDIA_CEC_H */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
From a2bdacb64471d710bb4bdbc70e27d276eaae6d00 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:03 +0200
|
||||
Subject: [PATCH 23/93] drm: bridge: dw-hdmi: Reject invalid product IDs
|
||||
|
||||
The DWC HDMI TX can be recognized by the two product identification
|
||||
registers. If the registers don't read as expect the IP will be very
|
||||
different than what the driver has been designed for, or will be
|
||||
misconfigured in a way that makes it non-operational (invalid memory
|
||||
address, incorrect clocks, ...). We should reject this situation with an
|
||||
error.
|
||||
|
||||
While this isn't critical for proper operation with supported IPs at the
|
||||
moment, the driver will soon gain automatic device-specific handling
|
||||
based on runtime device identification. This change makes it easier to
|
||||
implement that without having to default to a random guess in case the
|
||||
device can't be identified.
|
||||
|
||||
While at it print a readable version number in the device identification
|
||||
message instead of raw register values.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-14-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 25 +++++++++++++++++++------
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 8 ++++++++
|
||||
2 files changed, 27 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 06c252f..1809247 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1832,6 +1832,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
int irq;
|
||||
int ret;
|
||||
u32 val = 1;
|
||||
+ u16 version;
|
||||
+ u8 prod_id0;
|
||||
+ u8 prod_id1;
|
||||
u8 config0;
|
||||
u8 config1;
|
||||
|
||||
@@ -1914,12 +1917,22 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
/* Product and revision IDs */
|
||||
- dev_info(dev,
|
||||
- "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
|
||||
- hdmi_readb(hdmi, HDMI_DESIGN_ID),
|
||||
- hdmi_readb(hdmi, HDMI_REVISION_ID),
|
||||
- hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
|
||||
- hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
|
||||
+ version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
|
||||
+ | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
|
||||
+ prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0);
|
||||
+ prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1);
|
||||
+
|
||||
+ if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX ||
|
||||
+ (prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) {
|
||||
+ dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n",
|
||||
+ version, prod_id0, prod_id1);
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_iahb;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n",
|
||||
+ version >> 12, version & 0xfff,
|
||||
+ prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without");
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index 08235ae..91d7fab 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -545,6 +545,14 @@
|
||||
#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
|
||||
|
||||
enum {
|
||||
+/* PRODUCT_ID0 field values */
|
||||
+ HDMI_PRODUCT_ID0_HDMI_TX = 0xa0,
|
||||
+
|
||||
+/* PRODUCT_ID1 field values */
|
||||
+ HDMI_PRODUCT_ID1_HDCP = 0xc0,
|
||||
+ HDMI_PRODUCT_ID1_HDMI_RX = 0x02,
|
||||
+ HDMI_PRODUCT_ID1_HDMI_TX = 0x01,
|
||||
+
|
||||
/* CONFIG0_ID field values */
|
||||
HDMI_CONFIG0_I2S = 0x10,
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
From e7f6f1daa5b19c35fbf25d6f5501273023a41f72 Mon Sep 17 00:00:00 2001
|
||||
From: Hans Verkuil <hverkuil@xs4all.nl>
|
||||
Date: Wed, 7 Jun 2017 11:46:10 -0300
|
||||
Subject: [PATCH 24/79] cec: add cec_transmit_attempt_done helper function
|
||||
|
||||
A simpler variant of cec_transmit_done to be used where the HW does
|
||||
just a single attempt at a transmit. So if the status indicates an
|
||||
error, then the corresponding error count will always be 1 and this
|
||||
function figures that out based on the status argument.
|
||||
|
||||
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
Documentation/media/kapi/cec-core.rst | 10 ++++++++++
|
||||
drivers/media/cec/cec-adap.c | 26 ++++++++++++++++++++++++++
|
||||
include/media/cec.h | 6 ++++++
|
||||
3 files changed, 42 insertions(+)
|
||||
|
||||
diff --git a/Documentation/media/kapi/cec-core.rst b/Documentation/media/kapi/cec-core.rst
|
||||
index 278b358..8a65c69 100644
|
||||
--- a/Documentation/media/kapi/cec-core.rst
|
||||
+++ b/Documentation/media/kapi/cec-core.rst
|
||||
@@ -194,6 +194,11 @@ When a transmit finished (successfully or otherwise):
|
||||
void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
|
||||
u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt);
|
||||
|
||||
+or:
|
||||
+
|
||||
+.. c:function::
|
||||
+ void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status);
|
||||
+
|
||||
The status can be one of:
|
||||
|
||||
CEC_TX_STATUS_OK:
|
||||
@@ -231,6 +236,11 @@ to 1, if the hardware does support retry then either set these counters to
|
||||
0 if the hardware provides no feedback of which errors occurred and how many
|
||||
times, or fill in the correct values as reported by the hardware.
|
||||
|
||||
+The cec_transmit_attempt_done() function is a helper for cases where the
|
||||
+hardware never retries, so the transmit is always for just a single
|
||||
+attempt. It will call cec_transmit_done() in turn, filling in 1 for the
|
||||
+count argument corresponding to the status. Or all 0 if the status was OK.
|
||||
+
|
||||
When a CEC message was received:
|
||||
|
||||
.. c:function::
|
||||
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
|
||||
index 8a4417f..193cea1 100644
|
||||
--- a/drivers/media/cec/cec-adap.c
|
||||
+++ b/drivers/media/cec/cec-adap.c
|
||||
@@ -546,6 +546,32 @@ void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_transmit_done);
|
||||
|
||||
+void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status)
|
||||
+{
|
||||
+ switch (status) {
|
||||
+ case CEC_TX_STATUS_OK:
|
||||
+ cec_transmit_done(adap, status, 0, 0, 0, 0);
|
||||
+ return;
|
||||
+ case CEC_TX_STATUS_ARB_LOST:
|
||||
+ cec_transmit_done(adap, status, 1, 0, 0, 0);
|
||||
+ return;
|
||||
+ case CEC_TX_STATUS_NACK:
|
||||
+ cec_transmit_done(adap, status, 0, 1, 0, 0);
|
||||
+ return;
|
||||
+ case CEC_TX_STATUS_LOW_DRIVE:
|
||||
+ cec_transmit_done(adap, status, 0, 0, 1, 0);
|
||||
+ return;
|
||||
+ case CEC_TX_STATUS_ERROR:
|
||||
+ cec_transmit_done(adap, status, 0, 0, 0, 1);
|
||||
+ return;
|
||||
+ default:
|
||||
+ /* Should never happen */
|
||||
+ WARN(1, "cec-%s: invalid status 0x%02x\n", adap->name, status);
|
||||
+ return;
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(cec_transmit_attempt_done);
|
||||
+
|
||||
/*
|
||||
* Called when waiting for a reply times out.
|
||||
*/
|
||||
diff --git a/include/media/cec.h b/include/media/cec.h
|
||||
index fc69588..23c1faa 100644
|
||||
--- a/include/media/cec.h
|
||||
+++ b/include/media/cec.h
|
||||
@@ -227,6 +227,12 @@ int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
|
||||
/* Called by the adapter */
|
||||
void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
|
||||
u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt);
|
||||
+/*
|
||||
+ * Simplified version of cec_transmit_done for hardware that doesn't retry
|
||||
+ * failed transmits. So this is always just one attempt in which case
|
||||
+ * the status is sufficient.
|
||||
+ */
|
||||
+void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status);
|
||||
void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg);
|
||||
|
||||
/**
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
From dce4baf82ad245b9fc6a6fe6945e484ac9f32fa4 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:04 +0200
|
||||
Subject: [PATCH 24/93] drm: bridge: dw-hdmi: Detect AHB audio DMA using
|
||||
correct register
|
||||
|
||||
Bit 0 in CONFIG1_ID tells whether the IP core uses an AHB slave
|
||||
interface for control. The correct way to identify AHB audio DMA support
|
||||
is through bit 1 in CONFIG3_ID.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-15-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 6 +++---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 4 ++++
|
||||
2 files changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 1809247..730a7558 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1836,7 +1836,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
u8 prod_id0;
|
||||
u8 prod_id1;
|
||||
u8 config0;
|
||||
- u8 config1;
|
||||
+ u8 config3;
|
||||
|
||||
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
|
||||
if (!hdmi)
|
||||
@@ -1988,9 +1988,9 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
pdevinfo.id = PLATFORM_DEVID_AUTO;
|
||||
|
||||
config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
|
||||
- config1 = hdmi_readb(hdmi, HDMI_CONFIG1_ID);
|
||||
+ config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
|
||||
|
||||
- if (config1 & HDMI_CONFIG1_AHB) {
|
||||
+ if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
|
||||
struct dw_hdmi_audio_data audio;
|
||||
|
||||
audio.phys = iores->start;
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index 91d7fab..a4fd64a 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -559,6 +559,10 @@ enum {
|
||||
/* CONFIG1_ID field values */
|
||||
HDMI_CONFIG1_AHB = 0x01,
|
||||
|
||||
+/* CONFIG3_ID field values */
|
||||
+ HDMI_CONFIG3_AHBAUDDMA = 0x02,
|
||||
+ HDMI_CONFIG3_GPAUD = 0x01,
|
||||
+
|
||||
/* IH_FC_INT2 field values */
|
||||
HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
|
||||
HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
|
||||
--
|
||||
1.9.1
|
||||
|
176
patch/kernel/odroidc2-next/0025-cec-add-CEC_CAP_NEEDS_HPD.patch
Normal file
176
patch/kernel/odroidc2-next/0025-cec-add-CEC_CAP_NEEDS_HPD.patch
Normal file
|
@ -0,0 +1,176 @@
|
|||
From e4826bb782c7fca70e8c1b7cbe1bb726400399b5 Mon Sep 17 00:00:00 2001
|
||||
From: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
Date: Wed, 7 Jun 2017 11:46:12 -0300
|
||||
Subject: [PATCH 25/79] cec: add CEC_CAP_NEEDS_HPD
|
||||
|
||||
Add a new capability CEC_CAP_NEEDS_HPD. If this capability is set
|
||||
then the hardware can only use CEC if the HDMI Hotplug Detect pin
|
||||
is high. Such hardware cannot handle the corner case in the CEC specification
|
||||
where it is possible to transmit messages even if no hotplug signal is
|
||||
present (needed for some displays that turn off the HPD when in standby,
|
||||
but still have CEC enabled).
|
||||
|
||||
Typically hardware that needs this capability have the HPD wired to the CEC
|
||||
block, often to a 'power' or 'active' pin.
|
||||
|
||||
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/media/cec/cec-adap.c | 20 ++++++++++++++------
|
||||
drivers/media/cec/cec-api.c | 5 ++++-
|
||||
drivers/media/cec/cec-core.c | 1 +
|
||||
include/media/cec.h | 1 +
|
||||
include/uapi/linux/cec.h | 2 ++
|
||||
5 files changed, 22 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
|
||||
index 193cea1..ab82e84 100644
|
||||
--- a/drivers/media/cec/cec-adap.c
|
||||
+++ b/drivers/media/cec/cec-adap.c
|
||||
@@ -368,6 +368,8 @@ int cec_thread_func(void *_adap)
|
||||
* transmit should be canceled.
|
||||
*/
|
||||
err = wait_event_interruptible_timeout(adap->kthread_waitq,
|
||||
+ (adap->needs_hpd &&
|
||||
+ (!adap->is_configured && !adap->is_configuring)) ||
|
||||
kthread_should_stop() ||
|
||||
(!adap->transmitting &&
|
||||
!list_empty(&adap->transmit_queue)),
|
||||
@@ -383,7 +385,9 @@ int cec_thread_func(void *_adap)
|
||||
|
||||
mutex_lock(&adap->lock);
|
||||
|
||||
- if (kthread_should_stop()) {
|
||||
+ if ((adap->needs_hpd &&
|
||||
+ (!adap->is_configured && !adap->is_configuring)) ||
|
||||
+ kthread_should_stop()) {
|
||||
cec_flush(adap);
|
||||
goto unlock;
|
||||
}
|
||||
@@ -675,7 +679,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!adap->is_configured && !adap->is_configuring) {
|
||||
- if (msg->msg[0] != 0xf0) {
|
||||
+ if (adap->needs_hpd || msg->msg[0] != 0xf0) {
|
||||
dprintk(1, "%s: adapter is unconfigured\n", __func__);
|
||||
return -ENONET;
|
||||
}
|
||||
@@ -1154,7 +1158,9 @@ static int cec_config_log_addr(struct cec_adapter *adap,
|
||||
*/
|
||||
static void cec_adap_unconfigure(struct cec_adapter *adap)
|
||||
{
|
||||
- WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID));
|
||||
+ if (!adap->needs_hpd ||
|
||||
+ adap->phys_addr != CEC_PHYS_ADDR_INVALID)
|
||||
+ WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID));
|
||||
adap->log_addrs.log_addr_mask = 0;
|
||||
adap->is_configuring = false;
|
||||
adap->is_configured = false;
|
||||
@@ -1383,6 +1389,8 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
||||
if (phys_addr == adap->phys_addr || adap->devnode.unregistered)
|
||||
return;
|
||||
|
||||
+ dprintk(1, "new physical address %x.%x.%x.%x\n",
|
||||
+ cec_phys_addr_exp(phys_addr));
|
||||
if (phys_addr == CEC_PHYS_ADDR_INVALID ||
|
||||
adap->phys_addr != CEC_PHYS_ADDR_INVALID) {
|
||||
adap->phys_addr = CEC_PHYS_ADDR_INVALID;
|
||||
@@ -1392,7 +1400,7 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
||||
if (adap->monitor_all_cnt)
|
||||
WARN_ON(call_op(adap, adap_monitor_all_enable, false));
|
||||
mutex_lock(&adap->devnode.lock);
|
||||
- if (list_empty(&adap->devnode.fhs))
|
||||
+ if (adap->needs_hpd || list_empty(&adap->devnode.fhs))
|
||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||
mutex_unlock(&adap->devnode.lock);
|
||||
if (phys_addr == CEC_PHYS_ADDR_INVALID)
|
||||
@@ -1400,7 +1408,7 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
||||
}
|
||||
|
||||
mutex_lock(&adap->devnode.lock);
|
||||
- if (list_empty(&adap->devnode.fhs) &&
|
||||
+ if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) &&
|
||||
adap->ops->adap_enable(adap, true)) {
|
||||
mutex_unlock(&adap->devnode.lock);
|
||||
return;
|
||||
@@ -1408,7 +1416,7 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
||||
|
||||
if (adap->monitor_all_cnt &&
|
||||
call_op(adap, adap_monitor_all_enable, true)) {
|
||||
- if (list_empty(&adap->devnode.fhs))
|
||||
+ if (adap->needs_hpd || list_empty(&adap->devnode.fhs))
|
||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||
mutex_unlock(&adap->devnode.lock);
|
||||
return;
|
||||
diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c
|
||||
index 999926f..f7eb4c5 100644
|
||||
--- a/drivers/media/cec/cec-api.c
|
||||
+++ b/drivers/media/cec/cec-api.c
|
||||
@@ -202,7 +202,8 @@ static long cec_transmit(struct cec_adapter *adap, struct cec_fh *fh,
|
||||
err = -EPERM;
|
||||
else if (adap->is_configuring)
|
||||
err = -ENONET;
|
||||
- else if (!adap->is_configured && msg.msg[0] != 0xf0)
|
||||
+ else if (!adap->is_configured &&
|
||||
+ (adap->needs_hpd || msg.msg[0] != 0xf0))
|
||||
err = -ENONET;
|
||||
else if (cec_is_busy(adap, fh))
|
||||
err = -EBUSY;
|
||||
@@ -515,6 +516,7 @@ static int cec_open(struct inode *inode, struct file *filp)
|
||||
|
||||
mutex_lock(&devnode->lock);
|
||||
if (list_empty(&devnode->fhs) &&
|
||||
+ !adap->needs_hpd &&
|
||||
adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
|
||||
err = adap->ops->adap_enable(adap, true);
|
||||
if (err) {
|
||||
@@ -559,6 +561,7 @@ static int cec_release(struct inode *inode, struct file *filp)
|
||||
mutex_lock(&devnode->lock);
|
||||
list_del(&fh->list);
|
||||
if (list_empty(&devnode->fhs) &&
|
||||
+ !adap->needs_hpd &&
|
||||
adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
|
||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||
}
|
||||
diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c
|
||||
index 2f87748..b516d59 100644
|
||||
--- a/drivers/media/cec/cec-core.c
|
||||
+++ b/drivers/media/cec/cec-core.c
|
||||
@@ -230,6 +230,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
|
||||
adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
|
||||
adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE;
|
||||
adap->capabilities = caps;
|
||||
+ adap->needs_hpd = caps & CEC_CAP_NEEDS_HPD;
|
||||
adap->available_log_addrs = available_las;
|
||||
adap->sequence = 0;
|
||||
adap->ops = ops;
|
||||
diff --git a/include/media/cec.h b/include/media/cec.h
|
||||
index 23c1faa..56643b2 100644
|
||||
--- a/include/media/cec.h
|
||||
+++ b/include/media/cec.h
|
||||
@@ -164,6 +164,7 @@ struct cec_adapter {
|
||||
u8 available_log_addrs;
|
||||
|
||||
u16 phys_addr;
|
||||
+ bool needs_hpd;
|
||||
bool is_configuring;
|
||||
bool is_configured;
|
||||
u32 monitor_all_cnt;
|
||||
diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h
|
||||
index a0dfe27..44579a2 100644
|
||||
--- a/include/uapi/linux/cec.h
|
||||
+++ b/include/uapi/linux/cec.h
|
||||
@@ -336,6 +336,8 @@ static inline int cec_is_unconfigured(__u16 log_addr_mask)
|
||||
#define CEC_CAP_RC (1 << 4)
|
||||
/* Hardware can monitor all messages, not just directed and broadcast. */
|
||||
#define CEC_CAP_MONITOR_ALL (1 << 5)
|
||||
+/* Hardware can use CEC only if the HDMI HPD pin is high. */
|
||||
+#define CEC_CAP_NEEDS_HPD (1 << 6)
|
||||
|
||||
/**
|
||||
* struct cec_caps - CEC capabilities structure.
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
From 3b3c8dc7038a16dfeb29388d6b5afbef869ebc2d Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:05 +0200
|
||||
Subject: [PATCH 25/93] drm: bridge: dw-hdmi: Handle overflow workaround based
|
||||
on device version
|
||||
|
||||
Use the device version queried at runtime instead of the device type
|
||||
provided through platform data to handle the overflow workaround. This
|
||||
will make support of other SoCs integrating the same HDMI TX controller
|
||||
version easier.
|
||||
|
||||
Among the supported platforms only i.MX6DL and i.MX6Q have been
|
||||
identified as needing the workaround. Disabling it on Rockchip RK3288
|
||||
(which integrates a v2.00a controller) didn't produce any error or
|
||||
artifact.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-16-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 46 ++++++++++++++++++++++++++++------------
|
||||
1 file changed, 33 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 730a7558..f4faa14 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -117,8 +117,10 @@ struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
struct drm_bridge bridge;
|
||||
|
||||
- struct platform_device *audio;
|
||||
enum dw_hdmi_devtype dev_type;
|
||||
+ unsigned int version;
|
||||
+
|
||||
+ struct platform_device *audio;
|
||||
struct device *dev;
|
||||
struct clk *isfr_clk;
|
||||
struct clk *iahb_clk;
|
||||
@@ -1323,19 +1325,38 @@ static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
|
||||
/* Workaround to clear the overflow condition */
|
||||
static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- int count;
|
||||
+ unsigned int count;
|
||||
+ unsigned int i;
|
||||
u8 val;
|
||||
|
||||
- /* TMDS software reset */
|
||||
- hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
|
||||
+ /*
|
||||
+ * Under some circumstances the Frame Composer arithmetic unit can miss
|
||||
+ * an FC register write due to being busy processing the previous one.
|
||||
+ * The issue can be worked around by issuing a TMDS software reset and
|
||||
+ * then write one of the FC registers several times.
|
||||
+ *
|
||||
+ * The number of iterations matters and depends on the HDMI TX revision
|
||||
+ * (and possibly on the platform). So far only i.MX6Q (v1.30a) and
|
||||
+ * i.MX6DL (v1.31a) have been identified as needing the workaround, with
|
||||
+ * 4 and 1 iterations respectively.
|
||||
+ */
|
||||
|
||||
- val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
|
||||
- if (hdmi->dev_type == IMX6DL_HDMI) {
|
||||
- hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
|
||||
+ switch (hdmi->version) {
|
||||
+ case 0x130a:
|
||||
+ count = 4;
|
||||
+ break;
|
||||
+ case 0x131a:
|
||||
+ count = 1;
|
||||
+ break;
|
||||
+ default:
|
||||
return;
|
||||
}
|
||||
|
||||
- for (count = 0; count < 4; count++)
|
||||
+ /* TMDS software reset */
|
||||
+ hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
|
||||
+
|
||||
+ val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
|
||||
+ for (i = 0; i < count; i++)
|
||||
hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
|
||||
}
|
||||
|
||||
@@ -1832,7 +1853,6 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
int irq;
|
||||
int ret;
|
||||
u32 val = 1;
|
||||
- u16 version;
|
||||
u8 prod_id0;
|
||||
u8 prod_id1;
|
||||
u8 config0;
|
||||
@@ -1917,21 +1937,21 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
/* Product and revision IDs */
|
||||
- version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
|
||||
- | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
|
||||
+ hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
|
||||
+ | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
|
||||
prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0);
|
||||
prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1);
|
||||
|
||||
if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX ||
|
||||
(prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) {
|
||||
dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n",
|
||||
- version, prod_id0, prod_id1);
|
||||
+ hdmi->version, prod_id0, prod_id1);
|
||||
ret = -ENODEV;
|
||||
goto err_iahb;
|
||||
}
|
||||
|
||||
dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n",
|
||||
- version >> 12, version & 0xfff,
|
||||
+ hdmi->version >> 12, hdmi->version & 0xfff,
|
||||
prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without");
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
From c69ce1e08f7d1eeb8de98544ecc1c1c12fe91408 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:06 +0200
|
||||
Subject: [PATCH 26/93] drm: bridge: dw-hdmi: Detect PHY type at runtime
|
||||
|
||||
Detect the PHY type and use it to handle the PHY type-specific SVSRET
|
||||
signal.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-17-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 68 ++++++++++++++++++++++++++++++++++++++--
|
||||
include/drm/bridge/dw_hdmi.h | 10 ++++++
|
||||
2 files changed, 75 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index f4faa14..ef4f2f9 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -113,6 +113,12 @@ struct dw_hdmi_i2c {
|
||||
bool is_regaddr;
|
||||
};
|
||||
|
||||
+struct dw_hdmi_phy_data {
|
||||
+ enum dw_hdmi_phy_type type;
|
||||
+ const char *name;
|
||||
+ bool has_svsret;
|
||||
+};
|
||||
+
|
||||
struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
struct drm_bridge bridge;
|
||||
@@ -134,7 +140,9 @@ struct dw_hdmi {
|
||||
u8 edid[HDMI_EDID_LEN];
|
||||
bool cable_plugin;
|
||||
|
||||
+ const struct dw_hdmi_phy_data *phy;
|
||||
bool phy_enabled;
|
||||
+
|
||||
struct drm_display_mode previous_mode;
|
||||
|
||||
struct i2c_adapter *ddc;
|
||||
@@ -1015,7 +1023,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
dw_hdmi_phy_gen2_txpwron(hdmi, 1);
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
|
||||
- if (hdmi->dev_type == RK3288_HDMI)
|
||||
+ /* The DWC MHL and HDMI 2.0 PHYs need the SVSRET signal to be set. */
|
||||
+ if (hdmi->phy->has_svsret)
|
||||
dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
|
||||
/*Wait for PHY PLL lock */
|
||||
@@ -1840,6 +1849,54 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
+static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
|
||||
+ {
|
||||
+ .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
|
||||
+ .name = "DWC HDMI TX PHY",
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
|
||||
+ .name = "DWC MHL PHY + HEAC PHY",
|
||||
+ .has_svsret = true,
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_MHL_PHY,
|
||||
+ .name = "DWC MHL PHY",
|
||||
+ .has_svsret = true,
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
|
||||
+ .name = "DWC HDMI 3D TX PHY + HEAC PHY",
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
|
||||
+ .name = "DWC HDMI 3D TX PHY",
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
|
||||
+ .name = "DWC HDMI 2.0 TX PHY",
|
||||
+ .has_svsret = true,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ u8 phy_type;
|
||||
+
|
||||
+ phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
|
||||
+ if (dw_hdmi_phys[i].type == phy_type) {
|
||||
+ hdmi->phy = &dw_hdmi_phys[i];
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
|
||||
+ dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
|
||||
+ else
|
||||
+ dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
|
||||
+ phy_type);
|
||||
+
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
+
|
||||
static struct dw_hdmi *
|
||||
__dw_hdmi_probe(struct platform_device *pdev,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
@@ -1950,9 +2007,14 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
goto err_iahb;
|
||||
}
|
||||
|
||||
- dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n",
|
||||
+ ret = dw_hdmi_detect_phy(hdmi);
|
||||
+ if (ret < 0)
|
||||
+ goto err_iahb;
|
||||
+
|
||||
+ dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
|
||||
hdmi->version >> 12, hdmi->version & 0xfff,
|
||||
- prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without");
|
||||
+ prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
|
||||
+ hdmi->phy->name);
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 3bb22a8..b080a17 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -27,6 +27,16 @@ enum dw_hdmi_devtype {
|
||||
RK3288_HDMI,
|
||||
};
|
||||
|
||||
+enum dw_hdmi_phy_type {
|
||||
+ DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00,
|
||||
+ DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2,
|
||||
+ DW_HDMI_PHY_DWC_MHL_PHY = 0xc2,
|
||||
+ DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC = 0xe2,
|
||||
+ DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY = 0xf2,
|
||||
+ DW_HDMI_PHY_DWC_HDMI20_TX_PHY = 0xf3,
|
||||
+ DW_HDMI_PHY_VENDOR_PHY = 0xfe,
|
||||
+};
|
||||
+
|
||||
struct dw_hdmi_mpll_config {
|
||||
unsigned long mpixelclock;
|
||||
struct {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
From 5337b8bcf8f92396880e95094f639a343ef5453a Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 15:11:42 +0200
|
||||
Subject: [PATCH 26/79] dt-bindings: clock: gxbb: expose audin clock gate
|
||||
|
||||
Expose the clock gate required to power AUDIN block
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/clk/meson/gxbb.h | 2 +-
|
||||
include/dt-bindings/clock/gxbb-clkc.h | 1 +
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
|
||||
index 93b8f07..5c24285 100644
|
||||
--- a/drivers/clk/meson/gxbb.h
|
||||
+++ b/drivers/clk/meson/gxbb.h
|
||||
@@ -205,7 +205,7 @@
|
||||
#define CLKID_HIU_IFACE 32
|
||||
#define CLKID_ASSIST_MISC 33
|
||||
/* CLKID_SPI */
|
||||
-#define CLKID_I2S_SPDIF 35
|
||||
+/* CLKID_I2S_SPDIF */
|
||||
/* CLKID_ETH */
|
||||
#define CLKID_DEMUX 37
|
||||
/* CLKID_AIU_GLUE */
|
||||
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
index 3190e30..ba8a9be 100644
|
||||
--- a/include/dt-bindings/clock/gxbb-clkc.h
|
||||
+++ b/include/dt-bindings/clock/gxbb-clkc.h
|
||||
@@ -17,6 +17,7 @@
|
||||
#define CLKID_SAR_ADC 23
|
||||
#define CLKID_RNG0 25
|
||||
#define CLKID_SPI 34
|
||||
+#define CLKID_I2S_SPDIF 35
|
||||
#define CLKID_ETH 36
|
||||
#define CLKID_AIU_GLUE 38
|
||||
#define CLKID_I2S_OUT 40
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
From d4b067ab4833a89ccbd6c67bf5245621794dbe73 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 11:49:55 +0200
|
||||
Subject: [PATCH 27/79] 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>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@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 c0abad2..7db316f 100644
|
||||
--- a/sound/soc/Kconfig
|
||||
+++ b/sound/soc/Kconfig
|
||||
@@ -55,6 +55,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 39c27a5..d9892c3 100644
|
||||
--- a/sound/soc/Makefile
|
||||
+++ b/sound/soc/Makefile
|
||||
@@ -32,6 +32,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 0000000..216c850
|
||||
--- /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 || COMPILE_TEST
|
||||
+ 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 0000000..22028ab
|
||||
--- /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 0000000..99993ec
|
||||
--- /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 0000000..6e7a24c
|
||||
--- /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_ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
From d7ce5ad1e16494b6881a9b3e641f224f5d27597b Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:07 +0200
|
||||
Subject: [PATCH 27/93] drm: bridge: dw-hdmi: Define and use macros for PHY
|
||||
register addresses
|
||||
|
||||
Replace the hardcoded register address numerical values with macros to
|
||||
clarify the code.
|
||||
|
||||
This change has been tested by comparing the assembly code before and
|
||||
after the change.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-18-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 35 ++++++++++++---------
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 66 ++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 86 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index ef4f2f9..6e605fd 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -997,21 +997,26 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
HDMI_PHY_I2CM_SLAVE_ADDR);
|
||||
hdmi_phy_test_clear(hdmi, 0);
|
||||
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, 0x06);
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, 0x15);
|
||||
-
|
||||
- /* CURRCTRL */
|
||||
- hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], 0x10);
|
||||
-
|
||||
- hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
|
||||
- hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
|
||||
-
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->term, 0x19); /* TXTERM */
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, 0x09); /* CKSYMTXCTRL */
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, 0x0E); /* VLEVCTRL */
|
||||
-
|
||||
- /* REMOVE CLK TERM */
|
||||
- hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
|
||||
+ hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
|
||||
+ HDMI_3D_TX_PHY_CPCE_CTRL);
|
||||
+ hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
|
||||
+ HDMI_3D_TX_PHY_GMPCTRL);
|
||||
+ hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
|
||||
+ HDMI_3D_TX_PHY_CURRCTRL);
|
||||
+
|
||||
+ hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
|
||||
+ hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
|
||||
+ HDMI_3D_TX_PHY_MSM_CTRL);
|
||||
+
|
||||
+ hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
|
||||
+ hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
|
||||
+ HDMI_3D_TX_PHY_CKSYMTXCTRL);
|
||||
+ hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
|
||||
+ HDMI_3D_TX_PHY_VLEVCTRL);
|
||||
+
|
||||
+ /* Override and disable clock termination. */
|
||||
+ hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
|
||||
+ HDMI_3D_TX_PHY_CKCALCTRL);
|
||||
|
||||
dw_hdmi_phy_enable_powerdown(hdmi, false);
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index a4fd64a..f3c149c 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -1085,4 +1085,70 @@ enum {
|
||||
HDMI_I2CM_CTLINT_ARB_MASK = 0x4,
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * HDMI 3D TX PHY registers
|
||||
+ */
|
||||
+#define HDMI_3D_TX_PHY_PWRCTRL 0x00
|
||||
+#define HDMI_3D_TX_PHY_SERDIVCTRL 0x01
|
||||
+#define HDMI_3D_TX_PHY_SERCKCTRL 0x02
|
||||
+#define HDMI_3D_TX_PHY_SERCKKILLCTRL 0x03
|
||||
+#define HDMI_3D_TX_PHY_TXRESCTRL 0x04
|
||||
+#define HDMI_3D_TX_PHY_CKCALCTRL 0x05
|
||||
+#define HDMI_3D_TX_PHY_CPCE_CTRL 0x06
|
||||
+#define HDMI_3D_TX_PHY_TXCLKMEASCTRL 0x07
|
||||
+#define HDMI_3D_TX_PHY_TXMEASCTRL 0x08
|
||||
+#define HDMI_3D_TX_PHY_CKSYMTXCTRL 0x09
|
||||
+#define HDMI_3D_TX_PHY_CMPSEQCTRL 0x0a
|
||||
+#define HDMI_3D_TX_PHY_CMPPWRCTRL 0x0b
|
||||
+#define HDMI_3D_TX_PHY_CMPMODECTRL 0x0c
|
||||
+#define HDMI_3D_TX_PHY_MEASCTRL 0x0d
|
||||
+#define HDMI_3D_TX_PHY_VLEVCTRL 0x0e
|
||||
+#define HDMI_3D_TX_PHY_D2ACTRL 0x0f
|
||||
+#define HDMI_3D_TX_PHY_CURRCTRL 0x10
|
||||
+#define HDMI_3D_TX_PHY_DRVANACTRL 0x11
|
||||
+#define HDMI_3D_TX_PHY_PLLMEASCTRL 0x12
|
||||
+#define HDMI_3D_TX_PHY_PLLPHBYCTRL 0x13
|
||||
+#define HDMI_3D_TX_PHY_GRP_CTRL 0x14
|
||||
+#define HDMI_3D_TX_PHY_GMPCTRL 0x15
|
||||
+#define HDMI_3D_TX_PHY_MPLLMEASCTRL 0x16
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL 0x17
|
||||
+#define HDMI_3D_TX_PHY_SCRPB_STATUS 0x18
|
||||
+#define HDMI_3D_TX_PHY_TXTERM 0x19
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL 0x1a
|
||||
+#define HDMI_3D_TX_PHY_PATTERNGEN 0x1b
|
||||
+#define HDMI_3D_TX_PHY_SDCAP_MODE 0x1c
|
||||
+#define HDMI_3D_TX_PHY_SCOPEMODE 0x1d
|
||||
+#define HDMI_3D_TX_PHY_DIGTXMODE 0x1e
|
||||
+#define HDMI_3D_TX_PHY_STR_STATUS 0x1f
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNT0 0x20
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNT1 0x21
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNT2 0x22
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNTCLK 0x23
|
||||
+#define HDMI_3D_TX_PHY_SCOPESAMPLE 0x24
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNTMSB01 0x25
|
||||
+#define HDMI_3D_TX_PHY_SCOPECNTMSB2CK 0x26
|
||||
+
|
||||
+/* HDMI_3D_TX_PHY_CKCALCTRL values */
|
||||
+#define HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE BIT(15)
|
||||
+
|
||||
+/* HDMI_3D_TX_PHY_MSM_CTRL values */
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_MPLL_PH_SEL_CK BIT(13)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_CLK_REF_MPLL (0 << 1)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_OFF (1 << 1)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_PCLK (2 << 1)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK (3 << 1)
|
||||
+#define HDMI_3D_TX_PHY_MSM_CTRL_SCOPE_CK_SEL BIT(0)
|
||||
+
|
||||
+/* HDMI_3D_TX_PHY_PTRPT_ENBL values */
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_OVERRIDE BIT(15)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT2 BIT(8)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT1 BIT(7)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_PG_SKIP_BIT0 BIT(6)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_CK_REF_ENB BIT(5)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_RCAL_ENB BIT(4)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_CLK_ALIGN_ENB BIT(3)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_TX_READY BIT(2)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_CKO_WORD_ENB BIT(1)
|
||||
+#define HDMI_3D_TX_PHY_PTRPT_ENBL_REFCLK_ENB BIT(0)
|
||||
+
|
||||
#endif /* __DW_HDMI_H__ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,20 +1,25 @@
|
|||
From d8358b5a254018c6329d4da6fb215bcecdfbceae Mon Sep 17 00:00:00 2001
|
||||
From 45ed0fea98d308d6cae17be657dd01d5ee729d87 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 19 Jan 2017 15:49:08 +0100
|
||||
Subject: [PATCH 74/93] snd: meson: add aiu register definitions
|
||||
Date: Thu, 30 Mar 2017 12:00:10 +0200
|
||||
Subject: [PATCH 28/79] ASoC: meson: add register definitions
|
||||
|
||||
Add the register definition for the AIU and AUDIN blocks
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
sound/soc/meson/aiu-regs.h | 186 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 186 insertions(+)
|
||||
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 0000000..3b1945c
|
||||
index 0000000..67391e6
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu-regs.h
|
||||
@@ -0,0 +1,186 @@
|
||||
@@ -0,0 +1,182 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2017 BayLibre, SAS
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
@ -37,10 +42,6 @@ index 0000000..3b1945c
|
|||
+#ifndef _AIU_REGS_H_
|
||||
+#define _AIU_REGS_H_
|
||||
+
|
||||
+/* Base address of AIU within Cbus */
|
||||
+#define AIU_CBUS_BASE 0x5400 /* REALLY USEFUL ??? */
|
||||
+
|
||||
+/* AIU Registers */
|
||||
+#define AIU_958_BPF 0x000
|
||||
+#define AIU_958_BRST 0x004
|
||||
+#define AIU_958_LENGTH 0x008
|
||||
|
@ -85,7 +86,7 @@ index 0000000..3b1945c
|
|||
+#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 /* Unknown */
|
||||
+#define AIU_ACODEC_CTRL 0x0B0
|
||||
+#define AIU_958_CHSTAT_R0 0x0C0
|
||||
+#define AIU_958_CHSTAT_R1 0x0C4
|
||||
+#define AIU_958_VALID_CTRL 0x0C8
|
||||
|
@ -201,6 +202,160 @@ index 0000000..3b1945c
|
|||
+#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 0000000..f224610
|
||||
--- /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_ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
From 9e151c1acfd889a938f6f49bb07b14c101fa56d5 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:08 +0200
|
||||
Subject: [PATCH 28/93] drm: bridge: dw-hdmi: Fix the name of the PHY reset
|
||||
macros
|
||||
|
||||
The PHY reset signal is controlled by bit PHYRSTZ in the MC_PHYRSTZ
|
||||
register. The signal is active low on Gen1 PHYs and active high on Gen2
|
||||
PHYs. The driver toggles the signal high then low, which is correct for
|
||||
all currently supported platforms, but the register values macros are
|
||||
incorrectly named. Replace them with a single macro named after the bit,
|
||||
and add a comment to the source code to explain the behaviour.
|
||||
|
||||
The driver's behaviour isn't changed by this rename, the code will still
|
||||
need to be fixed to support Gen1 PHYs.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-19-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 6 +++---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.h | 3 +--
|
||||
2 files changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 6e605fd..93e8816 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -986,9 +986,9 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
/* gen2 pddq */
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
|
||||
- /* PHY reset */
|
||||
- hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
|
||||
- hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
|
||||
+ /* PHY reset. The reset signal is active high on Gen2 PHYs. */
|
||||
+ hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ);
|
||||
+ hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ);
|
||||
|
||||
hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
index f3c149c..325b0b8 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.h
|
||||
@@ -989,8 +989,7 @@ enum {
|
||||
HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0,
|
||||
|
||||
/* MC_PHYRSTZ field values */
|
||||
- HDMI_MC_PHYRSTZ_ASSERT = 0x0,
|
||||
- HDMI_MC_PHYRSTZ_DEASSERT = 0x1,
|
||||
+ HDMI_MC_PHYRSTZ_PHYRSTZ = 0x01,
|
||||
|
||||
/* MC_HEACPHY_RST field values */
|
||||
HDMI_MC_HEACPHY_RST_ASSERT = 0x1,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,163 +1,50 @@
|
|||
From 0a351cf435e75a028694a7d5782f2b46582b004d Mon Sep 17 00:00:00 2001
|
||||
From 98fd2d06e53a52a033317864b317549e6f3e9245 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Sun, 12 Feb 2017 00:50:07 +0100
|
||||
Subject: [PATCH 76/93] snd: soc: meson: support for aiu i2s dma
|
||||
Date: Thu, 30 Mar 2017 12:14:40 +0200
|
||||
Subject: [PATCH 29/79] ASoC: meson: add aiu i2s dma support
|
||||
|
||||
Initial support for meson aiu i2s dma
|
||||
TO BE COMPLETED ...
|
||||
Add support for the i2s output dma which is part of the AIU block
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
sound/soc/Kconfig | 1 +
|
||||
sound/soc/Makefile | 1 +
|
||||
sound/soc/meson/Kconfig | 17 ++
|
||||
sound/soc/meson/Kconfig | 7 +
|
||||
sound/soc/meson/Makefile | 2 +
|
||||
sound/soc/meson/aiu-common.c | 69 ++++++++
|
||||
sound/soc/meson/aiu-i2s-dma.c | 400 ++++++++++++++++++++++++++++++++++++++++++
|
||||
sound/soc/meson/aiu.h | 6 +
|
||||
7 files changed, 496 insertions(+)
|
||||
create mode 100644 sound/soc/meson/Kconfig
|
||||
create mode 100644 sound/soc/meson/Makefile
|
||||
create mode 100644 sound/soc/meson/aiu-common.c
|
||||
sound/soc/meson/aiu-i2s-dma.c | 367 ++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 376 insertions(+)
|
||||
create mode 100644 sound/soc/meson/aiu-i2s-dma.c
|
||||
create mode 100644 sound/soc/meson/aiu.h
|
||||
|
||||
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
|
||||
index 182d92e..58ed5cf 100644
|
||||
--- a/sound/soc/Kconfig
|
||||
+++ b/sound/soc/Kconfig
|
||||
@@ -54,6 +54,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 9a30f21..fbe16ac 100644
|
||||
--- a/sound/soc/Makefile
|
||||
+++ b/sound/soc/Makefile
|
||||
@@ -31,6 +31,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 0000000..f2504c6
|
||||
--- /dev/null
|
||||
index 216c850..ad31a11 100644
|
||||
--- a/sound/soc/meson/Kconfig
|
||||
+++ b/sound/soc/meson/Kconfig
|
||||
@@ -0,0 +1,17 @@
|
||||
+menu "Amlogic SoC Audio Support"
|
||||
+ depends on ARCH_MESON || COMPILE_TEST
|
||||
@@ -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_MESON_AIU_I2S_DMA
|
||||
+ tristate "Meson I2S Output DMA Support"
|
||||
+ select MFD_SYSCON
|
||||
+ select SND_MESON_AIU_COMMON
|
||||
+config SND_SOC_MESON_I2S
|
||||
+ tristate "Meson i2s interface"
|
||||
+ depends on SND_SOC_MESON
|
||||
+ help
|
||||
+ This adds ASoC driver the Amlogic Meson i2s DAI
|
||||
+ If unsure select "N".
|
||||
+
|
||||
+endmenu
|
||||
+
|
||||
+config SND_MESON_AIU_COMMON
|
||||
+ tristate
|
||||
+ depends on ARCH_MESON
|
||||
+ depends on REGMAP_MMIO
|
||||
+ 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
|
||||
new file mode 100644
|
||||
index 0000000..b237894
|
||||
--- /dev/null
|
||||
index 22028ab..273f275 100644
|
||||
--- a/sound/soc/meson/Makefile
|
||||
+++ b/sound/soc/meson/Makefile
|
||||
@@ -0,0 +1,2 @@
|
||||
+obj-$(CONFIG_SND_MESON_AIU_COMMON) += aiu-common.o
|
||||
+obj-$(CONFIG_SND_MESON_AIU_I2S_DMA) += aiu-i2s-dma.o
|
||||
diff --git a/sound/soc/meson/aiu-common.c b/sound/soc/meson/aiu-common.c
|
||||
new file mode 100644
|
||||
index 0000000..9beee94
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu-common.c
|
||||
@@ -0,0 +1,69 @@
|
||||
+/*
|
||||
+ * 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/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+
|
||||
+static const char* aiu_gate_names[] = { "aiu_top", "aiu_glue" };
|
||||
+
|
||||
+static int aiu_common_register_clk_gates(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct clk *gate;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(aiu_gate_names); i++) {
|
||||
+ gate = devm_clk_get(dev, aiu_gate_names[i]);
|
||||
+ if (IS_ERR(gate)) {
|
||||
+ if (PTR_ERR(gate) != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "Failed to get %s clock gate\n",
|
||||
+ aiu_gate_names[i]);
|
||||
+ return PTR_ERR(gate);
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(gate);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to enable %s clock gate\n",
|
||||
+ aiu_gate_names[i]);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int aiu_common_register(struct platform_device *pdev)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = aiu_common_register_clk_gates(pdev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* FIXME: We should also handle the AIU reset here */
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(aiu_common_register);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Meson AIU common helper");
|
||||
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
@@ -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 0000000..1e8886c
|
||||
index 0000000..bab950d
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu-i2s-dma.c
|
||||
@@ -0,0 +1,400 @@
|
||||
@@ -0,0 +1,367 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2017 BayLibre, SAS
|
||||
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
@ -177,8 +64,6 @@ index 0000000..1e8886c
|
|||
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/module.h>
|
||||
|
@ -189,16 +74,14 @@ index 0000000..1e8886c
|
|||
+#include <sound/pcm_params.h>
|
||||
+#include <sound/soc.h>
|
||||
+
|
||||
+#include "aiu.h"
|
||||
+#include "aiu-regs.h"
|
||||
+#include "audio-core.h"
|
||||
+
|
||||
+#define DRV_NAME "meson-aiu-i2s-dma"
|
||||
+
|
||||
+struct aiu_i2s_dma {
|
||||
+ struct regmap* regmap;
|
||||
+
|
||||
+ struct clk* i2s_out;
|
||||
+
|
||||
+ struct meson_audio_core_data *core;
|
||||
+ struct clk *fast;
|
||||
+ int irq;
|
||||
+};
|
||||
+
|
||||
|
@ -218,21 +101,17 @@ index 0000000..1e8886c
|
|||
+#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)
|
||||
+#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)
|
||||
+
|
||||
+/*
|
||||
+ * 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 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.
|
||||
+ * - 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,
|
||||
|
@ -265,20 +144,20 @@ index 0000000..1e8886c
|
|||
+ .channels_min = 2,
|
||||
+ .channels_max = 8,
|
||||
+ .period_bytes_min = AIU_I2S_DMA_BURST,
|
||||
+ .period_bytes_max = AIU_I2S_DMA_BURST * 65535, /* 8192, */
|
||||
+ .period_bytes_max = AIU_I2S_DMA_BURST * 65535,
|
||||
+ .periods_min = 2,
|
||||
+ .periods_max = UINT_MAX,
|
||||
+ .buffer_bytes_max = 1* 1024 * 1024,
|
||||
+ .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;
|
||||
+
|
||||
+ return snd_soc_platform_get_drvdata(rtd->platform);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static snd_pcm_uframes_t
|
||||
+aiu_i2s_dma_pointer(struct snd_pcm_substream *substream)
|
||||
+{
|
||||
|
@ -287,7 +166,7 @@ index 0000000..1e8886c
|
|||
+ unsigned int addr;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = regmap_read(priv->regmap, AIU_MEM_I2S_RD_PTR,
|
||||
+ ret = regmap_read(priv->core->aiu, AIU_MEM_I2S_RD_PTR,
|
||||
+ &addr);
|
||||
+ if (ret)
|
||||
+ return 0;
|
||||
|
@ -300,7 +179,7 @@ index 0000000..1e8886c
|
|||
+ unsigned int en_mask = (AIU_MEM_I2S_CONTROL_FILL_EN |
|
||||
+ AIU_MEM_I2S_CONTROL_EMPTY_EN);
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_CONTROL, en_mask,
|
||||
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_CONTROL, en_mask,
|
||||
+ enable ? en_mask : 0);
|
||||
+
|
||||
+}
|
||||
|
@ -329,17 +208,17 @@ index 0000000..1e8886c
|
|||
+
|
||||
+static void __dma_init_mem(struct aiu_i2s_dma *priv)
|
||||
+{
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_CONTROL,
|
||||
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_CONTROL,
|
||||
+ AIU_MEM_I2S_CONTROL_INIT,
|
||||
+ AIU_MEM_I2S_CONTROL_INIT);
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_BUF_CNTL,
|
||||
+ 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->regmap, AIU_MEM_I2S_CONTROL,
|
||||
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_CONTROL,
|
||||
+ AIU_MEM_I2S_CONTROL_INIT,
|
||||
+ 0);
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_BUF_CNTL,
|
||||
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_BUF_CNTL,
|
||||
+ AIU_MEM_I2S_BUF_CNTL_INIT,
|
||||
+ 0);
|
||||
+}
|
||||
|
@ -359,7 +238,7 @@ index 0000000..1e8886c
|
|||
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
|
||||
+ int ret;
|
||||
+ u32 burst_num, desc = 0, mem_ctl = 0;
|
||||
+ u32 burst_num, mem_ctl;
|
||||
+ dma_addr_t end_ptr;
|
||||
+
|
||||
+ ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
|
||||
|
@ -367,48 +246,26 @@ index 0000000..1e8886c
|
|||
+ return ret;
|
||||
+
|
||||
+ /* Setup memory layout */
|
||||
+ if (params_physical_width(params) == 16) {
|
||||
+ mem_ctl |= AIU_MEM_I2S_CONTROL_MODE_16BIT;
|
||||
+ } else {
|
||||
+ desc |= AIU_I2S_SOURCE_DESC_MODE_24BIT;
|
||||
+ desc |= AIU_I2S_SOURCE_DESC_MODE_32BIT;
|
||||
+ }
|
||||
+ if (params_physical_width(params) == 16)
|
||||
+ mem_ctl = AIU_MEM_I2S_CONTROL_MODE_16BIT;
|
||||
+ else
|
||||
+ mem_ctl = 0;
|
||||
+
|
||||
+ switch (params_channels(params)) {
|
||||
+ case 2: /* Nothing to do */
|
||||
+ break;
|
||||
+ case 8:
|
||||
+ desc |= AIU_I2S_SOURCE_DESC_MODE_8CH;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* Enable split mode - samples interleaved */
|
||||
+ desc |= AIU_I2S_SOURCE_DESC_MODE_SPLIT;
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_MEM_I2S_CONTROL,
|
||||
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_CONTROL,
|
||||
+ AIU_MEM_I2S_CONTROL_MODE_16BIT,
|
||||
+ mem_ctl);
|
||||
+
|
||||
+ regmap_update_bits(priv->regmap, AIU_I2S_SOURCE_DESC,
|
||||
+ AIU_I2S_SOURCE_DESC_MODE_8CH |
|
||||
+ AIU_I2S_SOURCE_DESC_MODE_24BIT |
|
||||
+ AIU_I2S_SOURCE_DESC_MODE_32BIT |
|
||||
+ AIU_I2S_SOURCE_DESC_MODE_SPLIT,
|
||||
+ desc);
|
||||
+
|
||||
+ /* Initialize memory pointers */
|
||||
+ regmap_write(priv->regmap, AIU_MEM_I2S_START_PTR, runtime->dma_addr);
|
||||
+ regmap_write(priv->regmap, AIU_MEM_I2S_RD_PTR, runtime->dma_addr);
|
||||
+ 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->regmap, AIU_MEM_I2S_END_PTR, end_ptr);
|
||||
+ 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->regmap, AIU_MEM_I2S_MASKS,
|
||||
+ 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));
|
||||
|
@ -456,22 +313,26 @@ index 0000000..1e8886c
|
|||
+
|
||||
+ /* Request the I2S DDR irq */
|
||||
+ ret = request_irq(priv->irq, aiu_i2s_dma_irq_block, 0,
|
||||
+ "meson-aiu-i2s-block", substream);
|
||||
+ DRV_NAME, substream);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Enable the DDR to FIFO clock gate */
|
||||
+ return clk_prepare_enable(priv->i2s_out);
|
||||
+ /* 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);
|
||||
+
|
||||
+ /* First close the clock gate so the DMA is definitely halted */
|
||||
+ clk_disable_unprepare(priv->i2s_out);
|
||||
+
|
||||
+ /* Free the irq */
|
||||
+ clk_disable_unprepare(priv->fast);
|
||||
+ free_irq(priv->irq, substream);
|
||||
+
|
||||
+ return 0;
|
||||
|
@ -507,28 +368,19 @@ index 0000000..1e8886c
|
|||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct aiu_i2s_dma *priv;
|
||||
+ int ret;
|
||||
+
|
||||
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if(!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);
|
||||
+
|
||||
+ ret = aiu_common_register(pdev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ priv->regmap = syscon_node_to_regmap(dev->parent->of_node);
|
||||
+ if (IS_ERR(priv->regmap)) {
|
||||
+ dev_err(dev, "failed to get our regmap\n");
|
||||
+ return PTR_ERR(priv->regmap);
|
||||
+ }
|
||||
+
|
||||
+ priv->i2s_out = devm_clk_get(dev, "i2s_out");
|
||||
+ if (IS_ERR(priv->i2s_out)) {
|
||||
+ if(PTR_ERR(priv->i2s_out) != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "Can't get i2s_out\n");
|
||||
+ return PTR_ERR(priv->i2s_out);
|
||||
+ 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);
|
||||
|
@ -540,17 +392,19 @@ index 0000000..1e8886c
|
|||
+ return snd_soc_register_platform(dev, &aiu_i2s_platform);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id aiu_i2s_dma_match[] = {
|
||||
+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_match);
|
||||
+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_match,
|
||||
+ .of_match_table = aiu_i2s_dma_of_match,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(aiu_i2s_dma_pdrv);
|
||||
|
@ -558,18 +412,6 @@ index 0000000..1e8886c
|
|||
+MODULE_DESCRIPTION("Meson AIU i2s DMA ASoC Driver");
|
||||
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h
|
||||
new file mode 100644
|
||||
index 0000000..a9d1c58
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu.h
|
||||
@@ -0,0 +1,6 @@
|
||||
+#ifndef _AIU_H_
|
||||
+#define _AIU_H_
|
||||
+
|
||||
+int aiu_common_register(struct platform_device *pdev);
|
||||
+
|
||||
+#endif /* _AIU_H_ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
From 9faac4dec35ecb92a6eb348a0904b5484b89df72 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Tue, 17 Jan 2017 10:29:09 +0200
|
||||
Subject: [PATCH 29/93] drm: bridge: dw-hdmi: Assert SVSRET before resetting
|
||||
the PHY
|
||||
|
||||
According to the PHY IP core vendor, the SVSRET signal must be asserted
|
||||
before resetting the PHY. Tests on RK3288 and R-Car Gen3 showed no
|
||||
regression, the change should thus be safe.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170117082910.27023-20-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 93e8816..4fda071 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -986,6 +986,10 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
/* gen2 pddq */
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
|
||||
+ /* Leave low power consumption mode by asserting SVSRET. */
|
||||
+ if (hdmi->phy->has_svsret)
|
||||
+ dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
+
|
||||
/* PHY reset. The reset signal is active high on Gen2 PHYs. */
|
||||
hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ);
|
||||
hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ);
|
||||
@@ -1028,11 +1032,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
dw_hdmi_phy_gen2_txpwron(hdmi, 1);
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
|
||||
- /* The DWC MHL and HDMI 2.0 PHYs need the SVSRET signal to be set. */
|
||||
- if (hdmi->phy->has_svsret)
|
||||
- dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
-
|
||||
- /*Wait for PHY PLL lock */
|
||||
+ /* Wait for PHY PLL lock */
|
||||
msec = 5;
|
||||
do {
|
||||
val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,515 @@
|
|||
From e976fda45f89573b89d118ded17112aae8a0f8f5 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 12:17:27 +0200
|
||||
Subject: [PATCH 30/79] 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>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@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 ad31a11..604c9e2 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 273f275..ea06dde 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 0000000..1008af8
|
||||
--- /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");
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
From e9b6ad390a468f272176a6ceb103d63a46094be4 Mon Sep 17 00:00:00 2001
|
||||
From: Arnd Bergmann <arnd@arndb.de>
|
||||
Date: Mon, 23 Jan 2017 13:20:38 +0100
|
||||
Subject: [PATCH 30/93] drm: bridge: dw-hdmi: fix building without CONFIG_OF
|
||||
|
||||
The of_node member in struct drm_bridge is hidden when CONFIG_OF
|
||||
is disabled, causing a build error:
|
||||
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c: In function '__dw_hdmi_probe':
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c:2063:14: error: 'struct drm_bridge' has no member named 'of_node'
|
||||
|
||||
We could fix this either using a Kconfig dependency on CONFIG_OF
|
||||
or making the one line conditional. The latter gives us better
|
||||
compile test coverage, so this is what I'm doing here.
|
||||
|
||||
Fixes: 69497eb9234e ("drm: bridge: dw-hdmi: Implement DRM bridge registration")
|
||||
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170123122312.3290934-1-arnd@arndb.de
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 4fda071..9a9ec27 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -2060,7 +2060,9 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
|
||||
hdmi->bridge.driver_private = hdmi;
|
||||
hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
|
||||
+#ifdef CONFIG_OF
|
||||
hdmi->bridge.of_node = pdev->dev.of_node;
|
||||
+#endif
|
||||
|
||||
ret = dw_hdmi_fb_registered(hdmi);
|
||||
if (ret)
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,439 @@
|
|||
From e3ad81320cb0d2282f7a31bceab130bf4105a711 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 13:43:52 +0200
|
||||
Subject: [PATCH 31/79] 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>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
sound/soc/meson/Kconfig | 7 +
|
||||
sound/soc/meson/Makefile | 2 +
|
||||
sound/soc/meson/aiu-spdif-dma.c | 385 ++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 394 insertions(+)
|
||||
create mode 100644 sound/soc/meson/aiu-spdif-dma.c
|
||||
|
||||
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
|
||||
index 604c9e2..8af3258 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 ea06dde..cef9a9d 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 0000000..e3ff74b
|
||||
--- /dev/null
|
||||
+++ b/sound/soc/meson/aiu-spdif-dma.c
|
||||
@@ -0,0 +1,385 @@
|
||||
+/*
|
||||
+ * 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;
|
||||
+
|
||||
+ return snd_soc_platform_get_drvdata(rtd->platform);
|
||||
+}
|
||||
+
|
||||
+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);
|
||||
+}
|
||||
+
|
||||
+struct snd_soc_platform_driver aiu_spdif_platform = {
|
||||
+ .ops = &aiu_spdif_dma_ops,
|
||||
+ .pcm_new = aiu_spdif_dma_new,
|
||||
+};
|
||||
+
|
||||
+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 snd_soc_register_platform(dev, &aiu_spdif_platform);
|
||||
+}
|
||||
+
|
||||
+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");
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
From 1ab78b07672b5e80bff302b1f2fab863a3107f2e Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 19:19:58 +0200
|
||||
Subject: [PATCH 31/93] drm: bridge: dw-hdmi: Remove unused functions
|
||||
|
||||
Most of the hdmi_phy_test_*() functions are unused. Remove them.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Tested-by: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-2-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 26 --------------------------
|
||||
1 file changed, 26 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 9a9ec27..ce74963 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -837,32 +837,6 @@ static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
|
||||
HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
|
||||
}
|
||||
|
||||
-static inline void hdmi_phy_test_enable(struct dw_hdmi *hdmi,
|
||||
- unsigned char bit)
|
||||
-{
|
||||
- hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
|
||||
- HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
|
||||
-}
|
||||
-
|
||||
-static inline void hdmi_phy_test_clock(struct dw_hdmi *hdmi,
|
||||
- unsigned char bit)
|
||||
-{
|
||||
- hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
|
||||
- HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
|
||||
-}
|
||||
-
|
||||
-static inline void hdmi_phy_test_din(struct dw_hdmi *hdmi,
|
||||
- unsigned char bit)
|
||||
-{
|
||||
- hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
|
||||
-}
|
||||
-
|
||||
-static inline void hdmi_phy_test_dout(struct dw_hdmi *hdmi,
|
||||
- unsigned char bit)
|
||||
-{
|
||||
- hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
|
||||
-}
|
||||
-
|
||||
static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
|
||||
{
|
||||
u32 val;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,430 @@
|
|||
From f526e3ef0f6b52f591d93f2a68f25dd6062b592c Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 13:46:03 +0200
|
||||
Subject: [PATCH 32/79] 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>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@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 8af3258..92422e7 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 cef9a9d..bc4391c 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 0000000..e763000
|
||||
--- /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");
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
From 83ea2ac12ecbd8d77aa2ac7c3effcdac8301ef26 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 19:19:59 +0200
|
||||
Subject: [PATCH 32/93] drm: bridge: dw-hdmi: Move CSC configuration out of PHY
|
||||
code
|
||||
|
||||
The color space converter isn't part of the PHY, move its configuration
|
||||
out of PHY code.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-3-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 25 ++++++++++---------------
|
||||
1 file changed, 10 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index ce74963..906583b 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -914,7 +914,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
||||
}
|
||||
|
||||
-static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
+static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
{
|
||||
u8 val, msec;
|
||||
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
@@ -946,14 +946,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- /* Enable csc path */
|
||||
- if (cscon)
|
||||
- val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
|
||||
- else
|
||||
- val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
|
||||
-
|
||||
- hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
|
||||
-
|
||||
/* gen2 tx power off */
|
||||
dw_hdmi_phy_gen2_txpwron(hdmi, 0);
|
||||
|
||||
@@ -1028,10 +1020,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
|
||||
static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
{
|
||||
int i, ret;
|
||||
- bool cscon;
|
||||
-
|
||||
- /*check csc whether needed activated in HDMI mode */
|
||||
- cscon = hdmi->sink_is_hdmi && is_color_space_conversion(hdmi);
|
||||
|
||||
/* HDMI Phy spec says to do the phy initialization sequence twice */
|
||||
for (i = 0; i < 2; i++) {
|
||||
@@ -1040,8 +1028,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
|
||||
- /* Enable CSC */
|
||||
- ret = hdmi_phy_configure(hdmi, cscon);
|
||||
+ ret = hdmi_phy_configure(hdmi);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -1303,6 +1290,14 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
|
||||
clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
|
||||
hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
|
||||
}
|
||||
+
|
||||
+ /* Enable color space conversion if needed (for HDMI sinks only). */
|
||||
+ if (hdmi->sink_is_hdmi && is_color_space_conversion(hdmi))
|
||||
+ hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
|
||||
+ HDMI_MC_FLOWCTRL);
|
||||
+ else
|
||||
+ hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
|
||||
+ HDMI_MC_FLOWCTRL);
|
||||
}
|
||||
|
||||
static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
From f0bd8f7b16c1d75d562e0731704e96efa6ea3966 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Fri, 31 Mar 2017 15:55:03 +0200
|
||||
Subject: [PATCH 33/79] 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>
|
||||
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 97c123e..cd4114f 100644
|
||||
--- a/arch/arm64/configs/defconfig
|
||||
+++ b/arch/arm64/configs/defconfig
|
||||
@@ -365,6 +365,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=y
|
||||
CONFIG_SND_SOC_AK4613=y
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
From 63411a28c0aad6f7df41c8d835d479d45ca35101 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 3 Mar 2017 19:20:00 +0200
|
||||
Subject: [PATCH 33/93] drm: bridge: dw-hdmi: Enable CSC even for DVI
|
||||
|
||||
If the input pixel format is not RGB, the CSC must be enabled in order to
|
||||
provide valid pixel to DVI sinks.
|
||||
This patch removes the hdmi only dependency on the CSC enabling.
|
||||
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-4-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 906583b..d863b33 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -1291,8 +1291,8 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
|
||||
hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
|
||||
}
|
||||
|
||||
- /* Enable color space conversion if needed (for HDMI sinks only). */
|
||||
- if (hdmi->sink_is_hdmi && is_color_space_conversion(hdmi))
|
||||
+ /* Enable color space conversion if needed */
|
||||
+ if (is_color_space_conversion(hdmi))
|
||||
hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
|
||||
HDMI_MC_FLOWCTRL);
|
||||
else
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
From 25b66766a7ebe95b2f083f27a808997d8438842c Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Fri, 31 Mar 2017 15:52:11 +0200
|
||||
Subject: [PATCH 34/79] ARM64: defconfig: enable CONFIG_SND_SOC_ES7134 as
|
||||
module
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/configs/defconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
|
||||
index cd4114f..21f519d 100644
|
||||
--- a/arch/arm64/configs/defconfig
|
||||
+++ b/arch/arm64/configs/defconfig
|
||||
@@ -372,6 +372,7 @@ CONFIG_SND_SOC_RCAR=y
|
||||
CONFIG_SND_SOC_SAMSUNG=y
|
||||
CONFIG_SND_SOC_RCAR=y
|
||||
CONFIG_SND_SOC_AK4613=y
|
||||
+CONFIG_SND_SOC_ES7134=m
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_OTG=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
From 4910824c44da97e1e8f1b934e75d0d40aaabaddc Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Mon, 6 Mar 2017 01:35:39 +0200
|
||||
Subject: [PATCH 34/93] drm: bridge: dw-hdmi: Fix the PHY power down sequence
|
||||
|
||||
The PHY requires us to wait for the PHY to switch to low power mode
|
||||
after deasserting TXPWRON and before asserting PDDQ in the power down
|
||||
sequence, otherwise power down will fail.
|
||||
|
||||
The PHY power down can be monitored though the TX_READY bit, available
|
||||
through I2C in the PHY registers, or the TX_PHY_LOCK bit, available
|
||||
through the HDMI TX registers. As the two are equivalent, let's pick the
|
||||
easier solution of polling the TX_PHY_LOCK bit.
|
||||
|
||||
The power down code is currently duplicated in multiple places. To avoid
|
||||
spreading multiple calls to a TX_PHY_LOCK poll function, we have to
|
||||
refactor the power down code and group it all in a single function.
|
||||
|
||||
Tests showed that one poll iteration was enough for TX_PHY_LOCK to
|
||||
become low, without requiring any additional delay. Retrying the read
|
||||
five times with a 1ms to 2ms delay between each attempt should thus be
|
||||
more than enough.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170305233539.11898-1-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 52 +++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 43 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index d863b33..3a1cd4c 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -116,6 +116,7 @@ struct dw_hdmi_i2c {
|
||||
struct dw_hdmi_phy_data {
|
||||
enum dw_hdmi_phy_type type;
|
||||
const char *name;
|
||||
+ unsigned int gen;
|
||||
bool has_svsret;
|
||||
};
|
||||
|
||||
@@ -914,6 +915,40 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
||||
}
|
||||
|
||||
+static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy;
|
||||
+ unsigned int i;
|
||||
+ u16 val;
|
||||
+
|
||||
+ if (phy->gen == 1) {
|
||||
+ dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
+ dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ dw_hdmi_phy_gen2_txpwron(hdmi, 0);
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went
|
||||
+ * to low power mode.
|
||||
+ */
|
||||
+ for (i = 0; i < 5; ++i) {
|
||||
+ val = hdmi_readb(hdmi, HDMI_PHY_STAT0);
|
||||
+ if (!(val & HDMI_PHY_TX_PHY_LOCK))
|
||||
+ break;
|
||||
+
|
||||
+ usleep_range(1000, 2000);
|
||||
+ }
|
||||
+
|
||||
+ if (val & HDMI_PHY_TX_PHY_LOCK)
|
||||
+ dev_warn(hdmi->dev, "PHY failed to power down\n");
|
||||
+ else
|
||||
+ dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i);
|
||||
+
|
||||
+ dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
+}
|
||||
+
|
||||
static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
{
|
||||
u8 val, msec;
|
||||
@@ -946,11 +981,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- /* gen2 tx power off */
|
||||
- dw_hdmi_phy_gen2_txpwron(hdmi, 0);
|
||||
-
|
||||
- /* gen2 pddq */
|
||||
- dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
+ dw_hdmi_phy_power_off(hdmi);
|
||||
|
||||
/* Leave low power consumption mode by asserting SVSRET. */
|
||||
if (hdmi->phy->has_svsret)
|
||||
@@ -1025,8 +1056,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
for (i = 0; i < 2; i++) {
|
||||
dw_hdmi_phy_sel_data_en_pol(hdmi, 1);
|
||||
dw_hdmi_phy_sel_interface_control(hdmi, 0);
|
||||
- dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
- dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
|
||||
ret = hdmi_phy_configure(hdmi);
|
||||
if (ret)
|
||||
@@ -1256,8 +1285,7 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
|
||||
if (!hdmi->phy_enabled)
|
||||
return;
|
||||
|
||||
- dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
- dw_hdmi_phy_enable_powerdown(hdmi, true);
|
||||
+ dw_hdmi_phy_power_off(hdmi);
|
||||
|
||||
hdmi->phy_enabled = false;
|
||||
}
|
||||
@@ -1827,23 +1855,29 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
{
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
|
||||
.name = "DWC HDMI TX PHY",
|
||||
+ .gen = 1,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
|
||||
.name = "DWC MHL PHY + HEAC PHY",
|
||||
+ .gen = 2,
|
||||
.has_svsret = true,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_MHL_PHY,
|
||||
.name = "DWC MHL PHY",
|
||||
+ .gen = 2,
|
||||
.has_svsret = true,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
|
||||
.name = "DWC HDMI 3D TX PHY + HEAC PHY",
|
||||
+ .gen = 2,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
|
||||
.name = "DWC HDMI 3D TX PHY",
|
||||
+ .gen = 2,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
|
||||
.name = "DWC HDMI 2.0 TX PHY",
|
||||
+ .gen = 2,
|
||||
.has_svsret = true,
|
||||
}
|
||||
};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
From e23a5c9ce63bcacd81a63ed7f5a3049138de9cb0 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Fri, 31 Mar 2017 15:50:39 +0200
|
||||
Subject: [PATCH 35/79] ARM64: defconfig: enable CONFIG_SND_SOC_DIO2125 as
|
||||
module
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/configs/defconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
|
||||
index 21f519d..6fe57e4 100644
|
||||
--- a/arch/arm64/configs/defconfig
|
||||
+++ b/arch/arm64/configs/defconfig
|
||||
@@ -372,6 +372,7 @@ CONFIG_SND_SOC_RCAR=y
|
||||
CONFIG_SND_SOC_SAMSUNG=y
|
||||
CONFIG_SND_SOC_RCAR=y
|
||||
CONFIG_SND_SOC_AK4613=y
|
||||
+CONFIG_SND_SOC_DIO2125=m
|
||||
CONFIG_SND_SOC_ES7134=m
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_OTG=y
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
From be5d590fc7021d9fa4aa9acd528f72047e8fd82b Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Mon, 6 Mar 2017 01:35:57 +0200
|
||||
Subject: [PATCH 35/93] drm: bridge: dw-hdmi: Fix the PHY power up sequence
|
||||
|
||||
When powering the PHY up we need to wait for the PLL to lock. This is
|
||||
done by polling the TX_PHY_LOCK bit in the HDMI_PHY_STAT0 register
|
||||
(interrupt-based wait could be implemented as well but is likely
|
||||
overkill). The bit is asserted when the PLL locks, but the current code
|
||||
incorrectly waits for the bit to be deasserted. Fix it, and while at it,
|
||||
replace the udelay() with a sleep as the code never runs in
|
||||
non-sleepable context.
|
||||
|
||||
To be consistent with the power down implementation move the poll loop
|
||||
to the power off function.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170305233557.11945-1-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 65 +++++++++++++++++++++++-----------------
|
||||
1 file changed, 37 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 3a1cd4c..c25eac8 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -949,9 +949,44 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
}
|
||||
|
||||
+static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy;
|
||||
+ unsigned int i;
|
||||
+ u8 val;
|
||||
+
|
||||
+ if (phy->gen == 1) {
|
||||
+ dw_hdmi_phy_enable_powerdown(hdmi, false);
|
||||
+
|
||||
+ /* Toggle TMDS enable. */
|
||||
+ dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
+ dw_hdmi_phy_enable_tmds(hdmi, 1);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ dw_hdmi_phy_gen2_txpwron(hdmi, 1);
|
||||
+ dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
+
|
||||
+ /* Wait for PHY PLL lock */
|
||||
+ for (i = 0; i < 5; ++i) {
|
||||
+ val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
|
||||
+ if (val)
|
||||
+ break;
|
||||
+
|
||||
+ usleep_range(1000, 2000);
|
||||
+ }
|
||||
+
|
||||
+ if (!val) {
|
||||
+ dev_err(hdmi->dev, "PHY PLL failed to lock\n");
|
||||
+ return -ETIMEDOUT;
|
||||
+ }
|
||||
+
|
||||
+ dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- u8 val, msec;
|
||||
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
@@ -1019,33 +1054,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
|
||||
HDMI_3D_TX_PHY_CKCALCTRL);
|
||||
|
||||
- dw_hdmi_phy_enable_powerdown(hdmi, false);
|
||||
-
|
||||
- /* toggle TMDS enable */
|
||||
- dw_hdmi_phy_enable_tmds(hdmi, 0);
|
||||
- dw_hdmi_phy_enable_tmds(hdmi, 1);
|
||||
-
|
||||
- /* gen2 tx power on */
|
||||
- dw_hdmi_phy_gen2_txpwron(hdmi, 1);
|
||||
- dw_hdmi_phy_gen2_pddq(hdmi, 0);
|
||||
-
|
||||
- /* Wait for PHY PLL lock */
|
||||
- msec = 5;
|
||||
- do {
|
||||
- val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
|
||||
- if (!val)
|
||||
- break;
|
||||
-
|
||||
- if (msec == 0) {
|
||||
- dev_err(hdmi->dev, "PHY PLL not locked\n");
|
||||
- return -ETIMEDOUT;
|
||||
- }
|
||||
-
|
||||
- udelay(1000);
|
||||
- msec--;
|
||||
- } while (1);
|
||||
-
|
||||
- return 0;
|
||||
+ return dw_hdmi_phy_power_on(hdmi);
|
||||
}
|
||||
|
||||
static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
From d2922cf55cc2d5a0cd32d4d7055bbb3b1dacd459 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Fri, 31 Mar 2017 15:53:05 +0200
|
||||
Subject: [PATCH 36/79] ARM64: defconfig: enable CONFIG_SND_SOC_SPDIF as module
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/configs/defconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
|
||||
index 6fe57e4..5da1e44 100644
|
||||
--- a/arch/arm64/configs/defconfig
|
||||
+++ b/arch/arm64/configs/defconfig
|
||||
@@ -374,6 +374,7 @@ CONFIG_SND_SOC_RCAR=y
|
||||
CONFIG_SND_SOC_AK4613=y
|
||||
CONFIG_SND_SOC_DIO2125=m
|
||||
CONFIG_SND_SOC_ES7134=m
|
||||
+CONFIG_SND_SOC_SPDIF=m
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_OTG=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
From 815a37cd2514fc9fac5913bdefad6fcbff35d743 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Mon, 6 Mar 2017 01:36:15 +0200
|
||||
Subject: [PATCH 36/93] drm: bridge: dw-hdmi: Create PHY operations
|
||||
|
||||
The HDMI TX controller support different PHYs whose programming
|
||||
interface can vary significantly, especially with vendor PHYs that are
|
||||
not provided by Synopsys. To support them, create a PHY operation
|
||||
structure that can be provided by the platform glue layer. The existing
|
||||
PHY handling code (limited to Synopsys PHY support) is refactored into a
|
||||
set of default PHY operations that are used automatically when the
|
||||
platform glue doesn't provide its own operations.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170305233615.11993-1-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 95 ++++++++++++++++++++++++++++------------
|
||||
include/drm/bridge/dw_hdmi.h | 18 +++++++-
|
||||
2 files changed, 82 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index c25eac8..cb27038 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -141,8 +141,12 @@ struct dw_hdmi {
|
||||
u8 edid[HDMI_EDID_LEN];
|
||||
bool cable_plugin;
|
||||
|
||||
- const struct dw_hdmi_phy_data *phy;
|
||||
- bool phy_enabled;
|
||||
+ struct {
|
||||
+ const struct dw_hdmi_phy_ops *ops;
|
||||
+ const char *name;
|
||||
+ void *data;
|
||||
+ bool enabled;
|
||||
+ } phy;
|
||||
|
||||
struct drm_display_mode previous_mode;
|
||||
|
||||
@@ -831,6 +835,10 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
|
||||
HDMI_VP_CONF);
|
||||
}
|
||||
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * Synopsys PHY Handling
|
||||
+ */
|
||||
+
|
||||
static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
|
||||
unsigned char bit)
|
||||
{
|
||||
@@ -917,7 +925,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
|
||||
|
||||
static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- const struct dw_hdmi_phy_data *phy = hdmi->phy;
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
unsigned int i;
|
||||
u16 val;
|
||||
|
||||
@@ -951,7 +959,7 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
|
||||
|
||||
static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- const struct dw_hdmi_phy_data *phy = hdmi->phy;
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
unsigned int i;
|
||||
u8 val;
|
||||
|
||||
@@ -987,6 +995,7 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
|
||||
|
||||
static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
{
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
@@ -1019,7 +1028,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_phy_power_off(hdmi);
|
||||
|
||||
/* Leave low power consumption mode by asserting SVSRET. */
|
||||
- if (hdmi->phy->has_svsret)
|
||||
+ if (phy->has_svsret)
|
||||
dw_hdmi_phy_enable_svsret(hdmi, 1);
|
||||
|
||||
/* PHY reset. The reset signal is active high on Gen2 PHYs. */
|
||||
@@ -1057,7 +1066,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
return dw_hdmi_phy_power_on(hdmi);
|
||||
}
|
||||
|
||||
-static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
+static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
|
||||
+ struct drm_display_mode *mode)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
@@ -1071,10 +1081,31 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- hdmi->phy_enabled = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
|
||||
+{
|
||||
+ dw_hdmi_phy_power_off(hdmi);
|
||||
+}
|
||||
+
|
||||
+static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
|
||||
+ void *data)
|
||||
+{
|
||||
+ return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
|
||||
+ connector_status_connected : connector_status_disconnected;
|
||||
+}
|
||||
+
|
||||
+static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
|
||||
+ .init = dw_hdmi_phy_init,
|
||||
+ .disable = dw_hdmi_phy_disable,
|
||||
+ .read_hpd = dw_hdmi_phy_read_hpd,
|
||||
+};
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * HDMI TX Setup
|
||||
+ */
|
||||
+
|
||||
static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
|
||||
{
|
||||
u8 de;
|
||||
@@ -1289,16 +1320,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
|
||||
}
|
||||
|
||||
-static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
|
||||
-{
|
||||
- if (!hdmi->phy_enabled)
|
||||
- return;
|
||||
-
|
||||
- dw_hdmi_phy_power_off(hdmi);
|
||||
-
|
||||
- hdmi->phy_enabled = false;
|
||||
-}
|
||||
-
|
||||
/* HDMI Initialization Step B.4 */
|
||||
static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
|
||||
{
|
||||
@@ -1431,9 +1452,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
hdmi_av_composer(hdmi, mode);
|
||||
|
||||
/* HDMI Initializateion Step B.2 */
|
||||
- ret = dw_hdmi_phy_init(hdmi);
|
||||
+ ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
+ hdmi->phy.enabled = true;
|
||||
|
||||
/* HDMI Initialization Step B.3 */
|
||||
dw_hdmi_enable_video_path(hdmi);
|
||||
@@ -1548,7 +1570,11 @@ static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
|
||||
|
||||
static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- dw_hdmi_phy_disable(hdmi);
|
||||
+ if (hdmi->phy.enabled) {
|
||||
+ hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
|
||||
+ hdmi->phy.enabled = false;
|
||||
+ }
|
||||
+
|
||||
hdmi->bridge_is_on = false;
|
||||
}
|
||||
|
||||
@@ -1611,8 +1637,7 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
|
||||
dw_hdmi_update_phy_mask(hdmi);
|
||||
mutex_unlock(&hdmi->mutex);
|
||||
|
||||
- return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
|
||||
- connector_status_connected : connector_status_disconnected;
|
||||
+ return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
|
||||
}
|
||||
|
||||
static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
@@ -1898,19 +1923,31 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
|
||||
phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
|
||||
|
||||
+ if (phy_type == DW_HDMI_PHY_VENDOR_PHY) {
|
||||
+ /* Vendor PHYs require support from the glue layer. */
|
||||
+ if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) {
|
||||
+ dev_err(hdmi->dev,
|
||||
+ "Vendor HDMI PHY not supported by glue layer\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ hdmi->phy.ops = hdmi->plat_data->phy_ops;
|
||||
+ hdmi->phy.data = hdmi->plat_data->phy_data;
|
||||
+ hdmi->phy.name = hdmi->plat_data->phy_name;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Synopsys PHYs are handled internally. */
|
||||
for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
|
||||
if (dw_hdmi_phys[i].type == phy_type) {
|
||||
- hdmi->phy = &dw_hdmi_phys[i];
|
||||
+ hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
|
||||
+ hdmi->phy.name = dw_hdmi_phys[i].name;
|
||||
+ hdmi->phy.data = (void *)&dw_hdmi_phys[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
- if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
|
||||
- dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
|
||||
- else
|
||||
- dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
|
||||
- phy_type);
|
||||
-
|
||||
+ dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -2031,7 +2068,7 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
|
||||
hdmi->version >> 12, hdmi->version & 0xfff,
|
||||
prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
|
||||
- hdmi->phy->name);
|
||||
+ hdmi->phy.name);
|
||||
|
||||
initialize_hdmi_ih_mutes(hdmi);
|
||||
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index b080a17..0f583ca 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -57,13 +57,27 @@ struct dw_hdmi_phy_config {
|
||||
u16 vlev_ctr; /* voltage level control */
|
||||
};
|
||||
|
||||
+struct dw_hdmi_phy_ops {
|
||||
+ int (*init)(struct dw_hdmi *hdmi, void *data,
|
||||
+ struct drm_display_mode *mode);
|
||||
+ void (*disable)(struct dw_hdmi *hdmi, void *data);
|
||||
+ enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data);
|
||||
+};
|
||||
+
|
||||
struct dw_hdmi_plat_data {
|
||||
enum dw_hdmi_devtype dev_type;
|
||||
+ enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
+ struct drm_display_mode *mode);
|
||||
+
|
||||
+ /* Vendor PHY support */
|
||||
+ const struct dw_hdmi_phy_ops *phy_ops;
|
||||
+ const char *phy_name;
|
||||
+ void *phy_data;
|
||||
+
|
||||
+ /* Synopsys PHY support */
|
||||
const struct dw_hdmi_mpll_config *mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config;
|
||||
- enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
- struct drm_display_mode *mode);
|
||||
};
|
||||
|
||||
int dw_hdmi_probe(struct platform_device *pdev,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
From 76c374731322248f9e48241e0debdfed6d794a44 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 15:19:04 +0200
|
||||
Subject: [PATCH 37/79] 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>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 35 ++++++++++++++++++++++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 38 +++++++++++++++++++++++++++++
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 37 ++++++++++++++++++++++++++++
|
||||
3 files changed, 110 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
index 8901eeb..2251881 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
|
||||
@@ -224,6 +224,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-uart";
|
||||
reg = <0x0 0x84c0 0x0 0x14>;
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
index 1d4c861..92d2b91 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
|
||||
@@ -602,6 +602,27 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&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";
|
||||
+
|
||||
+};
|
||||
+
|
||||
&i2c_A {
|
||||
clocks = <&clkc CLKID_I2C>;
|
||||
};
|
||||
@@ -618,6 +639,14 @@
|
||||
clocks = <&clkc CLKID_I2C>;
|
||||
};
|
||||
|
||||
+&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";
|
||||
+};
|
||||
+
|
||||
&saradc {
|
||||
compatible = "amlogic,meson-gxbb-saradc", "amlogic,meson-saradc";
|
||||
clocks = <&xtal>,
|
||||
@@ -649,6 +678,15 @@
|
||||
clock-names = "core", "clkin0", "clkin1";
|
||||
};
|
||||
|
||||
+&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>;
|
||||
};
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
index 6584e46..de0a26b 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
|
||||
@@ -208,6 +208,26 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&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";
|
||||
+};
|
||||
+
|
||||
&periphs {
|
||||
pinctrl_periphs: pinctrl@4b0 {
|
||||
compatible = "amlogic,meson-gxl-periphs-pinctrl";
|
||||
@@ -570,6 +590,14 @@
|
||||
clocks = <&clkc CLKID_I2C>;
|
||||
};
|
||||
|
||||
+&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";
|
||||
+};
|
||||
+
|
||||
&saradc {
|
||||
compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
|
||||
clocks = <&xtal>,
|
||||
@@ -601,6 +629,15 @@
|
||||
clock-names = "core", "clkin0", "clkin1";
|
||||
};
|
||||
|
||||
+&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>;
|
||||
};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
From 3fdd6b3e658373e45ecbe36093403a30bd309df5 Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 19:20:04 +0200
|
||||
Subject: [PATCH 37/93] drm: bridge: dw-hdmi: Add support for custom PHY
|
||||
configuration
|
||||
|
||||
The DWC HDMI TX controller interfaces with a companion PHY. While
|
||||
Synopsys provides multiple standard PHYs, SoC vendors can also integrate
|
||||
a custom PHY.
|
||||
|
||||
Modularize PHY configuration to support vendor PHYs through platform
|
||||
data. The existing PHY configuration code was originally written to
|
||||
support the DWC HDMI 3D TX PHY, and seems to be compatible with the DWC
|
||||
MLP PHY. The HDMI 2.0 PHY will require a separate configuration
|
||||
function.
|
||||
|
||||
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-8-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 109 ++++++++++++++++++++++++++-------------
|
||||
include/drm/bridge/dw_hdmi.h | 7 +++
|
||||
2 files changed, 81 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index cb27038..b835d81 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -118,6 +118,9 @@ struct dw_hdmi_phy_data {
|
||||
const char *name;
|
||||
unsigned int gen;
|
||||
bool has_svsret;
|
||||
+ int (*configure)(struct dw_hdmi *hdmi,
|
||||
+ const struct dw_hdmi_plat_data *pdata,
|
||||
+ unsigned long mpixelclock);
|
||||
};
|
||||
|
||||
struct dw_hdmi {
|
||||
@@ -860,8 +863,8 @@ static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
- unsigned char addr)
|
||||
+void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
+ unsigned char addr)
|
||||
{
|
||||
hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
|
||||
hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
|
||||
@@ -873,6 +876,7 @@ static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
HDMI_PHY_I2CM_OPERATION_ADDR);
|
||||
hdmi_phy_wait_i2c_done(hdmi, 1000);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
|
||||
|
||||
static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
|
||||
{
|
||||
@@ -993,37 +997,67 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
+/*
|
||||
+ * PHY configuration function for the DWC HDMI 3D TX PHY. Based on the available
|
||||
+ * information the DWC MHL PHY has the same register layout and is thus also
|
||||
+ * supported by this function.
|
||||
+ */
|
||||
+static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi,
|
||||
+ const struct dw_hdmi_plat_data *pdata,
|
||||
+ unsigned long mpixelclock)
|
||||
{
|
||||
- const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
- const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
|
||||
|
||||
/* PLL/MPLL Cfg - always match on final entry */
|
||||
for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
|
||||
- if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||
- mpll_config->mpixelclock)
|
||||
+ if (mpixelclock <= mpll_config->mpixelclock)
|
||||
break;
|
||||
|
||||
for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
|
||||
- if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||
- curr_ctrl->mpixelclock)
|
||||
+ if (mpixelclock <= curr_ctrl->mpixelclock)
|
||||
break;
|
||||
|
||||
for (; phy_config->mpixelclock != ~0UL; phy_config++)
|
||||
- if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||
- phy_config->mpixelclock)
|
||||
+ if (mpixelclock <= phy_config->mpixelclock)
|
||||
break;
|
||||
|
||||
if (mpll_config->mpixelclock == ~0UL ||
|
||||
curr_ctrl->mpixelclock == ~0UL ||
|
||||
- phy_config->mpixelclock == ~0UL) {
|
||||
- dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
|
||||
- hdmi->hdmi_data.video_mode.mpixelclock);
|
||||
+ phy_config->mpixelclock == ~0UL)
|
||||
return -EINVAL;
|
||||
- }
|
||||
+
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
|
||||
+ HDMI_3D_TX_PHY_CPCE_CTRL);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
|
||||
+ HDMI_3D_TX_PHY_GMPCTRL);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
|
||||
+ HDMI_3D_TX_PHY_CURRCTRL);
|
||||
+
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
|
||||
+ HDMI_3D_TX_PHY_MSM_CTRL);
|
||||
+
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
|
||||
+ HDMI_3D_TX_PHY_CKSYMTXCTRL);
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
|
||||
+ HDMI_3D_TX_PHY_VLEVCTRL);
|
||||
+
|
||||
+ /* Override and disable clock termination. */
|
||||
+ dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
|
||||
+ HDMI_3D_TX_PHY_CKCALCTRL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
|
||||
+ const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
|
||||
+ unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock;
|
||||
+ int ret;
|
||||
|
||||
dw_hdmi_phy_power_off(hdmi);
|
||||
|
||||
@@ -1042,26 +1076,16 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
|
||||
HDMI_PHY_I2CM_SLAVE_ADDR);
|
||||
hdmi_phy_test_clear(hdmi, 0);
|
||||
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
|
||||
- HDMI_3D_TX_PHY_CPCE_CTRL);
|
||||
- hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
|
||||
- HDMI_3D_TX_PHY_GMPCTRL);
|
||||
- hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
|
||||
- HDMI_3D_TX_PHY_CURRCTRL);
|
||||
-
|
||||
- hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
|
||||
- hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
|
||||
- HDMI_3D_TX_PHY_MSM_CTRL);
|
||||
-
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
|
||||
- HDMI_3D_TX_PHY_CKSYMTXCTRL);
|
||||
- hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
|
||||
- HDMI_3D_TX_PHY_VLEVCTRL);
|
||||
-
|
||||
- /* Override and disable clock termination. */
|
||||
- hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
|
||||
- HDMI_3D_TX_PHY_CKCALCTRL);
|
||||
+ /* Write to the PHY as configured by the platform */
|
||||
+ if (pdata->configure_phy)
|
||||
+ ret = pdata->configure_phy(hdmi, pdata, mpixelclock);
|
||||
+ else
|
||||
+ ret = phy->configure(hdmi, pdata, mpixelclock);
|
||||
+ if (ret) {
|
||||
+ dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n",
|
||||
+ mpixelclock);
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
return dw_hdmi_phy_power_on(hdmi);
|
||||
}
|
||||
@@ -1895,24 +1919,31 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
.name = "DWC MHL PHY + HEAC PHY",
|
||||
.gen = 2,
|
||||
.has_svsret = true,
|
||||
+ .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_MHL_PHY,
|
||||
.name = "DWC MHL PHY",
|
||||
.gen = 2,
|
||||
.has_svsret = true,
|
||||
+ .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
|
||||
.name = "DWC HDMI 3D TX PHY + HEAC PHY",
|
||||
.gen = 2,
|
||||
+ .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
|
||||
.name = "DWC HDMI 3D TX PHY",
|
||||
.gen = 2,
|
||||
+ .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
|
||||
}, {
|
||||
.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
|
||||
.name = "DWC HDMI 2.0 TX PHY",
|
||||
.gen = 2,
|
||||
.has_svsret = true,
|
||||
+ }, {
|
||||
+ .type = DW_HDMI_PHY_VENDOR_PHY,
|
||||
+ .name = "Vendor PHY",
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1943,6 +1974,14 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
|
||||
hdmi->phy.name = dw_hdmi_phys[i].name;
|
||||
hdmi->phy.data = (void *)&dw_hdmi_phys[i];
|
||||
+
|
||||
+ if (!dw_hdmi_phys[i].configure &&
|
||||
+ !hdmi->plat_data->configure_phy) {
|
||||
+ dev_err(hdmi->dev, "%s requires platform support\n",
|
||||
+ hdmi->phy.name);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 0f583ca..dd33025 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -78,6 +78,9 @@ struct dw_hdmi_plat_data {
|
||||
const struct dw_hdmi_mpll_config *mpll_cfg;
|
||||
const struct dw_hdmi_curr_ctrl *cur_ctr;
|
||||
const struct dw_hdmi_phy_config *phy_config;
|
||||
+ int (*configure_phy)(struct dw_hdmi *hdmi,
|
||||
+ const struct dw_hdmi_plat_data *pdata,
|
||||
+ unsigned long mpixelclock);
|
||||
};
|
||||
|
||||
int dw_hdmi_probe(struct platform_device *pdev,
|
||||
@@ -91,4 +94,8 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
|
||||
void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
|
||||
|
||||
+/* PHY configuration */
|
||||
+void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
+ unsigned char addr);
|
||||
+
|
||||
#endif /* __IMX_HDMI_H__ */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
From fb22697ac3dfd363e9d51307d1bb168bd6cf1c41 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 15:28:24 +0200
|
||||
Subject: [PATCH 38/79] ARM64: dts: meson-gxbb-p20x: add i2s codec node
|
||||
|
||||
Add the node for the i2s codec Everest 7134 found on the P20x reference
|
||||
design
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
index 3ed5c99..07b0f21 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
@@ -146,6 +146,12 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
+
|
||||
+ i2s_codec: external-codec {
|
||||
+ #sound-dai-cells = <0>;
|
||||
+ compatible = "everest,es7134";
|
||||
+ status = "okay";
|
||||
+ };
|
||||
};
|
||||
|
||||
/* This UART is brought out to the DB9 connector */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
From c5bdf6120fed0d57d7e602abc01f0cbacf275737 Mon Sep 17 00:00:00 2001
|
||||
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 19:20:05 +0200
|
||||
Subject: [PATCH 38/93] drm: bridge: dw-hdmi: Remove device type from platform
|
||||
data
|
||||
|
||||
The device type isn't used anymore now that workarounds and PHY-specific
|
||||
operations are performed based on version information read at runtime.
|
||||
Remove it.
|
||||
|
||||
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-9-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 2 --
|
||||
drivers/gpu/drm/imx/dw_hdmi-imx.c | 2 --
|
||||
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 -
|
||||
include/drm/bridge/dw_hdmi.h | 7 -------
|
||||
4 files changed, 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index b835d81..132c006 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -127,7 +127,6 @@ struct dw_hdmi {
|
||||
struct drm_connector connector;
|
||||
struct drm_bridge bridge;
|
||||
|
||||
- enum dw_hdmi_devtype dev_type;
|
||||
unsigned int version;
|
||||
|
||||
struct platform_device *audio;
|
||||
@@ -2014,7 +2013,6 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
|
||||
hdmi->plat_data = plat_data;
|
||||
hdmi->dev = dev;
|
||||
- hdmi->dev_type = plat_data->dev_type;
|
||||
hdmi->sample_rate = 48000;
|
||||
hdmi->disabled = true;
|
||||
hdmi->rxsense = true;
|
||||
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
index f645275..f039641 100644
|
||||
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
|
||||
@@ -175,7 +175,6 @@ static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con,
|
||||
.mpll_cfg = imx_mpll_cfg,
|
||||
.cur_ctr = imx_cur_ctr,
|
||||
.phy_config = imx_phy_config,
|
||||
- .dev_type = IMX6Q_HDMI,
|
||||
.mode_valid = imx6q_hdmi_mode_valid,
|
||||
};
|
||||
|
||||
@@ -183,7 +182,6 @@ static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con,
|
||||
.mpll_cfg = imx_mpll_cfg,
|
||||
.cur_ctr = imx_cur_ctr,
|
||||
.phy_config = imx_phy_config,
|
||||
- .dev_type = IMX6DL_HDMI,
|
||||
.mode_valid = imx6dl_hdmi_mode_valid,
|
||||
};
|
||||
|
||||
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
index a6d4a02..d538274 100644
|
||||
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
||||
@@ -237,7 +237,6 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
|
||||
.mpll_cfg = rockchip_mpll_cfg,
|
||||
.cur_ctr = rockchip_cur_ctr,
|
||||
.phy_config = rockchip_phy_config,
|
||||
- .dev_type = RK3288_HDMI,
|
||||
};
|
||||
|
||||
static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index dd33025..545f04fa 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -21,12 +21,6 @@ enum {
|
||||
DW_HDMI_RES_MAX,
|
||||
};
|
||||
|
||||
-enum dw_hdmi_devtype {
|
||||
- IMX6Q_HDMI,
|
||||
- IMX6DL_HDMI,
|
||||
- RK3288_HDMI,
|
||||
-};
|
||||
-
|
||||
enum dw_hdmi_phy_type {
|
||||
DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00,
|
||||
DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2,
|
||||
@@ -65,7 +59,6 @@ struct dw_hdmi_phy_ops {
|
||||
};
|
||||
|
||||
struct dw_hdmi_plat_data {
|
||||
- enum dw_hdmi_devtype dev_type;
|
||||
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
From c834ddb8c5ca2957b7adb99a2a864f1892884e5e Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 15:32:17 +0200
|
||||
Subject: [PATCH 39/79] ARM64: dts: meson-gxbb-p20x: add analog amplifier node
|
||||
|
||||
Add the node for the analog sound amplifier Dioo 2125 found on the p20x
|
||||
reference design
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
index 07b0f21..b9fc07c 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
@@ -152,6 +152,12 @@
|
||||
compatible = "everest,es7134";
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ amp: analog-amplifier {
|
||||
+ compatible = "dioo,dio2125";
|
||||
+ enable-gpios = <&gpio GPIOH_3 0>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
};
|
||||
|
||||
/* This UART is brought out to the DB9 connector */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,227 +0,0 @@
|
|||
From bee2b64f57985618a1b824362c427eb469f41e06 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 3 Mar 2017 19:20:06 +0200
|
||||
Subject: [PATCH 39/93] drm: bridge: dw-hdmi: Switch to regmap for register
|
||||
access
|
||||
|
||||
The Synopsys Designware HDMI TX Controller does not enforce register
|
||||
access on platforms instanciating it. The current driver supports two
|
||||
different types of memory-mapped flat register access, but in order to
|
||||
support the Amlogic Meson SoCs integration, and provide a more generic
|
||||
way to handle all sorts of register mapping, switch the register access
|
||||
to use the regmap infrastructure.
|
||||
|
||||
In the case of registers that are not flat memory-mapped or do not
|
||||
conform to the current driver implementation, a regmap struct can be
|
||||
given in the plat_data and be used at probe or bind.
|
||||
|
||||
Since the AHB audio driver is only available with direct memory access,
|
||||
only allow the I2S audio driver to be registered is directly
|
||||
memory-mapped.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-10-laurent.pinchart+renesas@ideasonboard.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/dw-hdmi.c | 109 +++++++++++++++++++++------------------
|
||||
include/drm/bridge/dw_hdmi.h | 1 +
|
||||
2 files changed, 59 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
index 132c006..026a0dc 100644
|
||||
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <drm/drm_of.h>
|
||||
@@ -171,8 +172,8 @@ struct dw_hdmi {
|
||||
unsigned int audio_n;
|
||||
bool audio_enable;
|
||||
|
||||
- void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
|
||||
- u8 (*read)(struct dw_hdmi *hdmi, int offset);
|
||||
+ unsigned int reg_shift;
|
||||
+ struct regmap *regm;
|
||||
};
|
||||
|
||||
#define HDMI_IH_PHY_STAT0_RX_SENSE \
|
||||
@@ -183,42 +184,23 @@ struct dw_hdmi {
|
||||
(HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \
|
||||
HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
|
||||
|
||||
-static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
|
||||
-{
|
||||
- writel(val, hdmi->regs + (offset << 2));
|
||||
-}
|
||||
-
|
||||
-static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset)
|
||||
-{
|
||||
- return readl(hdmi->regs + (offset << 2));
|
||||
-}
|
||||
-
|
||||
-static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
|
||||
-{
|
||||
- writeb(val, hdmi->regs + offset);
|
||||
-}
|
||||
-
|
||||
-static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset)
|
||||
-{
|
||||
- return readb(hdmi->regs + offset);
|
||||
-}
|
||||
-
|
||||
static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
|
||||
{
|
||||
- hdmi->write(hdmi, val, offset);
|
||||
+ regmap_write(hdmi->regm, offset << hdmi->reg_shift, val);
|
||||
}
|
||||
|
||||
static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
|
||||
{
|
||||
- return hdmi->read(hdmi, offset);
|
||||
+ unsigned int val = 0;
|
||||
+
|
||||
+ regmap_read(hdmi->regm, offset << hdmi->reg_shift, &val);
|
||||
+
|
||||
+ return val;
|
||||
}
|
||||
|
||||
static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
|
||||
{
|
||||
- u8 val = hdmi_readb(hdmi, reg) & ~mask;
|
||||
-
|
||||
- val |= data & mask;
|
||||
- hdmi_writeb(hdmi, val, reg);
|
||||
+ regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
|
||||
}
|
||||
|
||||
static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
|
||||
@@ -1989,6 +1971,20 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
+static const struct regmap_config hdmi_regmap_8bit_config = {
|
||||
+ .reg_bits = 32,
|
||||
+ .val_bits = 8,
|
||||
+ .reg_stride = 1,
|
||||
+ .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR,
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_config hdmi_regmap_32bit_config = {
|
||||
+ .reg_bits = 32,
|
||||
+ .val_bits = 32,
|
||||
+ .reg_stride = 4,
|
||||
+ .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2,
|
||||
+};
|
||||
+
|
||||
static struct dw_hdmi *
|
||||
__dw_hdmi_probe(struct platform_device *pdev,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
@@ -1998,7 +1994,7 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
struct platform_device_info pdevinfo;
|
||||
struct device_node *ddc_node;
|
||||
struct dw_hdmi *hdmi;
|
||||
- struct resource *iores;
|
||||
+ struct resource *iores = NULL;
|
||||
int irq;
|
||||
int ret;
|
||||
u32 val = 1;
|
||||
@@ -2022,22 +2018,6 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
mutex_init(&hdmi->audio_mutex);
|
||||
spin_lock_init(&hdmi->audio_lock);
|
||||
|
||||
- of_property_read_u32(np, "reg-io-width", &val);
|
||||
-
|
||||
- switch (val) {
|
||||
- case 4:
|
||||
- hdmi->write = dw_hdmi_writel;
|
||||
- hdmi->read = dw_hdmi_readl;
|
||||
- break;
|
||||
- case 1:
|
||||
- hdmi->write = dw_hdmi_writeb;
|
||||
- hdmi->read = dw_hdmi_readb;
|
||||
- break;
|
||||
- default:
|
||||
- dev_err(dev, "reg-io-width must be 1 or 4\n");
|
||||
- return ERR_PTR(-EINVAL);
|
||||
- }
|
||||
-
|
||||
ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
|
||||
if (ddc_node) {
|
||||
hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
|
||||
@@ -2051,11 +2031,38 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
dev_dbg(hdmi->dev, "no ddc property found\n");
|
||||
}
|
||||
|
||||
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
- hdmi->regs = devm_ioremap_resource(dev, iores);
|
||||
- if (IS_ERR(hdmi->regs)) {
|
||||
- ret = PTR_ERR(hdmi->regs);
|
||||
- goto err_res;
|
||||
+ if (!plat_data->regm) {
|
||||
+ const struct regmap_config *reg_config;
|
||||
+
|
||||
+ of_property_read_u32(np, "reg-io-width", &val);
|
||||
+ switch (val) {
|
||||
+ case 4:
|
||||
+ reg_config = &hdmi_regmap_32bit_config;
|
||||
+ hdmi->reg_shift = 2;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ reg_config = &hdmi_regmap_8bit_config;
|
||||
+ break;
|
||||
+ default:
|
||||
+ dev_err(dev, "reg-io-width must be 1 or 4\n");
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+ }
|
||||
+
|
||||
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ hdmi->regs = devm_ioremap_resource(dev, iores);
|
||||
+ if (IS_ERR(hdmi->regs)) {
|
||||
+ ret = PTR_ERR(hdmi->regs);
|
||||
+ goto err_res;
|
||||
+ }
|
||||
+
|
||||
+ hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config);
|
||||
+ if (IS_ERR(hdmi->regm)) {
|
||||
+ dev_err(dev, "Failed to configure regmap\n");
|
||||
+ ret = PTR_ERR(hdmi->regm);
|
||||
+ goto err_res;
|
||||
+ }
|
||||
+ } else {
|
||||
+ hdmi->regm = plat_data->regm;
|
||||
}
|
||||
|
||||
hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
|
||||
@@ -2165,7 +2172,7 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
|
||||
config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
|
||||
|
||||
- if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
|
||||
+ if (iores && config3 & HDMI_CONFIG3_AHBAUDDMA) {
|
||||
struct dw_hdmi_audio_data audio;
|
||||
|
||||
audio.phys = iores->start;
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 545f04fa..bcceee8 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -59,6 +59,7 @@ struct dw_hdmi_phy_ops {
|
||||
};
|
||||
|
||||
struct dw_hdmi_plat_data {
|
||||
+ struct regmap *regm;
|
||||
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
From 6f0475d8b6b9792d1aee758a1674aa77a6c4232e Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 17:49:00 +0200
|
||||
Subject: [PATCH 40/79] ARM64: dts: meson-gxbb-p20x: add spdif codec node
|
||||
|
||||
Add spdif-dit node to the meson gxbb reference design
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
index b9fc07c..c8559be 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
@@ -158,6 +158,12 @@
|
||||
enable-gpios = <&gpio GPIOH_3 0>;
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ spdif_out: spdif-out {
|
||||
+ #sound-dai-cells = <0>;
|
||||
+ compatible = "linux,spdif-dit";
|
||||
+ status = "okay";
|
||||
+ };
|
||||
};
|
||||
|
||||
/* This UART is brought out to the DB9 connector */
|
||||
--
|
||||
1.9.1
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,51 @@
|
|||
From 9f335bad0a74dc58e5450260dbfaa59911dfaa31 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 15:40:20 +0200
|
||||
Subject: [PATCH 41/79] ARM64: dts: meson-gxbb-p20x: add i2s and spdif output
|
||||
interfaces
|
||||
|
||||
Add the necessary pins for the i2s and spdif audio interface output and
|
||||
enable these interfaces
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 25 ++++++++++++++++++++++++
|
||||
1 file changed, 25 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
index c8559be..d36f82b0 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
@@ -292,3 +292,28 @@
|
||||
remote-endpoint = <&hdmi_connector_in>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+&audio {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&aiu_i2s_dma {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&aiu_spdif_dma {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&i2s_dai {
|
||||
+ pinctrl-0 = <&i2s_am_clk_pins>, <&i2s_out_ao_clk_pins>,
|
||||
+ <&i2s_out_lr_clk_pins>, <&i2s_out_ch01_ao_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&spdif_dai {
|
||||
+ pinctrl-0 = <&spdif_out_ao_6_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
From 8d012e114e251f5427cb46851ce47e43b745e6c3 Mon Sep 17 00:00:00 2001
|
||||
From: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Date: Mon, 20 Mar 2017 10:57:31 +0800
|
||||
Subject: [PATCH 41/93] drm/bridge: dw_hdmi: support i2c extended read mode
|
||||
|
||||
"I2C Master Interface Extended Read Mode" implements a segment
|
||||
pointer-based read operation using the Special Register configuration.
|
||||
|
||||
This patch fix https://patchwork.kernel.org/patch/7098101/ mentioned
|
||||
"The current implementation does not support "I2C Master Interface
|
||||
Extended Read Mode" to read data addressed by non-zero segment
|
||||
pointer, this means that if EDID has more than 1 extension blocks,
|
||||
EDID reading operation won't succeed"
|
||||
|
||||
With this patch, dw-hdmi can read EDID data with 1/2/4 blocks.
|
||||
|
||||
Signed-off-by: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Reviewed-by: Douglas Anderson <dianders@chromium.org>
|
||||
Acked-by: Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1489978651-16647-1-git-send-email-nickey.yang@rock-chips.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 38 +++++++++++++++++++------------
|
||||
1 file changed, 24 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index 026a0dc..0d112cf 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "dw-hdmi.h"
|
||||
#include "dw-hdmi-audio.h"
|
||||
|
||||
+#define DDC_SEGMENT_ADDR 0x30
|
||||
#define HDMI_EDID_LEN 512
|
||||
|
||||
#define RGB 0
|
||||
@@ -112,6 +113,7 @@ struct dw_hdmi_i2c {
|
||||
|
||||
u8 slave_reg;
|
||||
bool is_regaddr;
|
||||
+ bool is_segment;
|
||||
};
|
||||
|
||||
struct dw_hdmi_phy_data {
|
||||
@@ -247,8 +249,12 @@ static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi,
|
||||
reinit_completion(&i2c->cmp);
|
||||
|
||||
hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
|
||||
- hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ,
|
||||
- HDMI_I2CM_OPERATION);
|
||||
+ if (i2c->is_segment)
|
||||
+ hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ_EXT,
|
||||
+ HDMI_I2CM_OPERATION);
|
||||
+ else
|
||||
+ hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ,
|
||||
+ HDMI_I2CM_OPERATION);
|
||||
|
||||
stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
|
||||
if (!stat)
|
||||
@@ -260,6 +266,7 @@ static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi,
|
||||
|
||||
*buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI);
|
||||
}
|
||||
+ i2c->is_segment = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -309,12 +316,6 @@ static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap,
|
||||
dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
- if (msgs[i].addr != addr) {
|
||||
- dev_warn(hdmi->dev,
|
||||
- "unsupported transfer, changed slave address\n");
|
||||
- return -EOPNOTSUPP;
|
||||
- }
|
||||
-
|
||||
if (msgs[i].len == 0) {
|
||||
dev_dbg(hdmi->dev,
|
||||
"unsupported transfer %d/%d, no data\n",
|
||||
@@ -334,15 +335,24 @@ static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap,
|
||||
/* Set slave device register address on transfer */
|
||||
i2c->is_regaddr = false;
|
||||
|
||||
+ /* Set segment pointer for I2C extended read mode operation */
|
||||
+ i2c->is_segment = false;
|
||||
+
|
||||
for (i = 0; i < num; i++) {
|
||||
dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
|
||||
i + 1, num, msgs[i].len, msgs[i].flags);
|
||||
-
|
||||
- if (msgs[i].flags & I2C_M_RD)
|
||||
- ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len);
|
||||
- else
|
||||
- ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len);
|
||||
-
|
||||
+ if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) {
|
||||
+ i2c->is_segment = true;
|
||||
+ hdmi_writeb(hdmi, DDC_SEGMENT_ADDR, HDMI_I2CM_SEGADDR);
|
||||
+ hdmi_writeb(hdmi, *msgs[i].buf, HDMI_I2CM_SEGPTR);
|
||||
+ } else {
|
||||
+ if (msgs[i].flags & I2C_M_RD)
|
||||
+ ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf,
|
||||
+ msgs[i].len);
|
||||
+ else
|
||||
+ ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf,
|
||||
+ msgs[i].len);
|
||||
+ }
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
From bb66443e46eab9d08082e98b1c53c4ed9699e8b4 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 17:53:57 +0200
|
||||
Subject: [PATCH 42/79] ARM64: dts: meson-gxl-p230: add spdif codec node
|
||||
|
||||
Add spdif-dit node to the meson gxl reference design
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
index 49e19aa..3837560 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
@@ -84,6 +84,12 @@
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
};
|
||||
+
|
||||
+ spdif_out: spdif-out {
|
||||
+ #sound-dai-cells = <0>;
|
||||
+ compatible = "linux,spdif-dit";
|
||||
+ status = "okay";
|
||||
+ };
|
||||
};
|
||||
|
||||
&cec_AO {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
From 7feb88b4b876148c48911d2c9733fcab0e877cd9 Mon Sep 17 00:00:00 2001
|
||||
From: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Date: Tue, 21 Mar 2017 15:36:17 +0800
|
||||
Subject: [PATCH 42/93] drm: bridge: dw-hdmi: add HDMI vendor specific
|
||||
infoframe config
|
||||
|
||||
Vendor specific infoframe is mandatory for 4K2K resolution.
|
||||
Without this, the HDMI protocol compliance fails.
|
||||
|
||||
Signed-off-by: Nickey Yang <nickey.yang@rock-chips.com>
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
Signed-off-by: Archit Taneja <architt@codeaurora.org>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1490081777-2232-1-git-send-email-nickey.yang@rock-chips.com
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 53 +++++++++++++++++++++++++++++++
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 4 +++
|
||||
2 files changed, 57 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index 0d112cf..af93f7a 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -1240,6 +1240,58 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1);
|
||||
}
|
||||
|
||||
+static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi,
|
||||
+ struct drm_display_mode *mode)
|
||||
+{
|
||||
+ struct hdmi_vendor_infoframe frame;
|
||||
+ u8 buffer[10];
|
||||
+ ssize_t err;
|
||||
+
|
||||
+ err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, mode);
|
||||
+ if (err < 0)
|
||||
+ /*
|
||||
+ * Going into that statement does not means vendor infoframe
|
||||
+ * fails. It just informed us that vendor infoframe is not
|
||||
+ * needed for the selected mode. Only 4k or stereoscopic 3D
|
||||
+ * mode requires vendor infoframe. So just simply return.
|
||||
+ */
|
||||
+ return;
|
||||
+
|
||||
+ err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
|
||||
+ if (err < 0) {
|
||||
+ dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n",
|
||||
+ err);
|
||||
+ return;
|
||||
+ }
|
||||
+ hdmi_mask_writeb(hdmi, 0, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET,
|
||||
+ HDMI_FC_DATAUTO0_VSD_MASK);
|
||||
+
|
||||
+ /* Set the length of HDMI vendor specific InfoFrame payload */
|
||||
+ hdmi_writeb(hdmi, buffer[2], HDMI_FC_VSDSIZE);
|
||||
+
|
||||
+ /* Set 24bit IEEE Registration Identifier */
|
||||
+ hdmi_writeb(hdmi, buffer[4], HDMI_FC_VSDIEEEID0);
|
||||
+ hdmi_writeb(hdmi, buffer[5], HDMI_FC_VSDIEEEID1);
|
||||
+ hdmi_writeb(hdmi, buffer[6], HDMI_FC_VSDIEEEID2);
|
||||
+
|
||||
+ /* Set HDMI_Video_Format and HDMI_VIC/3D_Structure */
|
||||
+ hdmi_writeb(hdmi, buffer[7], HDMI_FC_VSDPAYLOAD0);
|
||||
+ hdmi_writeb(hdmi, buffer[8], HDMI_FC_VSDPAYLOAD1);
|
||||
+
|
||||
+ if (frame.s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
|
||||
+ hdmi_writeb(hdmi, buffer[9], HDMI_FC_VSDPAYLOAD2);
|
||||
+
|
||||
+ /* Packet frame interpolation */
|
||||
+ hdmi_writeb(hdmi, 1, HDMI_FC_DATAUTO1);
|
||||
+
|
||||
+ /* Auto packets per frame and line spacing */
|
||||
+ hdmi_writeb(hdmi, 0x11, HDMI_FC_DATAUTO2);
|
||||
+
|
||||
+ /* Configures the Frame Composer On RDRB mode */
|
||||
+ hdmi_mask_writeb(hdmi, 1, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET,
|
||||
+ HDMI_FC_DATAUTO0_VSD_MASK);
|
||||
+}
|
||||
+
|
||||
static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
@@ -1489,6 +1541,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
|
||||
/* HDMI Initialization Step F - Configure AVI InfoFrame */
|
||||
hdmi_config_AVI(hdmi, mode);
|
||||
+ hdmi_config_vendor_specific_infoframe(hdmi, mode);
|
||||
} else {
|
||||
dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
|
||||
index 325b0b8..c59f87e 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
|
||||
@@ -854,6 +854,10 @@ enum {
|
||||
HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
|
||||
HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,
|
||||
|
||||
+/* FC_DATAUTO0 field values */
|
||||
+ HDMI_FC_DATAUTO0_VSD_MASK = 0x08,
|
||||
+ HDMI_FC_DATAUTO0_VSD_OFFSET = 3,
|
||||
+
|
||||
/* PHY_CONF0 field values */
|
||||
HDMI_PHY_CONF0_PDZ_MASK = 0x80,
|
||||
HDMI_PHY_CONF0_PDZ_OFFSET = 7,
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
From 01ff36940e53cd410abec88ec2eb282c397a3a77 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 16:04:39 +0200
|
||||
Subject: [PATCH 43/79] ARM64: dts: meson-gxl-p230: add spdif output interface
|
||||
|
||||
Add the necessary pin for the spdif audio interface output and enable it
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
index 3837560..770a332 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
@@ -130,3 +130,17 @@
|
||||
status = "okay";
|
||||
vref-supply = <&vddio_ao18>;
|
||||
};
|
||||
+
|
||||
+&audio {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&aiu_spdif_dma {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&spdif_dai {
|
||||
+ pinctrl-0 = <&spdif_out_h_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
From b880ce74954cefe49cfc101c684c4ce0b0063945 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
Date: Fri, 3 Mar 2017 14:14:56 +0200
|
||||
Subject: [PATCH 43/93] drm: bridge: dw-hdmi: Extract PHY interrupt setup to a
|
||||
function
|
||||
|
||||
In preparation for adding PHY operations to handle RX SENSE and HPD,
|
||||
group all the PHY interrupt setup code in a single location and extract
|
||||
it to a separate function.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 50 ++++++++++++++-----------------
|
||||
1 file changed, 23 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index af93f7a..f82750a 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -1559,7 +1559,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
}
|
||||
|
||||
/* Wait until we are registered to enable interrupts */
|
||||
-static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
|
||||
+static void dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
|
||||
{
|
||||
hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
|
||||
HDMI_PHY_I2CM_INT_ADDR);
|
||||
@@ -1567,15 +1567,6 @@ static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
|
||||
hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
|
||||
HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
|
||||
HDMI_PHY_I2CM_CTLINT_ADDR);
|
||||
-
|
||||
- /* enable cable hot plug irq */
|
||||
- hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
-
|
||||
- /* Clear Hotplug interrupts */
|
||||
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
- HDMI_IH_PHY_STAT0);
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
|
||||
static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
|
||||
@@ -1693,6 +1684,26 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
|
||||
hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
}
|
||||
|
||||
+static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi)
|
||||
+{
|
||||
+ /*
|
||||
+ * Configure the PHY RX SENSE and HPD interrupts polarities and clear
|
||||
+ * any pending interrupt.
|
||||
+ */
|
||||
+ hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
|
||||
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
+ HDMI_IH_PHY_STAT0);
|
||||
+
|
||||
+ /* Enable cable hot plug irq. */
|
||||
+ hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
+
|
||||
+ /* Clear and unmute interrupts. */
|
||||
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
+ HDMI_IH_PHY_STAT0);
|
||||
+ hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
|
||||
+ HDMI_IH_MUTE_PHY_STAT0);
|
||||
+}
|
||||
+
|
||||
static enum drm_connector_status
|
||||
dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
@@ -2204,29 +2215,14 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
hdmi->ddc = NULL;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Configure registers related to HDMI interrupt
|
||||
- * generation before registering IRQ.
|
||||
- */
|
||||
- hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
|
||||
-
|
||||
- /* Clear Hotplug interrupts */
|
||||
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
- HDMI_IH_PHY_STAT0);
|
||||
-
|
||||
hdmi->bridge.driver_private = hdmi;
|
||||
hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
|
||||
#ifdef CONFIG_OF
|
||||
hdmi->bridge.of_node = pdev->dev.of_node;
|
||||
#endif
|
||||
|
||||
- ret = dw_hdmi_fb_registered(hdmi);
|
||||
- if (ret)
|
||||
- goto err_iahb;
|
||||
-
|
||||
- /* Unmute interrupts */
|
||||
- hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
|
||||
- HDMI_IH_MUTE_PHY_STAT0);
|
||||
+ dw_hdmi_fb_registered(hdmi);
|
||||
+ dw_hdmi_phy_setup_hpd(hdmi);
|
||||
|
||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||
pdevinfo.parent = dev;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
From bb5cf409583f04045ea97c7a039cb0935bbd6bfc Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 15:53:47 +0200
|
||||
Subject: [PATCH 44/79] WIP: ARM64: dts: meson-gxbb-p20x: add sound card
|
||||
support
|
||||
|
||||
This commit add sound card support to the meson-gxbb-p20x
|
||||
This patch is not intended to be merged upstream the architecture of
|
||||
the sound card has not been determined yet. To handle the routing caps
|
||||
of meson SoCs, we will probably have to make our own card.
|
||||
|
||||
This implementation using simple-card is provided for testing purpose only
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 51 ++++++++++++++++++++++++
|
||||
1 file changed, 51 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
index d36f82b0..88e3713 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
|
||||
@@ -164,6 +164,57 @@
|
||||
compatible = "linux,spdif-dit";
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ soc {
|
||||
+ sound {
|
||||
+ compatible = "simple-audio-card";
|
||||
+ simple-audio-card,name = "meson-gxbb-p20x";
|
||||
+ simple-audio-card,aux-devs = <&>;
|
||||
+ simple-audio-card,widgets =
|
||||
+ "Line", "Analog Left Output",
|
||||
+ "Line", "Analog Right Output";
|
||||
+ simple-audio-card,routing =
|
||||
+ "Analog Left Output", "OUTL",
|
||||
+ "Analog Right Output", "OUTR",
|
||||
+ "INL", "AOUTL",
|
||||
+ "INR", "AOUTR";
|
||||
+ status = "okay";
|
||||
+
|
||||
+ simple-audio-card,dai-link@0 {
|
||||
+ /* RCA 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 = <&i2s_codec>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ simple-audio-card,dai-link@1 {
|
||||
+ plat {
|
||||
+ sound-dai = <&aiu_spdif_dma>;
|
||||
+ };
|
||||
+
|
||||
+ cpu {
|
||||
+ sound-dai = <&spdif_dai>;
|
||||
+ };
|
||||
+
|
||||
+ codec {
|
||||
+ sound-dai = <&spdif_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
/* This UART is brought out to the DB9 connector */
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,551 +0,0 @@
|
|||
From 61801956e33a13e4682a8b52978d8f3c5d7f99e3 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 13 Jan 2017 16:07:42 +0100
|
||||
Subject: [PATCH 44/93] drm: bridge: dw-hdmi: Switch to V4L bus format and
|
||||
encodings
|
||||
|
||||
Some display pipelines can only provide non-RBG input pixels to the HDMI TX
|
||||
Controller, this patch takes the pixel format from the plat_data if provided.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 326 +++++++++++++++++++++---------
|
||||
include/drm/bridge/dw_hdmi.h | 63 ++++++
|
||||
2 files changed, 294 insertions(+), 95 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index f82750a..fcb0a27 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -30,18 +30,15 @@
|
||||
#include <drm/drm_encoder_slave.h>
|
||||
#include <drm/bridge/dw_hdmi.h>
|
||||
|
||||
+#include <uapi/linux/media-bus-format.h>
|
||||
+#include <uapi/linux/videodev2.h>
|
||||
+
|
||||
#include "dw-hdmi.h"
|
||||
#include "dw-hdmi-audio.h"
|
||||
|
||||
#define DDC_SEGMENT_ADDR 0x30
|
||||
#define HDMI_EDID_LEN 512
|
||||
|
||||
-#define RGB 0
|
||||
-#define YCBCR444 1
|
||||
-#define YCBCR422_16BITS 2
|
||||
-#define YCBCR422_8BITS 3
|
||||
-#define XVYCC444 4
|
||||
-
|
||||
enum hdmi_datamap {
|
||||
RGB444_8B = 0x01,
|
||||
RGB444_10B = 0x03,
|
||||
@@ -95,10 +92,10 @@ struct hdmi_vmode {
|
||||
};
|
||||
|
||||
struct hdmi_data_info {
|
||||
- unsigned int enc_in_format;
|
||||
- unsigned int enc_out_format;
|
||||
- unsigned int enc_color_depth;
|
||||
- unsigned int colorimetry;
|
||||
+ unsigned int enc_in_bus_format;
|
||||
+ unsigned int enc_out_bus_format;
|
||||
+ unsigned int enc_in_encoding;
|
||||
+ unsigned int enc_out_encoding;
|
||||
unsigned int pix_repet_factor;
|
||||
unsigned int hdcp_enable;
|
||||
struct hdmi_vmode video_mode;
|
||||
@@ -567,6 +564,92 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
|
||||
|
||||
+static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_RGB888_1X24:
|
||||
+ case MEDIA_BUS_FMT_RGB101010_1X30:
|
||||
+ case MEDIA_BUS_FMT_RGB121212_1X36:
|
||||
+ case MEDIA_BUS_FMT_RGB161616_1X48:
|
||||
+ return true;
|
||||
+
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_YUV8_1X24:
|
||||
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
||||
+ case MEDIA_BUS_FMT_YUV12_1X36:
|
||||
+ case MEDIA_BUS_FMT_YUV16_1X48:
|
||||
+ return true;
|
||||
+
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
+ case MEDIA_BUS_FMT_UYVY10_1X20:
|
||||
+ case MEDIA_BUS_FMT_UYVY12_1X24:
|
||||
+ return true;
|
||||
+
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_UYYVYY8_1X24:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY10_1X30:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY12_1X36:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY16_1X48:
|
||||
+ return true;
|
||||
+
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
|
||||
+{
|
||||
+ switch (bus_format) {
|
||||
+ case MEDIA_BUS_FMT_RGB888_1X24:
|
||||
+ case MEDIA_BUS_FMT_YUV8_1X24:
|
||||
+ case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY8_1X24:
|
||||
+ return 8;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_RGB101010_1X30:
|
||||
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
||||
+ case MEDIA_BUS_FMT_UYVY10_1X20:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY10_1X30:
|
||||
+ return 10;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_RGB121212_1X36:
|
||||
+ case MEDIA_BUS_FMT_YUV12_1X36:
|
||||
+ case MEDIA_BUS_FMT_UYVY12_1X24:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY12_1X36:
|
||||
+ return 12;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_RGB161616_1X48:
|
||||
+ case MEDIA_BUS_FMT_YUV16_1X48:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY16_1X48:
|
||||
+ return 16;
|
||||
+
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* this submodule is responsible for the video data synchronization.
|
||||
* for example, for RGB 4:4:4 input, the data map is defined as
|
||||
@@ -579,37 +662,49 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
|
||||
int color_format = 0;
|
||||
u8 val;
|
||||
|
||||
- if (hdmi->hdmi_data.enc_in_format == RGB) {
|
||||
- if (hdmi->hdmi_data.enc_color_depth == 8)
|
||||
- color_format = 0x01;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 10)
|
||||
- color_format = 0x03;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 12)
|
||||
- color_format = 0x05;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 16)
|
||||
- color_format = 0x07;
|
||||
- else
|
||||
- return;
|
||||
- } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
|
||||
- if (hdmi->hdmi_data.enc_color_depth == 8)
|
||||
- color_format = 0x09;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 10)
|
||||
- color_format = 0x0B;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 12)
|
||||
- color_format = 0x0D;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 16)
|
||||
- color_format = 0x0F;
|
||||
- else
|
||||
- return;
|
||||
- } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
|
||||
- if (hdmi->hdmi_data.enc_color_depth == 8)
|
||||
- color_format = 0x16;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 10)
|
||||
- color_format = 0x14;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 12)
|
||||
- color_format = 0x12;
|
||||
- else
|
||||
- return;
|
||||
+ switch (hdmi->hdmi_data.enc_in_bus_format) {
|
||||
+ case MEDIA_BUS_FMT_RGB888_1X24:
|
||||
+ color_format = 0x01;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_RGB101010_1X30:
|
||||
+ color_format = 0x03;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_RGB121212_1X36:
|
||||
+ color_format = 0x05;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_RGB161616_1X48:
|
||||
+ color_format = 0x07;
|
||||
+ break;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_YUV8_1X24:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY8_1X24:
|
||||
+ color_format = 0x09;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY10_1X30:
|
||||
+ color_format = 0x0B;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_YUV12_1X36:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY12_1X36:
|
||||
+ color_format = 0x0D;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_YUV16_1X48:
|
||||
+ case MEDIA_BUS_FMT_UYYVYY16_1X48:
|
||||
+ color_format = 0x0F;
|
||||
+ break;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
+ color_format = 0x16;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_UYVY10_1X20:
|
||||
+ color_format = 0x14;
|
||||
+ break;
|
||||
+ case MEDIA_BUS_FMT_UYVY12_1X24:
|
||||
+ color_format = 0x12;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ return;
|
||||
}
|
||||
|
||||
val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
|
||||
@@ -632,26 +727,30 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
|
||||
|
||||
static int is_color_space_conversion(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
|
||||
+ return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format;
|
||||
}
|
||||
|
||||
static int is_color_space_decimation(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
|
||||
+ if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
|
||||
return 0;
|
||||
- if (hdmi->hdmi_data.enc_in_format == RGB ||
|
||||
- hdmi->hdmi_data.enc_in_format == YCBCR444)
|
||||
+
|
||||
+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
|
||||
+ hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
|
||||
return 1;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_color_space_interpolation(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
|
||||
+ if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
|
||||
return 0;
|
||||
- if (hdmi->hdmi_data.enc_out_format == RGB ||
|
||||
- hdmi->hdmi_data.enc_out_format == YCBCR444)
|
||||
+
|
||||
+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
|
||||
+ hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
|
||||
return 1;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -662,15 +761,16 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
|
||||
u32 csc_scale = 1;
|
||||
|
||||
if (is_color_space_conversion(hdmi)) {
|
||||
- if (hdmi->hdmi_data.enc_out_format == RGB) {
|
||||
- if (hdmi->hdmi_data.colorimetry ==
|
||||
- HDMI_COLORIMETRY_ITU_601)
|
||||
+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ if (hdmi->hdmi_data.enc_out_encoding ==
|
||||
+ V4L2_YCBCR_ENC_601)
|
||||
csc_coeff = &csc_coeff_rgb_out_eitu601;
|
||||
else
|
||||
csc_coeff = &csc_coeff_rgb_out_eitu709;
|
||||
- } else if (hdmi->hdmi_data.enc_in_format == RGB) {
|
||||
- if (hdmi->hdmi_data.colorimetry ==
|
||||
- HDMI_COLORIMETRY_ITU_601)
|
||||
+ } else if (hdmi_bus_fmt_is_rgb(
|
||||
+ hdmi->hdmi_data.enc_in_bus_format)) {
|
||||
+ if (hdmi->hdmi_data.enc_out_encoding ==
|
||||
+ V4L2_YCBCR_ENC_601)
|
||||
csc_coeff = &csc_coeff_rgb_in_eitu601;
|
||||
else
|
||||
csc_coeff = &csc_coeff_rgb_in_eitu709;
|
||||
@@ -708,16 +808,23 @@ static void hdmi_video_csc(struct dw_hdmi *hdmi)
|
||||
else if (is_color_space_decimation(hdmi))
|
||||
decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
|
||||
|
||||
- if (hdmi->hdmi_data.enc_color_depth == 8)
|
||||
+ switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ case 8:
|
||||
color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 10)
|
||||
+ break;
|
||||
+ case 10:
|
||||
color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 12)
|
||||
+ break;
|
||||
+ case 12:
|
||||
color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
|
||||
- else if (hdmi->hdmi_data.enc_color_depth == 16)
|
||||
+ break;
|
||||
+ case 16:
|
||||
color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
|
||||
- else
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
return;
|
||||
+ }
|
||||
|
||||
/* Configure the CSC registers */
|
||||
hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
|
||||
@@ -740,32 +847,43 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
|
||||
struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
|
||||
u8 val, vp_conf;
|
||||
|
||||
- if (hdmi_data->enc_out_format == RGB ||
|
||||
- hdmi_data->enc_out_format == YCBCR444) {
|
||||
- if (!hdmi_data->enc_color_depth) {
|
||||
- output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
|
||||
- } else if (hdmi_data->enc_color_depth == 8) {
|
||||
+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
|
||||
+ hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ switch (hdmi_bus_fmt_color_depth(
|
||||
+ hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ case 8:
|
||||
color_depth = 4;
|
||||
output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
|
||||
- } else if (hdmi_data->enc_color_depth == 10) {
|
||||
+ break;
|
||||
+ case 10:
|
||||
color_depth = 5;
|
||||
- } else if (hdmi_data->enc_color_depth == 12) {
|
||||
+ break;
|
||||
+ case 12:
|
||||
color_depth = 6;
|
||||
- } else if (hdmi_data->enc_color_depth == 16) {
|
||||
+ break;
|
||||
+ case 16:
|
||||
color_depth = 7;
|
||||
- } else {
|
||||
- return;
|
||||
+ break;
|
||||
+ default:
|
||||
+ output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
|
||||
}
|
||||
- } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
|
||||
- if (!hdmi_data->enc_color_depth ||
|
||||
- hdmi_data->enc_color_depth == 8)
|
||||
+ } else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ switch (hdmi_bus_fmt_color_depth(
|
||||
+ hdmi->hdmi_data.enc_out_bus_format)) {
|
||||
+ case 0:
|
||||
+ case 8:
|
||||
remap_size = HDMI_VP_REMAP_YCC422_16bit;
|
||||
- else if (hdmi_data->enc_color_depth == 10)
|
||||
+ break;
|
||||
+ case 10:
|
||||
remap_size = HDMI_VP_REMAP_YCC422_20bit;
|
||||
- else if (hdmi_data->enc_color_depth == 12)
|
||||
+ break;
|
||||
+ case 12:
|
||||
remap_size = HDMI_VP_REMAP_YCC422_24bit;
|
||||
- else
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
return;
|
||||
+ }
|
||||
output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
|
||||
} else {
|
||||
return;
|
||||
@@ -1148,28 +1266,35 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
/* Initialise info frame from DRM mode */
|
||||
drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
|
||||
- if (hdmi->hdmi_data.enc_out_format == YCBCR444)
|
||||
+ if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
|
||||
frame.colorspace = HDMI_COLORSPACE_YUV444;
|
||||
- else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
|
||||
+ else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
|
||||
frame.colorspace = HDMI_COLORSPACE_YUV422;
|
||||
else
|
||||
frame.colorspace = HDMI_COLORSPACE_RGB;
|
||||
|
||||
/* Set up colorimetry */
|
||||
- if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
|
||||
- frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
|
||||
- if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
|
||||
- frame.extended_colorimetry =
|
||||
+ switch (hdmi->hdmi_data.enc_out_encoding) {
|
||||
+ case V4L2_YCBCR_ENC_601:
|
||||
+ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
|
||||
+ else
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
|
||||
+ frame.extended_colorimetry =
|
||||
HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
|
||||
- else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
|
||||
- frame.extended_colorimetry =
|
||||
+ case V4L2_YCBCR_ENC_709:
|
||||
+ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
|
||||
+ else
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
|
||||
+ frame.extended_colorimetry =
|
||||
HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
|
||||
- } else if (hdmi->hdmi_data.enc_out_format != RGB) {
|
||||
- frame.colorimetry = hdmi->hdmi_data.colorimetry;
|
||||
- frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
|
||||
- } else { /* Carries no data */
|
||||
- frame.colorimetry = HDMI_COLORIMETRY_NONE;
|
||||
- frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
|
||||
+ break;
|
||||
+ default: /* Carries no data */
|
||||
+ frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
|
||||
+ frame.extended_colorimetry =
|
||||
+ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
|
||||
+ break;
|
||||
}
|
||||
|
||||
frame.scan_mode = HDMI_SCAN_MODE_NONE;
|
||||
@@ -1498,19 +1623,30 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
(hdmi->vic == 21) || (hdmi->vic == 22) ||
|
||||
(hdmi->vic == 2) || (hdmi->vic == 3) ||
|
||||
(hdmi->vic == 17) || (hdmi->vic == 18))
|
||||
- hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
|
||||
+ hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601;
|
||||
else
|
||||
- hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
|
||||
+ hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709;
|
||||
|
||||
hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
|
||||
hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
|
||||
|
||||
- /* TODO: Get input format from IPU (via FB driver interface) */
|
||||
- hdmi->hdmi_data.enc_in_format = RGB;
|
||||
+ /* TOFIX: Get input format from plat data or fallback to RGB888 */
|
||||
+ if (hdmi->plat_data->input_bus_format >= 0)
|
||||
+ hdmi->hdmi_data.enc_in_bus_format =
|
||||
+ hdmi->plat_data->input_bus_format;
|
||||
+ else
|
||||
+ hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
+
|
||||
+ /* TOFIX: Get input encoding from plat data or fallback to none */
|
||||
+ if (hdmi->plat_data->input_bus_encoding >= 0)
|
||||
+ hdmi->hdmi_data.enc_in_encoding =
|
||||
+ hdmi->plat_data->input_bus_encoding;
|
||||
+ else
|
||||
+ hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
|
||||
|
||||
- hdmi->hdmi_data.enc_out_format = RGB;
|
||||
+ /* TOFIX: Default to RGB888 output format */
|
||||
+ hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
|
||||
- hdmi->hdmi_data.enc_color_depth = 8;
|
||||
hdmi->hdmi_data.pix_repet_factor = 0;
|
||||
hdmi->hdmi_data.hdcp_enable = 0;
|
||||
hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index bcceee8..0da74fb 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -14,6 +14,67 @@
|
||||
|
||||
struct dw_hdmi;
|
||||
|
||||
+/**
|
||||
+ * DOC: Supported input formats and encodings
|
||||
+ *
|
||||
+ * Depending on the Hardware configuration of the Controller IP, it supports
|
||||
+ * a subset of the following input formats and encodings on it's internal
|
||||
+ * 48bit bus.
|
||||
+ *
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + Format Name + Format Code + Encodings +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + RGB 4:4:4 8bit + ``MEDIA_BUS_FMT_RGB888_1X24`` + ``V4L2_YCBCR_ENC_DEFAULT`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + RGB 4:4:4 10bits + ``MEDIA_BUS_FMT_RGB101010_1X30``+ ``V4L2_YCBCR_ENC_DEFAULT`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + RGB 4:4:4 12bits + ``MEDIA_BUS_FMT_RGB121212_1X36``+ ``V4L2_YCBCR_ENC_DEFAULT`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + RGB 4:4:4 16bits + ``MEDIA_BUS_FMT_RGB161616_1X48``+ ``V4L2_YCBCR_ENC_DEFAULT`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:4:4 8bit + ``MEDIA_BUS_FMT_YUV8_1X24`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:4:4 10bits + ``MEDIA_BUS_FMT_YUV10_1X30`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:4:4 12bits + ``MEDIA_BUS_FMT_YUV12_1X36`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:4:4 16bits + ``MEDIA_BUS_FMT_YUV16_1X48`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_XV709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:2 8bit + ``MEDIA_BUS_FMT_UYVY8_1X16`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:2 10bits + ``MEDIA_BUS_FMT_UYVY10_1X20`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:2 12bits + ``MEDIA_BUS_FMT_UYVY12_1X24`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:0 8bit + ``MEDIA_BUS_FMT_UYYVYY8_1X24`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:0 10bits + ``MEDIA_BUS_FMT_UYYVYY10_1X30`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:0 12bits + ``MEDIA_BUS_FMT_UYYVYY12_1X36`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ * + YCbCr 4:2:0 16bits + ``MEDIA_BUS_FMT_UYYVYY16_1X48`` + ``V4L2_YCBCR_ENC_601`` +
|
||||
+ * + + + or ``V4L2_YCBCR_ENC_709`` +
|
||||
+ * +----------------------+---------------------------------+------------------------------+
|
||||
+ */
|
||||
+
|
||||
enum {
|
||||
DW_HDMI_RES_8,
|
||||
DW_HDMI_RES_10,
|
||||
@@ -62,6 +123,8 @@ struct dw_hdmi_plat_data {
|
||||
struct regmap *regm;
|
||||
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
+ unsigned long input_bus_format;
|
||||
+ unsigned long input_bus_encoding;
|
||||
|
||||
/* Vendor PHY support */
|
||||
const struct dw_hdmi_phy_ops *phy_ops;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
From 24739afc3e8549f7361dd2ac7f8f5368f8fe0f79 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Thu, 30 Mar 2017 16:06:10 +0200
|
||||
Subject: [PATCH 45/79] WIP: ARM64: dts: meson-gxl-p230: add sound card support
|
||||
|
||||
This commit add sound card support to the meson-gxbb-p230
|
||||
his patch is not intended to be merged upstream. The architecture of
|
||||
the sound card has not been determined yet. To handle the routing caps
|
||||
of meson SoCs, we will probably have to make our own card.
|
||||
|
||||
This implementation using simple-card is provided for testing purpose only
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
.../arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts | 21 +++++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
index 770a332..5da5206 100644
|
||||
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
|
||||
@@ -90,6 +90,27 @@
|
||||
compatible = "linux,spdif-dit";
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ soc {
|
||||
+ sound {
|
||||
+ compatible = "simple-audio-card";
|
||||
+ simple-audio-card,name = "meson-gxl-p230";
|
||||
+
|
||||
+ simple-audio-card,dai-link@0 {
|
||||
+ plat {
|
||||
+ sound-dai = <&aiu_spdif_dma>;
|
||||
+ };
|
||||
+
|
||||
+ cpu {
|
||||
+ sound-dai = <&spdif_dai>;
|
||||
+ };
|
||||
+
|
||||
+ codec {
|
||||
+ sound-dai = <&spdif_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
&cec_AO {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
From 5c5f665a2f6a9a8248bf38356f0958772d6d4ef6 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Wed, 8 Feb 2017 12:29:19 +0100
|
||||
Subject: [PATCH 45/93] drm: bridge: dw-hdmi: Move HPD handling to PHY
|
||||
operations
|
||||
|
||||
The HDMI TX controller support HPD and RXSENSE signaling from the PHY
|
||||
via it's STAT0 PHY interface, but some vendor PHYs can manage these
|
||||
signals independently from the controller, thus these STAT0 handling
|
||||
should be moved to PHY specific operations and become optional.
|
||||
|
||||
The existing STAT0 HPD and RXSENSE handling code is refactored into
|
||||
a supplementaty set of default PHY operations that are used automatically
|
||||
when the platform glue doesn't provide its own operations.
|
||||
|
||||
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 135 ++++++++++++++++++------------
|
||||
include/drm/bridge/dw_hdmi.h | 5 ++
|
||||
2 files changed, 86 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index fcb0a27..910d579 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -1229,10 +1229,46 @@ static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
|
||||
connector_status_connected : connector_status_disconnected;
|
||||
}
|
||||
|
||||
+static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data,
|
||||
+ bool force, bool disabled, bool rxsense)
|
||||
+{
|
||||
+ u8 old_mask = hdmi->phy_mask;
|
||||
+
|
||||
+ if (force || disabled || !rxsense)
|
||||
+ hdmi->phy_mask |= HDMI_PHY_RX_SENSE;
|
||||
+ else
|
||||
+ hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE;
|
||||
+
|
||||
+ if (old_mask != hdmi->phy_mask)
|
||||
+ hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
+}
|
||||
+
|
||||
+static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data)
|
||||
+{
|
||||
+ /*
|
||||
+ * Configure the PHY RX SENSE and HPD interrupts polarities and clear
|
||||
+ * any pending interrupt.
|
||||
+ */
|
||||
+ hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
|
||||
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
+ HDMI_IH_PHY_STAT0);
|
||||
+
|
||||
+ /* Enable cable hot plug irq. */
|
||||
+ hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
+
|
||||
+ /* Clear and unmute interrupts. */
|
||||
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
+ HDMI_IH_PHY_STAT0);
|
||||
+ hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
|
||||
+ HDMI_IH_MUTE_PHY_STAT0);
|
||||
+}
|
||||
+
|
||||
static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
|
||||
.init = dw_hdmi_phy_init,
|
||||
.disable = dw_hdmi_phy_disable,
|
||||
.read_hpd = dw_hdmi_phy_read_hpd,
|
||||
+ .update_hpd = dw_hdmi_phy_update_hpd,
|
||||
+ .setup_hpd = dw_hdmi_phy_setup_hpd,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@@ -1809,35 +1845,10 @@ static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
|
||||
*/
|
||||
static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
|
||||
{
|
||||
- u8 old_mask = hdmi->phy_mask;
|
||||
-
|
||||
- if (hdmi->force || hdmi->disabled || !hdmi->rxsense)
|
||||
- hdmi->phy_mask |= HDMI_PHY_RX_SENSE;
|
||||
- else
|
||||
- hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE;
|
||||
-
|
||||
- if (old_mask != hdmi->phy_mask)
|
||||
- hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
-}
|
||||
-
|
||||
-static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi)
|
||||
-{
|
||||
- /*
|
||||
- * Configure the PHY RX SENSE and HPD interrupts polarities and clear
|
||||
- * any pending interrupt.
|
||||
- */
|
||||
- hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
|
||||
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
- HDMI_IH_PHY_STAT0);
|
||||
-
|
||||
- /* Enable cable hot plug irq. */
|
||||
- hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
|
||||
-
|
||||
- /* Clear and unmute interrupts. */
|
||||
- hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
|
||||
- HDMI_IH_PHY_STAT0);
|
||||
- hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
|
||||
- HDMI_IH_MUTE_PHY_STAT0);
|
||||
+ if (hdmi->phy.ops->update_hpd)
|
||||
+ hdmi->phy.ops->update_hpd(hdmi, hdmi->phy.data,
|
||||
+ hdmi->force, hdmi->disabled,
|
||||
+ hdmi->rxsense);
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
@@ -2029,6 +2040,41 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
|
||||
+{
|
||||
+ mutex_lock(&hdmi->mutex);
|
||||
+
|
||||
+ if (!hdmi->disabled && !hdmi->force) {
|
||||
+ /*
|
||||
+ * If the RX sense status indicates we're disconnected,
|
||||
+ * clear the software rxsense status.
|
||||
+ */
|
||||
+ if (!rx_sense)
|
||||
+ hdmi->rxsense = false;
|
||||
+
|
||||
+ /*
|
||||
+ * Only set the software rxsense status when both
|
||||
+ * rxsense and hpd indicates we're connected.
|
||||
+ * This avoids what seems to be bad behaviour in
|
||||
+ * at least iMX6S versions of the phy.
|
||||
+ */
|
||||
+ if (hpd)
|
||||
+ hdmi->rxsense = true;
|
||||
+
|
||||
+ dw_hdmi_update_power(hdmi);
|
||||
+ dw_hdmi_update_phy_mask(hdmi);
|
||||
+ }
|
||||
+ mutex_unlock(&hdmi->mutex);
|
||||
+}
|
||||
+
|
||||
+void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
+
|
||||
+ __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense);
|
||||
+
|
||||
static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct dw_hdmi *hdmi = dev_id;
|
||||
@@ -2061,30 +2107,10 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
* ask the source to re-read the EDID.
|
||||
*/
|
||||
if (intr_stat &
|
||||
- (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
|
||||
- mutex_lock(&hdmi->mutex);
|
||||
- if (!hdmi->disabled && !hdmi->force) {
|
||||
- /*
|
||||
- * If the RX sense status indicates we're disconnected,
|
||||
- * clear the software rxsense status.
|
||||
- */
|
||||
- if (!(phy_stat & HDMI_PHY_RX_SENSE))
|
||||
- hdmi->rxsense = false;
|
||||
-
|
||||
- /*
|
||||
- * Only set the software rxsense status when both
|
||||
- * rxsense and hpd indicates we're connected.
|
||||
- * This avoids what seems to be bad behaviour in
|
||||
- * at least iMX6S versions of the phy.
|
||||
- */
|
||||
- if (phy_stat & HDMI_PHY_HPD)
|
||||
- hdmi->rxsense = true;
|
||||
-
|
||||
- dw_hdmi_update_power(hdmi);
|
||||
- dw_hdmi_update_phy_mask(hdmi);
|
||||
- }
|
||||
- mutex_unlock(&hdmi->mutex);
|
||||
- }
|
||||
+ (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD))
|
||||
+ __dw_hdmi_setup_rx_sense(hdmi,
|
||||
+ phy_stat & HDMI_PHY_HPD,
|
||||
+ phy_stat & HDMI_PHY_RX_SENSE);
|
||||
|
||||
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
|
||||
dev_dbg(hdmi->dev, "EVENT=%s\n",
|
||||
@@ -2358,7 +2384,8 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
|
||||
#endif
|
||||
|
||||
dw_hdmi_fb_registered(hdmi);
|
||||
- dw_hdmi_phy_setup_hpd(hdmi);
|
||||
+ if (hdmi->phy.ops->setup_hpd)
|
||||
+ hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
|
||||
|
||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||
pdevinfo.parent = dev;
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 0da74fb..0668ae1 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -117,6 +117,9 @@ struct dw_hdmi_phy_ops {
|
||||
struct drm_display_mode *mode);
|
||||
void (*disable)(struct dw_hdmi *hdmi, void *data);
|
||||
enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data);
|
||||
+ void (*update_hpd)(struct dw_hdmi *hdmi, void *data,
|
||||
+ bool force, bool disabled, bool rxsense);
|
||||
+ void (*setup_hpd)(struct dw_hdmi *hdmi, void *data);
|
||||
};
|
||||
|
||||
struct dw_hdmi_plat_data {
|
||||
@@ -147,6 +150,8 @@ int dw_hdmi_probe(struct platform_device *pdev,
|
||||
int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
|
||||
const struct dw_hdmi_plat_data *plat_data);
|
||||
|
||||
+void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense);
|
||||
+
|
||||
void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
|
||||
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
|
||||
void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
From 8fb6f1d768e64d2df3f4effdb90a953ba0080a76 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Mon, 20 Mar 2017 12:04:14 +0100
|
||||
Subject: [PATCH 46/79] clk: take the prepare lock out of clk_core_set_parent
|
||||
|
||||
Rework set_parent core function so it can be called when the prepare lock
|
||||
is already held by the caller.
|
||||
|
||||
This rework is done to ease the integration of the "protected" clock
|
||||
functionality.
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/clk/clk.c | 39 ++++++++++++++++++---------------------
|
||||
1 file changed, 18 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
|
||||
index fc58c52..f5c3715 100644
|
||||
--- a/drivers/clk/clk.c
|
||||
+++ b/drivers/clk/clk.c
|
||||
@@ -1787,7 +1787,8 @@ bool clk_has_parent(struct clk *clk, struct clk *parent)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_has_parent);
|
||||
|
||||
-static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
|
||||
+static int clk_core_set_parent_nolock(struct clk_core *core,
|
||||
+ struct clk_core *parent)
|
||||
{
|
||||
int ret = 0;
|
||||
int p_index = 0;
|
||||
@@ -1796,23 +1797,16 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
|
||||
if (!core)
|
||||
return 0;
|
||||
|
||||
- /* prevent racing with updates to the clock topology */
|
||||
- clk_prepare_lock();
|
||||
-
|
||||
if (core->parent == parent)
|
||||
- goto out;
|
||||
+ return 0;
|
||||
|
||||
/* verify ops for for multi-parent clks */
|
||||
- if ((core->num_parents > 1) && (!core->ops->set_parent)) {
|
||||
- ret = -ENOSYS;
|
||||
- goto out;
|
||||
- }
|
||||
+ if ((core->num_parents > 1) && (!core->ops->set_parent))
|
||||
+ return -ENOSYS;
|
||||
|
||||
/* check that we are allowed to re-parent if the clock is in use */
|
||||
- if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
|
||||
- ret = -EBUSY;
|
||||
- goto out;
|
||||
- }
|
||||
+ if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count)
|
||||
+ return -EBUSY;
|
||||
|
||||
/* try finding the new parent index */
|
||||
if (parent) {
|
||||
@@ -1820,8 +1814,7 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
|
||||
if (p_index < 0) {
|
||||
pr_debug("%s: clk %s can not be parent of clk %s\n",
|
||||
__func__, parent->name, core->name);
|
||||
- ret = p_index;
|
||||
- goto out;
|
||||
+ return p_index;
|
||||
}
|
||||
p_rate = parent->rate;
|
||||
}
|
||||
@@ -1831,7 +1824,7 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
|
||||
|
||||
/* abort if a driver objects */
|
||||
if (ret & NOTIFY_STOP_MASK)
|
||||
- goto out;
|
||||
+ return ret;
|
||||
|
||||
/* do the re-parent */
|
||||
ret = __clk_set_parent(core, parent, p_index);
|
||||
@@ -1844,9 +1837,6 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
|
||||
__clk_recalc_accuracies(core);
|
||||
}
|
||||
|
||||
-out:
|
||||
- clk_prepare_unlock();
|
||||
-
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1869,10 +1859,17 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
|
||||
*/
|
||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
+ int ret;
|
||||
+
|
||||
if (!clk)
|
||||
return 0;
|
||||
|
||||
- return clk_core_set_parent(clk->core, parent ? parent->core : NULL);
|
||||
+ clk_prepare_lock();
|
||||
+ ret = clk_core_set_parent_nolock(clk->core,
|
||||
+ parent ? parent->core : NULL);
|
||||
+ clk_prepare_unlock();
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_parent);
|
||||
|
||||
@@ -2753,7 +2750,7 @@ void clk_unregister(struct clk *clk)
|
||||
/* Reparent all children to the orphan list. */
|
||||
hlist_for_each_entry_safe(child, t, &clk->core->children,
|
||||
child_node)
|
||||
- clk_core_set_parent(child, NULL);
|
||||
+ clk_core_set_parent_nolock(child, NULL);
|
||||
}
|
||||
|
||||
hlist_del_init(&clk->core->child_node);
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
From 050ccc8152e10f6d8ae44cf6772a78331d8df19e Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 2 Feb 2017 10:47:43 +0100
|
||||
Subject: [PATCH 46/93] drm: meson: rename module name to meson-drm
|
||||
|
||||
The module is currently named "meson.ko" which can lead to some
|
||||
confusion, this patches renames it "meson-drm.ko"
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1486028864-19622-2-git-send-email-narmstrong@baylibre.com
|
||||
---
|
||||
drivers/gpu/drm/meson/Makefile | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile
|
||||
index 2591978..92cf845 100644
|
||||
--- a/drivers/gpu/drm/meson/Makefile
|
||||
+++ b/drivers/gpu/drm/meson/Makefile
|
||||
@@ -1,4 +1,4 @@
|
||||
-meson-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
|
||||
-meson-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
|
||||
+meson-drm-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
|
||||
+meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
|
||||
|
||||
-obj-$(CONFIG_DRM_MESON) += meson.o
|
||||
+obj-$(CONFIG_DRM_MESON) += meson-drm.o
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
From 12e852dedde5d635713d095df5e83cc3ac54c64a Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Mon, 20 Mar 2017 12:20:41 +0100
|
||||
Subject: [PATCH 47/79] clk: add clk_core_set_phase_nolock function
|
||||
|
||||
Create a core function for set_phase, as it is done for set_rate and
|
||||
set_parent.
|
||||
|
||||
This rework is done to ease the integration of "protected" clock
|
||||
functionality.
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/clk/clk.c | 31 +++++++++++++++++++------------
|
||||
1 file changed, 19 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
|
||||
index f5c3715..dceaf0f 100644
|
||||
--- a/drivers/clk/clk.c
|
||||
+++ b/drivers/clk/clk.c
|
||||
@@ -1873,6 +1873,23 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_parent);
|
||||
|
||||
+static int clk_core_set_phase_nolock(struct clk_core *core, int degrees)
|
||||
+{
|
||||
+ int ret = -EINVAL;
|
||||
+
|
||||
+ if (!core)
|
||||
+ return 0;
|
||||
+
|
||||
+ trace_clk_set_phase(core, degrees);
|
||||
+
|
||||
+ if (core->ops->set_phase)
|
||||
+ ret = core->ops->set_phase(core->hw, degrees);
|
||||
+
|
||||
+ trace_clk_set_phase_complete(core, degrees);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* clk_set_phase - adjust the phase shift of a clock signal
|
||||
* @clk: clock signal source
|
||||
@@ -1895,7 +1912,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
*/
|
||||
int clk_set_phase(struct clk *clk, int degrees)
|
||||
{
|
||||
- int ret = -EINVAL;
|
||||
+ int ret;
|
||||
|
||||
if (!clk)
|
||||
return 0;
|
||||
@@ -1906,17 +1923,7 @@ int clk_set_phase(struct clk *clk, int degrees)
|
||||
degrees += 360;
|
||||
|
||||
clk_prepare_lock();
|
||||
-
|
||||
- trace_clk_set_phase(clk->core, degrees);
|
||||
-
|
||||
- if (clk->core->ops->set_phase)
|
||||
- ret = clk->core->ops->set_phase(clk->core->hw, degrees);
|
||||
-
|
||||
- trace_clk_set_phase_complete(clk->core, degrees);
|
||||
-
|
||||
- if (!ret)
|
||||
- clk->core->phase = degrees;
|
||||
-
|
||||
+ ret = clk_core_set_phase_nolock(clk->core, degrees);
|
||||
clk_prepare_unlock();
|
||||
|
||||
return ret;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
From e0f2204f17c247d5e9384d8a57835b480ff16115 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Thu, 2 Feb 2017 10:47:44 +0100
|
||||
Subject: [PATCH 47/93] drm: meson: rename driver name to meson-drm
|
||||
|
||||
The platform driver name is currently "meson" which can lead to some
|
||||
confusion, this patch renames it to "meson-drm" and removes the owner
|
||||
attribute since is always added by __platform_driver_register called by the
|
||||
module_platform_driver() macro.
|
||||
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Acked-by: Daniel Vetter <daniel@ffwll.ch>
|
||||
Link: http://patchwork.freedesktop.org/patch/msgid/1486028864-19622-3-git-send-email-narmstrong@baylibre.com
|
||||
---
|
||||
drivers/gpu/drm/meson/meson_drv.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
|
||||
index ff1f601..380bde7 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_drv.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_drv.c
|
||||
@@ -329,8 +329,7 @@ static int meson_drv_remove(struct platform_device *pdev)
|
||||
.probe = meson_drv_probe,
|
||||
.remove = meson_drv_remove,
|
||||
.driver = {
|
||||
- .owner = THIS_MODULE,
|
||||
- .name = DRIVER_NAME,
|
||||
+ .name = "meson-drm",
|
||||
.of_match_table = dt_match,
|
||||
},
|
||||
};
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
From c87711484070e9fb733330662a19f7fc1de9b368 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Mon, 20 Mar 2017 14:35:47 +0100
|
||||
Subject: [PATCH 48/79] clk: rework calls to round and determine rate callbacks
|
||||
|
||||
Rework the way the callbacks round_rate and determine_rate are called. The
|
||||
goal is to do this at a single point and make it easier to add conditions
|
||||
before calling them.
|
||||
|
||||
This rework is done to ease the integration of "protected" clock
|
||||
functionality.
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/clk/clk.c | 78 +++++++++++++++++++++++++++++++------------------------
|
||||
1 file changed, 44 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
|
||||
index dceaf0f..8cc4672 100644
|
||||
--- a/drivers/clk/clk.c
|
||||
+++ b/drivers/clk/clk.c
|
||||
@@ -833,16 +833,34 @@ static int clk_disable_unused(void)
|
||||
}
|
||||
late_initcall_sync(clk_disable_unused);
|
||||
|
||||
-static int clk_core_round_rate_nolock(struct clk_core *core,
|
||||
- struct clk_rate_request *req)
|
||||
+static int clk_core_determine_round(struct clk_core *core,
|
||||
+ struct clk_rate_request *req)
|
||||
{
|
||||
- struct clk_core *parent;
|
||||
long rate;
|
||||
|
||||
- lockdep_assert_held(&prepare_lock);
|
||||
+ if (core->ops->determine_rate) {
|
||||
+ return core->ops->determine_rate(core->hw, req);
|
||||
+ } else if (core->ops->round_rate) {
|
||||
+ rate = core->ops->round_rate(core->hw, req->rate,
|
||||
+ &req->best_parent_rate);
|
||||
+ if (rate < 0)
|
||||
+ return rate;
|
||||
|
||||
- if (!core)
|
||||
- return 0;
|
||||
+ req->rate = rate;
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void clk_core_init_rate_req(struct clk_core *core,
|
||||
+ struct clk_rate_request *req)
|
||||
+{
|
||||
+ struct clk_core *parent;
|
||||
+
|
||||
+ if (WARN_ON(!core || !req))
|
||||
+ return;
|
||||
|
||||
parent = core->parent;
|
||||
if (parent) {
|
||||
@@ -852,22 +870,24 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
|
||||
req->best_parent_hw = NULL;
|
||||
req->best_parent_rate = 0;
|
||||
}
|
||||
+}
|
||||
|
||||
- if (core->ops->determine_rate) {
|
||||
- return core->ops->determine_rate(core->hw, req);
|
||||
- } else if (core->ops->round_rate) {
|
||||
- rate = core->ops->round_rate(core->hw, req->rate,
|
||||
- &req->best_parent_rate);
|
||||
- if (rate < 0)
|
||||
- return rate;
|
||||
+static int clk_core_round_rate_nolock(struct clk_core *core,
|
||||
+ struct clk_rate_request *req)
|
||||
+{
|
||||
+ lockdep_assert_held(&prepare_lock);
|
||||
|
||||
- req->rate = rate;
|
||||
- } else if (core->flags & CLK_SET_RATE_PARENT) {
|
||||
- return clk_core_round_rate_nolock(parent, req);
|
||||
- } else {
|
||||
- req->rate = core->rate;
|
||||
- }
|
||||
+ if (!core)
|
||||
+ return 0;
|
||||
+
|
||||
+ clk_core_init_rate_req(core, req);
|
||||
+
|
||||
+ if (core->ops->determine_rate || core->ops->round_rate)
|
||||
+ return clk_core_determine_round(core, req);
|
||||
+ else if (core->flags & CLK_SET_RATE_PARENT)
|
||||
+ return clk_core_round_rate_nolock(core->parent, req);
|
||||
|
||||
+ req->rate = core->rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1356,36 +1376,26 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
|
||||
clk_core_get_boundaries(core, &min_rate, &max_rate);
|
||||
|
||||
/* find the closest rate and parent clk/rate */
|
||||
- if (core->ops->determine_rate) {
|
||||
+ if (core->ops->determine_rate || core->ops->round_rate) {
|
||||
struct clk_rate_request req;
|
||||
|
||||
req.rate = rate;
|
||||
req.min_rate = min_rate;
|
||||
req.max_rate = max_rate;
|
||||
- if (parent) {
|
||||
- req.best_parent_hw = parent->hw;
|
||||
- req.best_parent_rate = parent->rate;
|
||||
- } else {
|
||||
- req.best_parent_hw = NULL;
|
||||
- req.best_parent_rate = 0;
|
||||
- }
|
||||
|
||||
- ret = core->ops->determine_rate(core->hw, &req);
|
||||
+ clk_core_init_rate_req(core, &req);
|
||||
+
|
||||
+ ret = clk_core_determine_round(core, &req);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
best_parent_rate = req.best_parent_rate;
|
||||
new_rate = req.rate;
|
||||
parent = req.best_parent_hw ? req.best_parent_hw->core : NULL;
|
||||
- } else if (core->ops->round_rate) {
|
||||
- ret = core->ops->round_rate(core->hw, rate,
|
||||
- &best_parent_rate);
|
||||
- if (ret < 0)
|
||||
- return NULL;
|
||||
|
||||
- new_rate = ret;
|
||||
if (new_rate < min_rate || new_rate > max_rate)
|
||||
return NULL;
|
||||
+
|
||||
} else if (!parent || !(core->flags & CLK_SET_RATE_PARENT)) {
|
||||
/* pass-through clock without adjustable parent */
|
||||
core->new_rate = core->rate;
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
From 1f82a2baa3b5935ed41738f38cf486872aa8a9f7 Mon Sep 17 00:00:00 2001
|
||||
From: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Date: Fri, 13 Jan 2017 15:57:10 +0100
|
||||
Subject: [PATCH 48/93] drm/meson: Use crtc_state for hdisplay and fix atomic
|
||||
flush/enable sync for vsync commit
|
||||
|
||||
Clean the crtc_enable by using the proper crtc_state instead of the state
|
||||
of the primary plane state data.
|
||||
|
||||
Also fix the dependency to commit the plane changes even if enable is called
|
||||
after the flush.
|
||||
---
|
||||
drivers/gpu/drm/meson/meson_crtc.c | 15 +++++++++++----
|
||||
1 file changed, 11 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
|
||||
index 749770e..d4b114d 100644
|
||||
--- a/drivers/gpu/drm/meson/meson_crtc.c
|
||||
+++ b/drivers/gpu/drm/meson/meson_crtc.c
|
||||
@@ -60,11 +60,18 @@ struct meson_crtc {
|
||||
static void meson_crtc_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
|
||||
- struct drm_plane *plane = meson_crtc->priv->primary_plane;
|
||||
+ struct drm_crtc_state *crtc_state = crtc->state;
|
||||
struct meson_drm *priv = meson_crtc->priv;
|
||||
|
||||
+ DRM_DEBUG_DRIVER("\n");
|
||||
+
|
||||
+ if (!crtc_state) {
|
||||
+ DRM_ERROR("Invalid crtc_state\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* Enable VPP Postblend */
|
||||
- writel(plane->state->crtc_w,
|
||||
+ writel(crtc_state->mode.hdisplay,
|
||||
priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
|
||||
|
||||
writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
|
||||
@@ -79,6 +86,7 @@ static void meson_crtc_disable(struct drm_crtc *crtc)
|
||||
struct meson_drm *priv = meson_crtc->priv;
|
||||
|
||||
priv->viu.osd1_enabled = false;
|
||||
+ priv->viu.osd1_commit = false;
|
||||
|
||||
/* Disable VPP Postblend */
|
||||
writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
|
||||
@@ -115,8 +123,7 @@ static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
|
||||
struct meson_drm *priv = meson_crtc->priv;
|
||||
|
||||
- if (priv->viu.osd1_enabled)
|
||||
- priv->viu.osd1_commit = true;
|
||||
+ priv->viu.osd1_commit = true;
|
||||
}
|
||||
|
||||
static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
|
||||
--
|
||||
1.9.1
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
From 0e588289da294fb71f7873c2781758a7ba19dc7f Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Date: Fri, 19 May 2017 11:44:22 +0200
|
||||
Subject: [PATCH 49/79] clk: use round rate to bail out early in set_rate
|
||||
|
||||
The current implementation of clk_core_set_rate_nolock bails out early if
|
||||
the requested rate is exactly the same as the one set. It should bail out
|
||||
if the request would not result in rate a change. This important when rate
|
||||
is not exactly what is requested, which is fairly common with PLLs.
|
||||
|
||||
Ex: provider able to give any rate with steps of 100Hz
|
||||
- 1st consumer request 48000Hz and gets it.
|
||||
- 2nd consumer request 48010Hz as well. If we were to perform the usual
|
||||
mechanism, we would get 48000Hz as well. The clock would not change so
|
||||
there is no point performing any checks to make sure the clock can change,
|
||||
we know it won't.
|
||||
|
||||
This is important to prepare the addition of the clock protection mechanism
|
||||
|
||||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
---
|
||||
drivers/clk/clk.c | 23 +++++++++++++++++++++--
|
||||
1 file changed, 21 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
|
||||
index 8cc4672..163cb98 100644
|
||||
--- a/drivers/clk/clk.c
|
||||
+++ b/drivers/clk/clk.c
|
||||
@@ -1570,15 +1570,34 @@ static void clk_change_rate(struct clk_core *core)
|
||||
clk_change_rate(core->new_child);
|
||||
}
|
||||
|
||||
+static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core,
|
||||
+ unsigned long req_rate)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct clk_rate_request req;
|
||||
+
|
||||
+ if (!core)
|
||||
+ return 0;
|
||||
+
|
||||
+ clk_core_get_boundaries(core, &req.min_rate, &req.max_rate);
|
||||
+ req.rate = req_rate;
|
||||
+
|
||||
+ ret = clk_core_round_rate_nolock(core, &req);
|
||||
+
|
||||
+ return ret ? 0 : req.rate;
|
||||
+}
|
||||
+
|
||||
static int clk_core_set_rate_nolock(struct clk_core *core,
|
||||
unsigned long req_rate)
|
||||
{
|
||||
struct clk_core *top, *fail_clk;
|
||||
- unsigned long rate = req_rate;
|
||||
+ unsigned long rate;
|
||||
|
||||
if (!core)
|
||||
return 0;
|
||||
|
||||
+ rate = clk_core_req_round_rate_nolock(core, req_rate);
|
||||
+
|
||||
/* bail early if nothing to do */
|
||||
if (rate == clk_core_get_rate_nolock(core))
|
||||
return 0;
|
||||
@@ -1587,7 +1606,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
|
||||
return -EBUSY;
|
||||
|
||||
/* calculate new rates and get the topmost changed clock */
|
||||
- top = clk_calc_new_rates(core, rate);
|
||||
+ top = clk_calc_new_rates(core, req_rate);
|
||||
if (!top)
|
||||
return -EINVAL;
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue