Allwinner A64 has display engine pipeline like other Allwinner SOC's A83T/H3/H5.
A64 behaviour similar to Allwinner A83T where
Mixer0 => TCON0 => LVDS/RGB/MIPI-DSI
Mixer1 => TCON1 => HDMI
as per Display System Block DiagramAllwinner_A64_User_Manual_V1.1.pdf
This is second patch-set followed with previous RFC[1] and first series[2]
and merely concentrated on HDMI pipeline through TCON1 and rest will add eventually.
This series fixed previous version comments
- about documenting fallback compatibles
- adding new compatible for mixer1
- support for multiple DW HDMI PHY clock parents (thanks, to Jernej)
Note:
Pine64 boards are unable to get edid by default like other A64 boards,
but forcing 'video=HDMI-A-1:1920x1080@60D' kernel command line can
create edid with display on penel.
Log:
[ 1.613196] sun4i-drm display-engine: bound 1200000.mixer (ops sun8i_mixer_ops)
[ 1.620764] sun4i-drm display-engine: No panel or bridge found... RGB output disabled
[ 1.628612] sun4i-drm display-engine: bound 1c0d000.lcd-controller (ops sun4i_tcon_ops)
[ 1.637677] sun8i-dw-hdmi 1ee0000.hdmi: Detected HDMI TX controller v1.32a with HDCP (sun8i_dw_hdmi_ph
y)
[ 1.647699] sun8i-dw-hdmi 1ee0000.hdmi: registered DesignWare HDMI I2C bus driver
[ 1.656090] [drm] forcing HDMI-A-1 connector on
[ 1.660664] sun4i-drm display-engine: bound 1ee0000.hdmi (ops sun8i_dw_hdmi_ops)
[ 1.668063] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[ 1.674684] [drm] No driver support for vblank timestamp query.
[ 2.497502] Console: switching to colour frame buffer device 240x67
[ 2.551795] sun4i-drm display-engine: fb0: frame buffer device
[ 2.558166] [drm] Initialized sun4i-drm 1.0.0 20150629 for display-engine on minor 0
[2] https://lkml.org/lkml/2018/4/30/288
[1] https://lkml.org/lkml/2018/4/24/547
Icenowy Zheng (1):
drm: sun4i: add support for HVCC regulator for DWC HDMI glue
Jagan Teki (22):
dt-bindings: clock: Add compatible for A64 DE2 CCU
arm64: dts: allwinner: a64: Add DE2 CCU
clk: sunxi-ng: Enable DE2_CCU for SUN8I and SUN50I
clk: sunxi-ng: a64: Add minimal rate for video PLLs
drm/sun4i: Add support for A64 mixer1
dt-bindings: display: Add compatible for A64 DE2 tcon1 blocks
drm/sun4i: Add support for A64 display engine
arm64: dts: allwinner: a64: Add DE2 tcon1 pipeline
drm/sun4i: Enable DE2 Mixer for SUN8I and SUN50I
arm64: defconfig: Enable CONFIG_DRM_SUN4I
dt-bindings: display: Add compatible for A64 HDMI
dt-bindings: display: Add compatible for A64 HDMI PHY
dt-bindings: clock: sun50i-a64-ccu: Add PLL_VIDEO[0-1] macros
arm64: dts: allwinner: a64: Add HDMI support
drm/sun4i: Enable DesignWare HDMI for SUN8I and SUN50I
arm64: dts: allwinner: a64: Add HDMI pipeline
arm64: dts: allwinner: a64: bananapi-m64: Enable HDMI output
arm64: dts: allwinner: a64: nanopi-a64: Enable HDMI output
arm64: dts: allwinner: a64: orangepi-win: Enable HDMI output
arm64: dts: allwinner: a64: a64-olinuxino: Enable HDMI output
arm64: dts: allwinner: a64: pine64: Enable HDMI output
arm64: dts: allwinner: a64: sopine: Enable HDMI output
Jernej Skrabec (3):
drm/sun4i: DE2 mixer: Add index quirk
drm/sun4i: Add support for multiple DW HDMI PHY clock parents
drm/sun4i: Add support for A64 HDMI PHY
.../devicetree/bindings/clock/sun8i-de2.txt | 1 +
.../bindings/display/sunxi/sun4i-drm.txt | 5 +
.../boot/dts/allwinner/sun50i-a64-bananapi-m64.dts | 26 +++++
.../boot/dts/allwinner/sun50i-a64-nanopi-a64.dts | 26 +++++
.../boot/dts/allwinner/sun50i-a64-olinuxino.dts | 26 +++++
.../boot/dts/allwinner/sun50i-a64-orangepi-win.dts | 26 +++++
.../arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 26 +++++
.../dts/allwinner/sun50i-a64-sopine-baseboard.dts | 26 +++++
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 124 +++++++++++++++++++++
arch/arm64/configs/defconfig | 1 +
drivers/clk/sunxi-ng/Kconfig | 2 +
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 46 ++++----
drivers/gpu/drm/sun4i/Kconfig | 3 +-
drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 14 +++
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 11 +-
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 44 ++++++--
drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 89 +++++++++++----
drivers/gpu/drm/sun4i/sun8i_mixer.c | 17 ++-
drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 +
include/dt-bindings/clock/sun50i-a64-ccu.h | 2 +
21 files changed, 458 insertions(+), 60 deletions(-)
--
2.14.3
Allwinner A64 has DE2 CCU is similar to H3/H5 SoC.
So add compatible for A64 which is fallback compatible
for H5, so update fallback binding.
Signed-off-by: Jagan Teki <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
Changes for v2:
- Add fallback compatible
Documentation/devicetree/bindings/clock/sun8i-de2.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
index f2fa87c4765c..e3ffe0bcd0a0 100644
--- a/Documentation/devicetree/bindings/clock/sun8i-de2.txt
+++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
@@ -7,6 +7,7 @@ Required properties :
- "allwinner,sun8i-h3-de2-clk"
- "allwinner,sun8i-v3s-de2-clk"
- "allwinner,sun50i-h5-de2-clk"
+ - "allwinner,sun50i-a64-de2-clk", "allwinner,sun50i-h5-de2-clk"
- reg: Must contain the registers base address and length
- clocks: phandle to the clocks feeding the display engine subsystem.
--
2.14.3
DE2 CCU in Allwinner A64 has same like H5, so use the
similar dts details for A64 with fallback compatible.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- Add h5 compatible first since A64 came first.
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 1b2ef28c42bd..26c2a9c44727 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -43,9 +43,11 @@
*/
#include <dt-bindings/clock/sun50i-a64-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
#include <dt-bindings/clock/sun8i-r-ccu.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/sun50i-a64-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
/ {
interrupt-parent = <&gic>;
@@ -168,6 +170,19 @@
#size-cells = <1>;
ranges;
+ display_clocks: clock@1000000 {
+ compatible = "allwinner,sun50i-h5-de2-clk",
+ "allwinner,sun50i-a64-de2-clk";
+ reg = <0x01000000 0x100000>;
+ clocks = <&ccu CLK_DE>,
+ <&ccu CLK_BUS_DE>;
+ clock-names = "mod",
+ "bus";
+ resets = <&ccu RST_BUS_DE>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
syscon: syscon@1c00000 {
compatible = "allwinner,sun50i-a64-system-controller",
"syscon";
--
2.14.3
Allwinner SoC like SUN8I and SUN50I has DE2 CCU so enable them
as default.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- Enable for MACH_SUN8I
drivers/clk/sunxi-ng/Kconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 826674d090fd..e20182aa9748 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -63,6 +63,8 @@ config SUN8I_V3S_CCU
config SUN8I_DE2_CCU
bool "Support for the Allwinner SoCs DE2 CCU"
+ default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
+ depends on DRM_SUN4I && (MACH_SUN8I || (ARM64 && ARCH_SUNXI))
config SUN8I_R40_CCU
bool "Support for the Allwinner R40 CCU"
--
2.14.3
According to documentation and experience with other similar SoCs, video
PLLs don't work stable if their output frequency is set below 192 MHz.
Because of that, set minimal rate to both A64 video PLLs to 192 MHz.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- New patch
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 46 ++++++++++++++++++-----------------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index ee9c12cf3f08..d0e30192f0cf 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -64,17 +64,18 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
BIT(28), /* lock */
CLK_SET_RATE_UNGATE);
-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0",
- "osc24M", 0x010,
- 8, 7, /* N */
- 0, 4, /* M */
- BIT(24), /* frac enable */
- BIT(25), /* frac select */
- 270000000, /* frac rate 0 */
- 297000000, /* frac rate 1 */
- BIT(31), /* gate */
- BIT(28), /* lock */
- CLK_SET_RATE_UNGATE);
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video0_clk, "pll-video0",
+ "osc24M", 0x010,
+ 192000000, /* Minimum rate */
+ 8, 7, /* N */
+ 0, 4, /* M */
+ BIT(24), /* frac enable */
+ BIT(25), /* frac select */
+ 270000000, /* frac rate 0 */
+ 297000000, /* frac rate 1 */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
"osc24M", 0x018,
@@ -125,17 +126,18 @@ static struct ccu_nk pll_periph1_clk = {
},
};
-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1",
- "osc24M", 0x030,
- 8, 7, /* N */
- 0, 4, /* M */
- BIT(24), /* frac enable */
- BIT(25), /* frac select */
- 270000000, /* frac rate 0 */
- 297000000, /* frac rate 1 */
- BIT(31), /* gate */
- BIT(28), /* lock */
- CLK_SET_RATE_UNGATE);
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video1_clk, "pll-video1",
+ "osc24M", 0x030,
+ 192000000, /* Minimum rate */
+ 8, 7, /* N */
+ 0, 4, /* M */
+ BIT(24), /* frac enable */
+ BIT(25), /* frac select */
+ 270000000, /* frac rate 0 */
+ 297000000, /* frac rate 1 */
+ BIT(31), /* gate */
+ BIT(28), /* lock */
+ CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
"osc24M", 0x038,
--
2.14.3
Mixers in Allwinner have similar capabilities as others SoCs with DE2.
Mixer1 has 1 VI and 1 UI planes and supports HW scaling on all
planes.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- New patch
drivers/gpu/drm/sun4i/sun8i_mixer.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 36d90c76317a..5b02c6ee2be6 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -508,6 +508,15 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
.mod_rate = 150000000,
};
+static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
+ .ccsc = 1,
+ .index = 1,
+ .mod_rate = 297000000,
+ .scaler_mask = 0x3,
+ .ui_num = 1,
+ .vi_num = 1,
+};
+
static const struct of_device_id sun8i_mixer_of_table[] = {
{
.compatible = "allwinner,sun8i-a83t-de2-mixer-0",
@@ -525,6 +534,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = {
.compatible = "allwinner,sun8i-v3s-de2-mixer",
.data = &sun8i_v3s_mixer_cfg,
},
+ {
+ .compatible = "allwinner,sun50i-a64-de2-mixer-1",
+ .data = &sun50i_a64_mixer1_cfg,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
--
2.14.3
The DE2 on the A64 is mainly composed of the mixers and tcons,
plus various encoders.
This patch add second mixer and tcon which eventually useful
for testing HDMI. the other part of DE2 will add in future.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- Change compatibles and other based on previous patch changes
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 61 +++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 26c2a9c44727..9c1452ee8027 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -107,6 +107,12 @@
};
};
+ de: display-engine {
+ compatible = "allwinner,sun50i-a64-display-engine";
+ allwinner,pipelines = <&mixer1>;
+ status = "disabled";
+ };
+
osc24M: osc24M_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
@@ -183,6 +189,30 @@
#reset-cells = <1>;
};
+ mixer1: mixer@1200000 {
+ compatible = "allwinner,sun50i-a64-de2-mixer-1";
+ reg = <0x01200000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER1>,
+ <&display_clocks CLK_MIXER1>;
+ clock-names = "bus",
+ "mod";
+ resets = <&display_clocks RST_WB>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer1_out: port@1 {
+ reg = <1>;
+
+ mixer1_out_tcon1: endpoint {
+ remote-endpoint = <&tcon1_in_mixer1>;
+ };
+ };
+ };
+ };
+
+
syscon: syscon@1c00000 {
compatible = "allwinner,sun50i-a64-system-controller",
"syscon";
@@ -200,6 +230,37 @@
#dma-cells = <1>;
};
+ tcon1: lcd-controller@1c0d000 {
+ compatible = "allwinner,sun50i-a64-tcon-tv",
+ "allwinner,sun8i-a83t-tcon-tv";
+ reg = <0x01c0d000 0x1000>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON1>, <&ccu CLK_TCON1>;
+ clock-names = "ahb", "tcon-ch1";
+ resets = <&ccu RST_BUS_TCON1>;
+ reset-names = "lcd";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon1_in: port@0 {
+ reg = <0>;
+
+ tcon1_in_mixer1: endpoint {
+ remote-endpoint = <&mixer1_out_tcon1>;
+ };
+ };
+
+ tcon1_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ };
+ };
+ };
+
mmc0: mmc@1c0f000 {
compatible = "allwinner,sun50i-a64-mmc";
reg = <0x01c0f000 0x1000>;
--
2.14.3
Enable DRM Support for Allwinner Display Engine, built as a module.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index d25121b087bb..d2db76f296cf 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -421,6 +421,7 @@ CONFIG_DRM_EXYNOS_DSI=y
CONFIG_DRM_EXYNOS_HDMI=y
CONFIG_DRM_EXYNOS_MIC=y
CONFIG_DRM_ROCKCHIP=m
+CONFIG_DRM_SUN4I=m
CONFIG_ROCKCHIP_ANALOGIX_DP=y
CONFIG_ROCKCHIP_CDN_DP=y
CONFIG_ROCKCHIP_DW_HDMI=y
--
2.14.3
From: Jernej Skrabec <[email protected]>
PHY is the same as in H3, except it can select between two clock parent.
Signed-off-by: Jernej Skrabec <[email protected]>
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- new patch
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 0eadf087fc46..39fbf7257fce 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -392,6 +392,13 @@ static struct regmap_config sun8i_hdmi_phy_regmap_config = {
.name = "phy"
};
+static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
+ .phy_clk_num = 2,
+ .phy_init = &sun8i_hdmi_phy_init_h3,
+ .phy_disable = &sun8i_hdmi_phy_disable_h3,
+ .phy_config = &sun8i_hdmi_phy_config_h3,
+};
+
static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
.phy_init = &sun8i_hdmi_phy_init_a83t,
.phy_disable = &sun8i_hdmi_phy_disable_a83t,
@@ -406,6 +413,10 @@ static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
};
static const struct of_device_id sun8i_hdmi_phy_of_table[] = {
+ {
+ .compatible = "allwinner,sun50i-a64-hdmi-phy",
+ .data = &sun50i_a64_hdmi_phy,
+ },
{
.compatible = "allwinner,sun8i-a83t-hdmi-phy",
.data = &sun8i_a83t_hdmi_phy,
--
2.14.3
HDMI on Allwinner A64 has similar like H3/H5/A83T.
Add compatible a64 and update A83T compatible as fallback.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- Add fallback compatible
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 863afad6a4df..1a5ff416dea4 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -78,6 +78,7 @@ Required properties:
- compatible: value must be one of:
* "allwinner,sun8i-a83t-dw-hdmi"
+ * "allwinner,sun50i-a64-dw-hdmi", "allwinner,sun8i-a83t-dw-hdmi"
- reg: base address and size of memory-mapped region
- reg-io-width: See dw_hdmi.txt. Shall be 1.
- interrupts: HDMI interrupt number
--
2.14.3
Display Engine(DE2) in Allwinner A64 has two mixers and tcons.
The routing for mixer0 is through tcon0 and connected to
LVDS/RGB/MIPI-DSI controller.
The routing for mixer1 is through tcon1 and connected to HDMI.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 50d19605c38f..c84102a750f8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -368,6 +368,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
{ .compatible = "allwinner,sun8i-h3-display-engine" },
{ .compatible = "allwinner,sun8i-v3s-display-engine" },
{ .compatible = "allwinner,sun9i-a80-display-engine" },
+ { .compatible = "allwinner,sun50i-a64-display-engine" },
{ }
};
MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
--
2.14.3
Allwinner A64 has DE2 pipeline with tcon0 and tcon1 block
which is similar Allwinner A83T.
This patch adds dt-binding documentation for A64 DE2 tcon1 blocks.
Mixer1 has different configuration for A64 so use separate compatible
but tcon1 has similar behaviour with A83T so add fallback compatible.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- Add fallback compatible for tcon1
- Add separate compatible for mixer1
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 3346c1e2a7a0..863afad6a4df 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -148,6 +148,7 @@ Required properties:
* allwinner,sun8i-v3s-tcon
* allwinner,sun9i-a80-tcon-lcd
* allwinner,sun9i-a80-tcon-tv
+ * "allwinner,sun50i-a64-tcon-tv", "allwinner,sun8i-a83t-tcon-tv"
- reg: base address and size of memory-mapped region
- interrupts: interrupt associated to this IP
- clocks: phandles to the clocks feeding the TCON.
@@ -311,6 +312,7 @@ Required properties:
* allwinner,sun8i-a83t-de2-mixer-1
* allwinner,sun8i-h3-de2-mixer-0
* allwinner,sun8i-v3s-de2-mixer
+ * allwinner,sun50i-a64-de2-mixer-1"
- reg: base address and size of the memory-mapped region.
- clocks: phandles to the clocks feeding the mixer
* bus: the mixer interface clock
@@ -343,6 +345,7 @@ Required properties:
* allwinner,sun8i-h3-display-engine
* allwinner,sun8i-v3s-display-engine
* allwinner,sun9i-a80-display-engine
+ * allwinner,sun50i-a64-display-engine
- allwinner,pipelines: list of phandle to the display engine
frontends (DE 1.0) or mixers (DE 2.0) available.
--
2.14.3
Allwinner SoC like SUN8I and SUN50I are now using DE2 Mixer
so enable them as default.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- Enable for SUN8I
drivers/gpu/drm/sun4i/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 156a865c3e6d..a84120025197 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -61,7 +61,7 @@ config DRM_SUN8I_DW_HDMI
config DRM_SUN8I_MIXER
tristate "Support for Allwinner Display Engine 2.0 Mixer"
- default MACH_SUN8I
+ default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
help
Choose this option if you have an Allwinner SoC with the
Allwinner Display Engine 2.0, which has a mixer to do some
--
2.14.3
From: Jernej Skrabec <[email protected]>
Some SoCs with DW HDMI have multiple possible clock parents, like A64
and R40.
Expand HDMI PHY clock driver to support second clock parent.
Signed-off-by: Jernej Skrabec <[email protected]>
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- new patch
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 9 ++-
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 33 ++++++++---
drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 89 ++++++++++++++++++++++--------
3 files changed, 96 insertions(+), 35 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 79154f0f674a..303189d6602c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -98,7 +98,8 @@
#define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN BIT(29)
#define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN BIT(28)
#define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 BIT(27)
-#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL BIT(26)
+#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK BIT(26)
+#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT 26
#define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN BIT(25)
#define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22)
#define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20)
@@ -146,7 +147,7 @@
struct sun8i_hdmi_phy;
struct sun8i_hdmi_phy_variant {
- bool has_phy_clk;
+ int phy_clk_num;
void (*phy_init)(struct sun8i_hdmi_phy *phy);
void (*phy_disable)(struct dw_hdmi *hdmi,
struct sun8i_hdmi_phy *phy);
@@ -160,6 +161,7 @@ struct sun8i_hdmi_phy {
struct clk *clk_mod;
struct clk *clk_phy;
struct clk *clk_pll0;
+ struct clk *clk_pll1;
unsigned int rcal;
struct regmap *regs;
struct reset_control *rst_phy;
@@ -188,6 +190,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi);
void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
-int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev);
+int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
+ int clk_num);
#endif /* _SUN8I_DW_HDMI_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 5a52fc489a9d..0eadf087fc46 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
- regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
+ /*
+ * NOTE: We have to be careful not to overwrite PHY parent
+ * clock selection bit and clock divider.
+ */
+ regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
+ (u32)~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
+ pll_cfg1_init);
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
(u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
pll_cfg2_init);
@@ -232,7 +238,7 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
- if (phy->variant->has_phy_clk)
+ if (phy->variant->phy_clk_num)
clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000);
return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000);
@@ -393,7 +399,7 @@ static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
};
static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
- .has_phy_clk = true,
+ .phy_clk_num = 1,
.phy_init = &sun8i_hdmi_phy_init_h3,
.phy_disable = &sun8i_hdmi_phy_disable_h3,
.phy_config = &sun8i_hdmi_phy_config_h3,
@@ -464,7 +470,7 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
goto err_put_clk_bus;
}
- if (phy->variant->has_phy_clk) {
+ if (phy->variant->phy_clk_num) {
phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
if (IS_ERR(phy->clk_pll0)) {
dev_err(dev, "Could not get pll-0 clock\n");
@@ -472,7 +478,16 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
goto err_put_clk_mod;
}
- ret = sun8i_phy_clk_create(phy, dev);
+ if (phy->variant->phy_clk_num) {
+ phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
+ if (IS_ERR(phy->clk_pll1)) {
+ dev_err(dev, "Could not get pll-1 clock\n");
+ ret = PTR_ERR(phy->clk_pll1);
+ goto err_put_clk_mod;
+ }
+ }
+
+ ret = sun8i_phy_clk_create(phy, dev, phy->variant->phy_clk_num);
if (ret) {
dev_err(dev, "Couldn't create the PHY clock\n");
goto err_put_clk_pll0;
@@ -515,8 +530,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
err_put_rst_phy:
reset_control_put(phy->rst_phy);
err_put_clk_pll0:
- if (phy->variant->has_phy_clk)
- clk_put(phy->clk_pll0);
+ clk_put(phy->clk_pll0);
+ clk_put(phy->clk_pll1);
err_put_clk_mod:
clk_put(phy->clk_mod);
err_put_clk_bus:
@@ -536,8 +551,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
reset_control_put(phy->rst_phy);
- if (phy->variant->has_phy_clk)
- clk_put(phy->clk_pll0);
+ clk_put(phy->clk_pll0);
+ clk_put(phy->clk_pll1);
clk_put(phy->clk_mod);
clk_put(phy->clk_bus);
}
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
index faea449812f8..85b12fc96dbc 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
@@ -22,29 +22,36 @@ static int sun8i_phy_clk_determine_rate(struct clk_hw *hw,
{
unsigned long rate = req->rate;
unsigned long best_rate = 0;
- struct clk_hw *parent;
+ struct clk_hw *best_parent = NULL;
+ struct clk_hw *parent = NULL;
int best_div = 1;
- int i;
+ int i, p;
- parent = clk_hw_get_parent(hw);
-
- for (i = 1; i <= 16; i++) {
- unsigned long ideal = rate * i;
- unsigned long rounded;
-
- rounded = clk_hw_round_rate(parent, ideal);
-
- if (rounded == ideal) {
- best_rate = rounded;
- best_div = i;
- break;
- }
+ for (p = 0; p < clk_hw_get_num_parents(hw); p++) {
+ parent = clk_hw_get_parent_by_index(hw, p);
+ if (!parent)
+ continue;
- if (!best_rate ||
- abs(rate - rounded / i) <
- abs(rate - best_rate / best_div)) {
- best_rate = rounded;
- best_div = i;
+ for (i = 1; i <= 16; i++) {
+ unsigned long ideal = rate * i;
+ unsigned long rounded;
+
+ rounded = clk_hw_round_rate(parent, ideal);
+
+ if (rounded == ideal) {
+ best_rate = rounded;
+ best_div = i;
+ best_parent = parent;
+ break;
+ }
+
+ if (!best_rate ||
+ abs(rate - rounded / i) <
+ abs(rate - best_rate / best_div)) {
+ best_rate = rounded;
+ best_div = i;
+ best_parent = parent;
+ }
}
}
@@ -95,22 +102,58 @@ static int sun8i_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
+static u8 sun8i_phy_clk_get_parent(struct clk_hw *hw)
+{
+ struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
+ u32 reg;
+
+ regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, ®);
+ reg = (reg & SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK) >>
+ SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT;
+
+ return reg;
+}
+
+static int sun8i_phy_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
+
+ if (index > 1)
+ return -EINVAL;
+
+ regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
+ SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
+ index << SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT);
+
+ return 0;
+}
+
static const struct clk_ops sun8i_phy_clk_ops = {
.determine_rate = sun8i_phy_clk_determine_rate,
.recalc_rate = sun8i_phy_clk_recalc_rate,
.set_rate = sun8i_phy_clk_set_rate,
+
+ .get_parent = sun8i_phy_clk_get_parent,
+ .set_parent = sun8i_phy_clk_set_parent,
};
-int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev)
+int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
+ int clk_num)
{
struct clk_init_data init;
struct sun8i_phy_clk *priv;
- const char *parents[1];
+ const char *parents[2];
parents[0] = __clk_get_name(phy->clk_pll0);
if (!parents[0])
return -ENODEV;
+ if (clk_num == 2) {
+ parents[1] = __clk_get_name(phy->clk_pll1);
+ if (!parents[1])
+ return -ENODEV;
+ }
+
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -118,7 +161,7 @@ int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev)
init.name = "hdmi-phy-clk";
init.ops = &sun8i_phy_clk_ops;
init.parent_names = parents;
- init.num_parents = 1;
+ init.num_parents = clk_num;
init.flags = CLK_SET_RATE_PARENT;
priv->phy = phy;
--
2.14.3
Allwinner SoC like SUN8I and SUN50I are now using DesignWare HDMI
so enable them as default.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- Enable for SUN8I
drivers/gpu/drm/sun4i/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index a84120025197..c10617c1f84b 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -52,6 +52,7 @@ config DRM_SUN6I_DSI
config DRM_SUN8I_DW_HDMI
tristate "Support for Allwinner version of DesignWare HDMI"
+ default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
depends on DRM_SUN4I
select DRM_DW_HDMI
help
--
2.14.3
HDMI pipeline on Allwinner A64 has similar behavior like A83T
where tcon1 is connected to HDMI.
Setup the pipeline according to that.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 4ffd4787acd2..8ec6559d10cc 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -257,6 +257,10 @@
#size-cells = <0>;
reg = <1>;
+ tcon1_out_hdmi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&hdmi_in_tcon1>;
+ };
};
};
};
@@ -719,6 +723,23 @@
phys = <&hdmi_phy>;
phy-names = "hdmi-phy";
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi_in: port@0 {
+ reg = <0>;
+
+ hdmi_in_tcon1: endpoint {
+ remote-endpoint = <&tcon1_out_hdmi>;
+ };
+ };
+
+ hdmi_out: port@1 {
+ reg = <1>;
+ };
+ };
};
hdmi_phy: hdmi-phy@1ef0000 {
--
2.14.3
Enable HDMI output on Bananpi-m64 board.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
.../boot/dts/allwinner/sun50i-a64-bananapi-m64.dts | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
index 0716b1441187..bbbf7b17b70b 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
@@ -60,6 +60,17 @@
stdout-path = "serial0:115200n8";
};
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
@@ -86,6 +97,10 @@
};
};
+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -103,6 +118,17 @@
status = "okay";
};
+&hdmi {
+ hvcc-supply = <®_dldo1>;
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
--
2.14.3
Enable HDMI output on pine64 board.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
.../arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
index a75825798a71..a4ec0900a885 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
@@ -62,6 +62,21 @@
chosen {
stdout-path = "serial0:115200n8";
};
+
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+};
+
+&de {
+ status = "okay";
};
&ehci0 {
@@ -82,6 +97,17 @@
};
+&hdmi {
+ hvcc-supply = <®_dldo1>;
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
--
2.14.3
Allwinner A64 has two clock parents PLL_VIDEO0 and PLL_VIDEO1.
Include these macros on dt-bindings so-that the same can be
used while defining CCU clock phadles.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- new patch
include/dt-bindings/clock/sun50i-a64-ccu.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h
index d66432c6e675..d1d7d5b7d06a 100644
--- a/include/dt-bindings/clock/sun50i-a64-ccu.h
+++ b/include/dt-bindings/clock/sun50i-a64-ccu.h
@@ -43,7 +43,9 @@
#ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_
#define _DT_BINDINGS_CLK_SUN50I_A64_H_
+#define CLK_PLL_VIDEO0 7
#define CLK_PLL_PERIPH0 11
+#define CLK_PLL_VIDEO1 15
#define CLK_BUS_MIPI_DSI 28
#define CLK_BUS_CE 29
--
2.14.3
Enable HDMI output on a64-olinuxino board.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
.../boot/dts/allwinner/sun50i-a64-olinuxino.dts | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
index 3b3081b10ecb..83329c8fec4f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
@@ -58,12 +58,38 @@
stdout-path = "serial0:115200n8";
};
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
};
};
+&de {
+ status = "okay";
+};
+
+&hdmi {
+ hvcc-supply = <®_dldo1>;
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
--
2.14.3
Enable HDMI output on Orangepi-win board.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
.../boot/dts/allwinner/sun50i-a64-orangepi-win.dts | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
index bf42690a3361..b6fdd052d473 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
@@ -57,12 +57,38 @@
chosen {
stdout-path = "serial0:115200n8";
};
+
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+};
+
+&de {
+ status = "okay";
};
&ehci1 {
status = "okay";
};
+&hdmi {
+ hvcc-supply = <®_dldo1>;
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
--
2.14.3
Enable HDMI output on sopine board.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
.../dts/allwinner/sun50i-a64-sopine-baseboard.dts | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
index abe179de35d7..72f29b78117c 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
@@ -61,6 +61,17 @@
stdout-path = "serial0:115200n8";
};
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
reg_vcc1v8: vcc1v8 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8";
@@ -69,6 +80,10 @@
};
};
+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -86,6 +101,17 @@
status = "okay";
};
+&hdmi {
+ hvcc-supply = <®_dldo1>;
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&mdio {
ext_rgmii_phy: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
--
2.14.3
From: Icenowy Zheng <[email protected]>
Allwinner SoCs with DWC HDMI controller have a "HVCC" power pin for the
HDMI part, and on some boards it's connected to a dedicated regulator
rather than the main 3.3v.
Add support for optional HVCC regulator. For boards that doesn't use a
dedicated regulator to power it, the default dummy regulator is used.
Signed-off-by: Icenowy Zheng <[email protected]>
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 14 ++++++++++++++
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 ++
2 files changed, 16 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 9f40a44b456b..7c33faff7ad4 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -73,6 +73,12 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
if (encoder->possible_crtcs == 0)
return -EPROBE_DEFER;
+ hdmi->vcc_hdmi = devm_regulator_get(dev, "hvcc");
+ if (IS_ERR(hdmi->vcc_hdmi)) {
+ dev_err(dev, "Could not get HDMI power supply\n");
+ return PTR_ERR(hdmi->vcc_hdmi);
+ }
+
hdmi->rst_ctrl = devm_reset_control_get(dev, "ctrl");
if (IS_ERR(hdmi->rst_ctrl)) {
dev_err(dev, "Could not get ctrl reset control\n");
@@ -91,6 +97,12 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
return ret;
}
+ ret = regulator_enable(hdmi->vcc_hdmi);
+ if (ret) {
+ dev_err(dev, "Cannot enable HDMI power supply\n");
+ goto err_disable_vcc;
+ }
+
ret = clk_prepare_enable(hdmi->clk_tmds);
if (ret) {
dev_err(dev, "Could not enable tmds clock\n");
@@ -143,6 +155,8 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
clk_disable_unprepare(hdmi->clk_tmds);
err_assert_ctrl_reset:
reset_control_assert(hdmi->rst_ctrl);
+err_disable_vcc:
+ regulator_disable(hdmi->vcc_hdmi);
return ret;
}
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 303189d6602c..65366eeb38d8 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -10,6 +10,7 @@
#include <drm/drm_encoder.h>
#include <linux/clk.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000
@@ -175,6 +176,7 @@ struct sun8i_dw_hdmi {
struct drm_encoder encoder;
struct sun8i_hdmi_phy *phy;
struct dw_hdmi_plat_data plat_data;
+ struct regulator *vcc_hdmi;
struct reset_control *rst_ctrl;
};
--
2.14.3
Enable HDMI output on nanopi-a64 board.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- none
.../boot/dts/allwinner/sun50i-a64-nanopi-a64.dts | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts
index e2dce48fa29a..19fe7eed45e9 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts
@@ -57,6 +57,21 @@
chosen {
stdout-path = "serial0:115200n8";
};
+
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+};
+
+&de {
+ status = "okay";
};
&ehci0 {
@@ -67,6 +82,17 @@
status = "okay";
};
+&hdmi {
+ hvcc-supply = <®_dldo1>;
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
/* i2c1 connected with gpio headers like pine64, bananapi */
&i2c1 {
pinctrl-names = "default";
--
2.14.3
HDMI on Allwinner A64 has similar behaviour like H3/H5/A83T, so
reuse the same dts node details for A64 with A83T compatible
as fallback.
HDMI PHY on Allwinner A64 has two clock parents so add them
as pll-0 and pll-1 in CCU clock phadles.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- Change compatibles and other based on previous patch changes
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 9c1452ee8027..4ffd4787acd2 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -705,6 +705,33 @@
#interrupt-cells = <3>;
};
+ hdmi: hdmi@1ee0000 {
+ compatible = "allwinner,sun50i-a64-dw-hdmi",
+ "allwinner,sun8i-a83t-dw-hdmi";
+ reg = <0x01ee0000 0x10000>;
+ reg-io-width = <1>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_DDC>,
+ <&ccu CLK_HDMI>;
+ clock-names = "iahb", "isfr", "tmds";
+ resets = <&ccu RST_BUS_HDMI1>;
+ reset-names = "ctrl";
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ status = "disabled";
+ };
+
+ hdmi_phy: hdmi-phy@1ef0000 {
+ compatible = "allwinner,sun50i-a64-hdmi-phy";
+ reg = <0x01ef0000 0x10000>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_DDC>,
+ <&ccu CLK_PLL_VIDEO0>, <&ccu CLK_PLL_VIDEO1>;
+ clock-names = "bus", "mod", "pll-0", "pll-1";
+ resets = <&ccu RST_BUS_HDMI0>;
+ reset-names = "phy";
+ #phy-cells = <0>;
+ };
+
rtc: rtc@1f00000 {
compatible = "allwinner,sun6i-a31-rtc";
reg = <0x01f00000 0x54>;
--
2.14.3
HDMI PHY on Allwinner A64 has similar like H3/H5 but with
two clock parents, so add separate compatible for A64.
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- Add separate compatible for A64
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 1a5ff416dea4..4f7b9dca8ca0 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -104,6 +104,7 @@ Required properties:
- compatible: value must be one of:
* allwinner,sun8i-a83t-hdmi-phy
* allwinner,sun8i-h3-hdmi-phy
+ * allwinner,sun50i-a64-hdmi-phy
- reg: base address and size of memory-mapped region
- clocks: phandles to the clocks feeding the HDMI PHY
* bus: the HDMI PHY interface clock
--
2.14.3
From: Jernej Skrabec <[email protected]>
When TCON set up TCON TOP, it needs to know mixer index. Here we do that
by setting engine ID to number provided in mixer index quirk.
Signed-off-by: Jernej Skrabec <[email protected]>
Signed-off-by: Jagan Teki <[email protected]>
---
Changes for v2:
- New patch
drivers/gpu/drm/sun4i/sun8i_mixer.c | 4 ++--
drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 126899d6f0d3..36d90c76317a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -353,13 +353,13 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
dev_set_drvdata(dev, mixer);
mixer->engine.ops = &sun8i_engine_ops;
mixer->engine.node = dev->of_node;
- /* The ID of the mixer currently doesn't matter */
- mixer->engine.id = -1;
mixer->cfg = of_device_get_match_data(dev);
if (!mixer->cfg)
return -EINVAL;
+ mixer->engine.id = mixer->cfg->index;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev, res);
if (IS_ERR(regs))
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index f34e70c42adf..aeda6e9a7627 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -123,6 +123,7 @@ struct de2_fmt_info {
* are invalid.
* @mod_rate: module clock rate that needs to be set in order to have
* a functional block.
+ * @index: mixer index, needed to properly set TCON TOP
*/
struct sun8i_mixer_cfg {
int vi_num;
@@ -130,6 +131,7 @@ struct sun8i_mixer_cfg {
int scaler_mask;
int ccsc;
unsigned long mod_rate;
+ int index;
};
struct sun8i_mixer {
--
2.14.3
On Fri, May 18, 2018 at 03:15:10PM +0530, Jagan Teki wrote:
> Allwinner A64 has display engine pipeline like other Allwinner SOC's A83T/H3/H5.
>
> A64 behaviour similar to Allwinner A83T where
> Mixer0 => TCON0 => LVDS/RGB/MIPI-DSI
> Mixer1 => TCON1 => HDMI
> as per Display System Block DiagramAllwinner_A64_User_Manual_V1.1.pdf
>
> This is second patch-set followed with previous RFC[1] and first series[2]
> and merely concentrated on HDMI pipeline through TCON1 and rest will add eventually.
>
> This series fixed previous version comments
> - about documenting fallback compatibles
> - adding new compatible for mixer1
> - support for multiple DW HDMI PHY clock parents (thanks, to Jernej)
>
> Note:
> Pine64 boards are unable to get edid by default like other A64 boards,
> but forcing 'video=HDMI-A-1:1920x1080@60D' kernel command line can
> create edid with display on penel.
There's no point in trying to push this without the SRAM issue being
solved. It is required, and won't be merged unless this is addressed.
Maxime
--
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
On Fri, May 18, 2018 at 03:15:22PM +0530, Jagan Teki wrote:
> From: Jernej Skrabec <[email protected]>
>
> Some SoCs with DW HDMI have multiple possible clock parents, like A64
> and R40.
>
> Expand HDMI PHY clock driver to support second clock parent.
>
> Signed-off-by: Jernej Skrabec <[email protected]>
> Signed-off-by: Jagan Teki <[email protected]>
> ---
> Changes for v2:
> - new patch
>
> drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 9 ++-
> drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 33 ++++++++---
> drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 89 ++++++++++++++++++++++--------
> 3 files changed, 96 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> index 79154f0f674a..303189d6602c 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> @@ -98,7 +98,8 @@
> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN BIT(29)
> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN BIT(28)
> #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 BIT(27)
> -#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL BIT(26)
> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK BIT(26)
> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT 26
> #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN BIT(25)
> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22)
> #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20)
> @@ -146,7 +147,7 @@
> struct sun8i_hdmi_phy;
>
> struct sun8i_hdmi_phy_variant {
> - bool has_phy_clk;
> + int phy_clk_num;
> void (*phy_init)(struct sun8i_hdmi_phy *phy);
> void (*phy_disable)(struct dw_hdmi *hdmi,
> struct sun8i_hdmi_phy *phy);
> @@ -160,6 +161,7 @@ struct sun8i_hdmi_phy {
> struct clk *clk_mod;
> struct clk *clk_phy;
> struct clk *clk_pll0;
> + struct clk *clk_pll1;
> unsigned int rcal;
> struct regmap *regs;
> struct reset_control *rst_phy;
> @@ -188,6 +190,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi);
> void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
> const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
>
> -int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev);
> +int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
> + int clk_num);
>
> #endif /* _SUN8I_DW_HDMI_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> index 5a52fc489a9d..0eadf087fc46 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> @@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
> SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
>
> - regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
> + /*
> + * NOTE: We have to be careful not to overwrite PHY parent
> + * clock selection bit and clock divider.
> + */
> + regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
> + (u32)~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
> + pll_cfg1_init);
> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
> (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
> pll_cfg2_init);
> @@ -232,7 +238,7 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
> SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
>
> - if (phy->variant->has_phy_clk)
> + if (phy->variant->phy_clk_num)
> clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000);
>
> return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000);
> @@ -393,7 +399,7 @@ static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
> };
>
> static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
> - .has_phy_clk = true,
> + .phy_clk_num = 1,
> .phy_init = &sun8i_hdmi_phy_init_h3,
> .phy_disable = &sun8i_hdmi_phy_disable_h3,
> .phy_config = &sun8i_hdmi_phy_config_h3,
> @@ -464,7 +470,7 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
> goto err_put_clk_bus;
> }
>
> - if (phy->variant->has_phy_clk) {
> + if (phy->variant->phy_clk_num) {
> phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
> if (IS_ERR(phy->clk_pll0)) {
> dev_err(dev, "Could not get pll-0 clock\n");
> @@ -472,7 +478,16 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
> goto err_put_clk_mod;
> }
>
> - ret = sun8i_phy_clk_create(phy, dev);
> + if (phy->variant->phy_clk_num) {
> + phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
> + if (IS_ERR(phy->clk_pll1)) {
> + dev_err(dev, "Could not get pll-1 clock\n");
> + ret = PTR_ERR(phy->clk_pll1);
> + goto err_put_clk_mod;
> + }
> + }
> +
You have a bug here. If phy_clk_num == 1, you'll still try to lookup
pll-1.
And this is a bit sloppy, since if phy_clk_num == 3, you won't try to
lookup pll-2 either.
> + ret = sun8i_phy_clk_create(phy, dev, phy->variant->phy_clk_num);
> if (ret) {
> dev_err(dev, "Couldn't create the PHY clock\n");
> goto err_put_clk_pll0;
> @@ -515,8 +530,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
> err_put_rst_phy:
> reset_control_put(phy->rst_phy);
> err_put_clk_pll0:
> - if (phy->variant->has_phy_clk)
> - clk_put(phy->clk_pll0);
> + clk_put(phy->clk_pll0);
> + clk_put(phy->clk_pll1);
> err_put_clk_mod:
> clk_put(phy->clk_mod);
> err_put_clk_bus:
> @@ -536,8 +551,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
>
> reset_control_put(phy->rst_phy);
>
> - if (phy->variant->has_phy_clk)
> - clk_put(phy->clk_pll0);
> + clk_put(phy->clk_pll0);
> + clk_put(phy->clk_pll1);
> clk_put(phy->clk_mod);
> clk_put(phy->clk_bus);
> }
> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
> index faea449812f8..85b12fc96dbc 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
> @@ -22,29 +22,36 @@ static int sun8i_phy_clk_determine_rate(struct clk_hw *hw,
> {
> unsigned long rate = req->rate;
> unsigned long best_rate = 0;
> - struct clk_hw *parent;
> + struct clk_hw *best_parent = NULL;
> + struct clk_hw *parent = NULL;
> int best_div = 1;
> - int i;
> + int i, p;
>
> - parent = clk_hw_get_parent(hw);
> -
> - for (i = 1; i <= 16; i++) {
> - unsigned long ideal = rate * i;
> - unsigned long rounded;
> -
> - rounded = clk_hw_round_rate(parent, ideal);
> -
> - if (rounded == ideal) {
> - best_rate = rounded;
> - best_div = i;
> - break;
> - }
> + for (p = 0; p < clk_hw_get_num_parents(hw); p++) {
> + parent = clk_hw_get_parent_by_index(hw, p);
> + if (!parent)
> + continue;
>
> - if (!best_rate ||
> - abs(rate - rounded / i) <
> - abs(rate - best_rate / best_div)) {
> - best_rate = rounded;
> - best_div = i;
> + for (i = 1; i <= 16; i++) {
> + unsigned long ideal = rate * i;
> + unsigned long rounded;
> +
> + rounded = clk_hw_round_rate(parent, ideal);
> +
> + if (rounded == ideal) {
> + best_rate = rounded;
> + best_div = i;
> + best_parent = parent;
> + break;
> + }
> +
> + if (!best_rate ||
> + abs(rate - rounded / i) <
> + abs(rate - best_rate / best_div)) {
> + best_rate = rounded;
> + best_div = i;
> + best_parent = parent;
> + }
> }
> }
>
> @@ -95,22 +102,58 @@ static int sun8i_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> return 0;
> }
>
> +static u8 sun8i_phy_clk_get_parent(struct clk_hw *hw)
> +{
> + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
> + u32 reg;
> +
> + regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, ®);
> + reg = (reg & SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK) >>
> + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT;
> +
> + return reg;
> +}
> +
> +static int sun8i_phy_clk_set_parent(struct clk_hw *hw, u8 index)
> +{
> + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
> +
> + if (index > 1)
> + return -EINVAL;
> +
> + regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
> + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
> + index << SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT);
> +
> + return 0;
> +}
> +
The DT bindings changes and the clk changes should be part of separate
patches.
Maxime
--
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
On Fri, May 18, 2018 at 03:15:26PM +0530, Jagan Teki wrote:
> Allwinner A64 has two clock parents PLL_VIDEO0 and PLL_VIDEO1.
>
> Include these macros on dt-bindings so-that the same can be
> used while defining CCU clock phadles.
>
> Signed-off-by: Jagan Teki <[email protected]>
> ---
> Changes for v2:
> - new patch
>
> include/dt-bindings/clock/sun50i-a64-ccu.h | 2 ++
> 1 file changed, 2 insertions(+)
Reviewed-by: Rob Herring <[email protected]>
Hi,
Dne petek, 18. maj 2018 ob 12:01:16 CEST je Maxime Ripard napisal(a):
> On Fri, May 18, 2018 at 03:15:22PM +0530, Jagan Teki wrote:
> > From: Jernej Skrabec <[email protected]>
> >
> > Some SoCs with DW HDMI have multiple possible clock parents, like A64
> > and R40.
> >
> > Expand HDMI PHY clock driver to support second clock parent.
> >
> > Signed-off-by: Jernej Skrabec <[email protected]>
> > Signed-off-by: Jagan Teki <[email protected]>
> > ---
> > Changes for v2:
> > - new patch
> >
> > drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 9 ++-
> > drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 33 ++++++++---
> > drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 89
> > ++++++++++++++++++++++-------- 3 files changed, 96 insertions(+), 35
> > deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> > b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index 79154f0f674a..303189d6602c
> > 100644
> > --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> > +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> > @@ -98,7 +98,8 @@
> >
> > #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN BIT(29)
> > #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN BIT(28)
> > #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 BIT(27)
> >
> > -#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL BIT(26)
> > +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK BIT(26)
> > +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT 26
> >
> > #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN BIT(25)
> > #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22)
> > #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20)
> >
> > @@ -146,7 +147,7 @@
> >
> > struct sun8i_hdmi_phy;
> >
> > struct sun8i_hdmi_phy_variant {
> >
> > - bool has_phy_clk;
> > + int phy_clk_num;
> >
> > void (*phy_init)(struct sun8i_hdmi_phy *phy);
> > void (*phy_disable)(struct dw_hdmi *hdmi,
> >
> > struct sun8i_hdmi_phy *phy);
> >
> > @@ -160,6 +161,7 @@ struct sun8i_hdmi_phy {
> >
> > struct clk *clk_mod;
> > struct clk *clk_phy;
> > struct clk *clk_pll0;
> >
> > + struct clk *clk_pll1;
> >
> > unsigned int rcal;
> > struct regmap *regs;
> > struct reset_control *rst_phy;
> >
> > @@ -188,6 +190,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi
> > *hdmi);
> >
> > void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
> > const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
> >
> > -int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev);
> > +int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
> > + int clk_num);
> >
> > #endif /* _SUN8I_DW_HDMI_H_ */
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> > b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index 5a52fc489a9d..0eadf087fc46
> > 100644
> > --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> > +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> > @@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi
> > *hdmi,>
> > regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
> >
> > SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
> >
> > - regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
> > + /*
> > + * NOTE: We have to be careful not to overwrite PHY parent
> > + * clock selection bit and clock divider.
> > + */
> > + regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
> > + (u32)~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
> > + pll_cfg1_init);
> >
> > regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
> >
> > (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
> > pll_cfg2_init);
> >
> > @@ -232,7 +238,7 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi,
> > void *data,>
> > regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
> >
> > SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
> >
> > - if (phy->variant->has_phy_clk)
> > + if (phy->variant->phy_clk_num)
> >
> > clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000);
> >
> > return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000);
> >
> > @@ -393,7 +399,7 @@ static const struct sun8i_hdmi_phy_variant
> > sun8i_a83t_hdmi_phy = {>
> > };
> >
> > static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
> >
> > - .has_phy_clk = true,
> > + .phy_clk_num = 1,
> >
> > .phy_init = &sun8i_hdmi_phy_init_h3,
> > .phy_disable = &sun8i_hdmi_phy_disable_h3,
> > .phy_config = &sun8i_hdmi_phy_config_h3,
> >
> > @@ -464,7 +470,7 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
> > struct device_node *node)>
> > goto err_put_clk_bus;
> >
> > }
> >
> > - if (phy->variant->has_phy_clk) {
> > + if (phy->variant->phy_clk_num) {
> >
> > phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
> > if (IS_ERR(phy->clk_pll0)) {
> >
> > dev_err(dev, "Could not get pll-0 clock\n");
> >
> > @@ -472,7 +478,16 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
> > struct device_node *node)>
> > goto err_put_clk_mod;
> >
> > }
> >
> > - ret = sun8i_phy_clk_create(phy, dev);
> > + if (phy->variant->phy_clk_num) {
> > + phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
> > + if (IS_ERR(phy->clk_pll1)) {
> > + dev_err(dev, "Could not get pll-1 clock\n");
> > + ret = PTR_ERR(phy->clk_pll1);
> > + goto err_put_clk_mod;
> > + }
> > + }
> > +
>
> You have a bug here. If phy_clk_num == 1, you'll still try to lookup
> pll-1.
This is actually WIP patch taken from my github. This issue was fixed already
locally on disk. I thought Jagan will not use it until SRAM C patches land.
>
> And this is a bit sloppy, since if phy_clk_num == 3, you won't try to
> lookup pll-2 either.
It is highly unlikely this will be higher than 2, at least for this HDMI PHY,
since it has only 1 bit reserved for parent selection. But since I have to fix
it, I'll add ">= 2"
>
> > + ret = sun8i_phy_clk_create(phy, dev, phy->variant->phy_clk_num);
> >
> > if (ret) {
> >
> > dev_err(dev, "Couldn't create the PHY clock\n");
> > goto err_put_clk_pll0;
> >
> > @@ -515,8 +530,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
> > struct device_node *node)>
> > err_put_rst_phy:
> > reset_control_put(phy->rst_phy);
> >
> > err_put_clk_pll0:
> > - if (phy->variant->has_phy_clk)
> > - clk_put(phy->clk_pll0);
> > + clk_put(phy->clk_pll0);
> > + clk_put(phy->clk_pll1);
> >
> > err_put_clk_mod:
> > clk_put(phy->clk_mod);
> >
> > err_put_clk_bus:
> > @@ -536,8 +551,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
> >
> > reset_control_put(phy->rst_phy);
> >
> > - if (phy->variant->has_phy_clk)
> > - clk_put(phy->clk_pll0);
> > + clk_put(phy->clk_pll0);
> > + clk_put(phy->clk_pll1);
> >
> > clk_put(phy->clk_mod);
> > clk_put(phy->clk_bus);
> >
> > }
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
> > b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c index
> > faea449812f8..85b12fc96dbc 100644
> > --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
> > +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
> > @@ -22,29 +22,36 @@ static int sun8i_phy_clk_determine_rate(struct clk_hw
> > *hw,>
> > {
> >
> > unsigned long rate = req->rate;
> > unsigned long best_rate = 0;
> >
> > - struct clk_hw *parent;
> > + struct clk_hw *best_parent = NULL;
> > + struct clk_hw *parent = NULL;
> >
> > int best_div = 1;
> >
> > - int i;
> > + int i, p;
> >
> > - parent = clk_hw_get_parent(hw);
> > -
> > - for (i = 1; i <= 16; i++) {
> > - unsigned long ideal = rate * i;
> > - unsigned long rounded;
> > -
> > - rounded = clk_hw_round_rate(parent, ideal);
> > -
> > - if (rounded == ideal) {
> > - best_rate = rounded;
> > - best_div = i;
> > - break;
> > - }
> > + for (p = 0; p < clk_hw_get_num_parents(hw); p++) {
> > + parent = clk_hw_get_parent_by_index(hw, p);
> > + if (!parent)
> > + continue;
> >
> > - if (!best_rate ||
> > - abs(rate - rounded / i) <
> > - abs(rate - best_rate / best_div)) {
> > - best_rate = rounded;
> > - best_div = i;
> > + for (i = 1; i <= 16; i++) {
> > + unsigned long ideal = rate * i;
> > + unsigned long rounded;
> > +
> > + rounded = clk_hw_round_rate(parent, ideal);
> > +
> > + if (rounded == ideal) {
> > + best_rate = rounded;
> > + best_div = i;
> > + best_parent = parent;
> > + break;
> > + }
> > +
> > + if (!best_rate ||
> > + abs(rate - rounded / i) <
> > + abs(rate - best_rate / best_div)) {
> > + best_rate = rounded;
> > + best_div = i;
> > + best_parent = parent;
> > + }
> >
> > }
> >
> > }
> >
> > @@ -95,22 +102,58 @@ static int sun8i_phy_clk_set_rate(struct clk_hw *hw,
> > unsigned long rate,>
> > return 0;
> >
> > }
> >
> > +static u8 sun8i_phy_clk_get_parent(struct clk_hw *hw)
> > +{
> > + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
> > + u32 reg;
> > +
> > + regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, ®);
> > + reg = (reg & SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK) >>
> > + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT;
> > +
> > + return reg;
> > +}
> > +
> > +static int sun8i_phy_clk_set_parent(struct clk_hw *hw, u8 index)
> > +{
> > + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
> > +
> > + if (index > 1)
> > + return -EINVAL;
> > +
> > + regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
> > + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
> > + index << SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT);
> > +
> > + return 0;
> > +}
> > +
>
> The DT bindings changes and the clk changes should be part of separate
> patches.
By DT bindings changes you mean code which reads DT and not DT documentation,
right?
Ok, I'll split it.
BTW, I'll resend fixed version of this patch for my R40 HDMI series, since
there is nothing to hold it back, unlike for this.
Best regards,
Jernej
Hi, guys,
On 05/18/2018 05:46 PM, Jernej Škrabec wrote:
> Hi,
>
> Dne petek, 18. maj 2018 ob 12:01:16 CEST je Maxime Ripard napisal(a):
>> On Fri, May 18, 2018 at 03:15:22PM +0530, Jagan Teki wrote:
>>> From: Jernej Skrabec <[email protected]>
>>>
>>> Some SoCs with DW HDMI have multiple possible clock parents, like A64
>>> and R40.
>>>
>>> Expand HDMI PHY clock driver to support second clock parent.
>>>
>>> Signed-off-by: Jernej Skrabec <[email protected]>
>>> Signed-off-by: Jagan Teki <[email protected]>
>>> ---
>>> Changes for v2:
>>> - new patch
>>>
>>> drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 9 ++-
>>> drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 33 ++++++++---
>>> drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 89
>>> ++++++++++++++++++++++-------- 3 files changed, 96 insertions(+), 35
>>> deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
>>> b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index 79154f0f674a..303189d6602c
>>> 100644
>>> --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
>>> +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
>>> @@ -98,7 +98,8 @@
>>>
>>> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN BIT(29)
>>> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN BIT(28)
>>> #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 BIT(27)
>>>
>>> -#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL BIT(26)
>>> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK BIT(26)
>>> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT 26
>>>
>>> #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN BIT(25)
>>> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22)
>>> #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20)
>>>
>>> @@ -146,7 +147,7 @@
>>>
>>> struct sun8i_hdmi_phy;
>>>
>>> struct sun8i_hdmi_phy_variant {
>>>
>>> - bool has_phy_clk;
>>> + int phy_clk_num;
>>>
>>> void (*phy_init)(struct sun8i_hdmi_phy *phy);
>>> void (*phy_disable)(struct dw_hdmi *hdmi,
>>>
>>> struct sun8i_hdmi_phy *phy);
>>>
>>> @@ -160,6 +161,7 @@ struct sun8i_hdmi_phy {
>>>
>>> struct clk *clk_mod;
>>> struct clk *clk_phy;
>>> struct clk *clk_pll0;
>>>
>>> + struct clk *clk_pll1;
>>>
>>> unsigned int rcal;
>>> struct regmap *regs;
>>> struct reset_control *rst_phy;
>>>
>>> @@ -188,6 +190,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi
>>> *hdmi);
>>>
>>> void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
>>> const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
>>>
>>> -int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev);
>>> +int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
>>> + int clk_num);
>>>
>>> #endif /* _SUN8I_DW_HDMI_H_ */
>>>
>>> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
>>> b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index 5a52fc489a9d..0eadf087fc46
>>> 100644
>>> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
>>> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
>>> @@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi
>>> *hdmi,>
>>> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
>>>
>>> SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
>>>
>>> - regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
>>> + /*
>>> + * NOTE: We have to be careful not to overwrite PHY parent
>>> + * clock selection bit and clock divider.
>>> + */
>>> + regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
>>> + (u32)~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
>>> + pll_cfg1_init);
>>>
>>> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
>>>
>>> (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
>>> pll_cfg2_init);
>>>
>>> @@ -232,7 +238,7 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi,
>>> void *data,>
>>> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
>>>
>>> SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
>>>
>>> - if (phy->variant->has_phy_clk)
>>> + if (phy->variant->phy_clk_num)
>>>
>>> clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000);
>>>
>>> return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000);
>>>
>>> @@ -393,7 +399,7 @@ static const struct sun8i_hdmi_phy_variant
>>> sun8i_a83t_hdmi_phy = {>
>>> };
>>>
>>> static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
>>>
>>> - .has_phy_clk = true,
>>> + .phy_clk_num = 1,
>>>
>>> .phy_init = &sun8i_hdmi_phy_init_h3,
>>> .phy_disable = &sun8i_hdmi_phy_disable_h3,
>>> .phy_config = &sun8i_hdmi_phy_config_h3,
>>>
>>> @@ -464,7 +470,7 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
>>> struct device_node *node)>
>>> goto err_put_clk_bus;
>>>
>>> }
>>>
>>> - if (phy->variant->has_phy_clk) {
>>> + if (phy->variant->phy_clk_num) {
>>>
>>> phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
>>> if (IS_ERR(phy->clk_pll0)) {
>>>
>>> dev_err(dev, "Could not get pll-0 clock\n");
>>>
>>> @@ -472,7 +478,16 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
>>> struct device_node *node)>
>>> goto err_put_clk_mod;
>>>
>>> }
>>>
>>> - ret = sun8i_phy_clk_create(phy, dev);
>>> + if (phy->variant->phy_clk_num) {
>>> + phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
>>> + if (IS_ERR(phy->clk_pll1)) {
>>> + dev_err(dev, "Could not get pll-1 clock\n");
>>> + ret = PTR_ERR(phy->clk_pll1);
>>> + goto err_put_clk_mod;
>>> + }
>>> + }
>>> +
>> You have a bug here. If phy_clk_num == 1, you'll still try to lookup
>> pll-1.
> This is actually WIP patch taken from my github. This issue was fixed already
> locally on disk. I thought Jagan will not use it until SRAM C patches land.
>
>> And this is a bit sloppy, since if phy_clk_num == 3, you won't try to
>> lookup pll-2 either.
> It is highly unlikely this will be higher than 2, at least for this HDMI PHY,
> since it has only 1 bit reserved for parent selection. But since I have to fix
> it, I'll add ">= 2"
>
>>> + ret = sun8i_phy_clk_create(phy, dev, phy->variant->phy_clk_num);
>>>
>>> if (ret) {
>>>
>>> dev_err(dev, "Couldn't create the PHY clock\n");
>>> goto err_put_clk_pll0;
>>>
>>> @@ -515,8 +530,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
>>> struct device_node *node)>
>>> err_put_rst_phy:
>>> reset_control_put(phy->rst_phy);
>>>
>>> err_put_clk_pll0:
>>> - if (phy->variant->has_phy_clk)
>>> - clk_put(phy->clk_pll0);
>>> + clk_put(phy->clk_pll0);
>>> + clk_put(phy->clk_pll1);
>>>
>>> err_put_clk_mod:
>>> clk_put(phy->clk_mod);
>>>
>>> err_put_clk_bus:
>>> @@ -536,8 +551,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
>>>
>>> reset_control_put(phy->rst_phy);
>>>
>>> - if (phy->variant->has_phy_clk)
>>> - clk_put(phy->clk_pll0);
>>> + clk_put(phy->clk_pll0);
>>> + clk_put(phy->clk_pll1);
>>>
>>> clk_put(phy->clk_mod);
>>> clk_put(phy->clk_bus);
>>>
>>> }
>>>
>>> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
>>> b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c index
>>> faea449812f8..85b12fc96dbc 100644
>>> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
>>> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
>>> @@ -22,29 +22,36 @@ static int sun8i_phy_clk_determine_rate(struct clk_hw
>>> *hw,>
>>> {
>>>
>>> unsigned long rate = req->rate;
>>> unsigned long best_rate = 0;
>>>
>>> - struct clk_hw *parent;
>>> + struct clk_hw *best_parent = NULL;
>>> + struct clk_hw *parent = NULL;
>>>
>>> int best_div = 1;
>>>
>>> - int i;
>>> + int i, p;
>>>
>>> - parent = clk_hw_get_parent(hw);
>>> -
>>> - for (i = 1; i <= 16; i++) {
>>> - unsigned long ideal = rate * i;
>>> - unsigned long rounded;
>>> -
>>> - rounded = clk_hw_round_rate(parent, ideal);
>>> -
>>> - if (rounded == ideal) {
>>> - best_rate = rounded;
>>> - best_div = i;
>>> - break;
>>> - }
>>> + for (p = 0; p < clk_hw_get_num_parents(hw); p++) {
>>> + parent = clk_hw_get_parent_by_index(hw, p);
>>> + if (!parent)
>>> + continue;
>>>
>>> - if (!best_rate ||
>>> - abs(rate - rounded / i) <
>>> - abs(rate - best_rate / best_div)) {
>>> - best_rate = rounded;
>>> - best_div = i;
>>> + for (i = 1; i <= 16; i++) {
>>> + unsigned long ideal = rate * i;
>>> + unsigned long rounded;
>>> +
>>> + rounded = clk_hw_round_rate(parent, ideal);
>>> +
>>> + if (rounded == ideal) {
>>> + best_rate = rounded;
>>> + best_div = i;
>>> + best_parent = parent;
>>> + break;
>>> + }
>>> +
>>> + if (!best_rate ||
>>> + abs(rate - rounded / i) <
>>> + abs(rate - best_rate / best_div)) {
>>> + best_rate = rounded;
>>> + best_div = i;
>>> + best_parent = parent;
>>> + }
>>>
>>> }
>>>
>>> }
>>>
>>> @@ -95,22 +102,58 @@ static int sun8i_phy_clk_set_rate(struct clk_hw *hw,
>>> unsigned long rate,>
>>> return 0;
>>>
>>> }
>>>
>>> +static u8 sun8i_phy_clk_get_parent(struct clk_hw *hw)
>>> +{
>>> + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
>>> + u32 reg;
>>> +
>>> + regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, ®);
>>> + reg = (reg & SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK) >>
>>> + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT;
>>> +
>>> + return reg;
>>> +}
>>> +
>>> +static int sun8i_phy_clk_set_parent(struct clk_hw *hw, u8 index)
>>> +{
>>> + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
>>> +
>>> + if (index > 1)
>>> + return -EINVAL;
>>> +
>>> + regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
>>> + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
>>> + index << SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT);
>>> +
>>> + return 0;
>>> +}
>>> +
>> The DT bindings changes and the clk changes should be part of separate
>> patches.
> By DT bindings changes you mean code which reads DT and not DT documentation,
> right?
>
> Ok, I'll split it.
>
> BTW, I'll resend fixed version of this patch for my R40 HDMI series, since
> there is nothing to hold it back, unlike for this.
>
> Best regards,
> Jernej
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
you have been talking about SRAM patches, required for A64 DE2, for
about a half a year.
May I ask you to explain in a couple of words why they are so important ?
I am really curious because I have DE2 already working on my A64 without
those magic patches..
Thanks,
Sergey
Hi,
Dne petek, 18. maj 2018 ob 17:09:40 CEST je Sergey Suloev napisal(a):
> Hi, guys,
>
> On 05/18/2018 05:46 PM, Jernej Škrabec wrote:
> > Hi,
> >
> > Dne petek, 18. maj 2018 ob 12:01:16 CEST je Maxime Ripard napisal(a):
> >> On Fri, May 18, 2018 at 03:15:22PM +0530, Jagan Teki wrote:
> >>> From: Jernej Skrabec <[email protected]>
> >>>
> >>> Some SoCs with DW HDMI have multiple possible clock parents, like A64
> >>> and R40.
> >>>
> >>> Expand HDMI PHY clock driver to support second clock parent.
> >>>
> >>> Signed-off-by: Jernej Skrabec <[email protected]>
> >>> Signed-off-by: Jagan Teki <[email protected]>
> >>> ---
> >>> Changes for v2:
> >>> - new patch
> >>>
> >>> drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 9 ++-
> >>> drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 33 ++++++++---
> >>> drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 89
> >>> ++++++++++++++++++++++-------- 3 files changed, 96 insertions(+), 35
> >>> deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> >>> b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index 79154f0f674a..303189d6602c
> >>> 100644
> >>> --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> >>> +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> >>> @@ -98,7 +98,8 @@
> >>>
> >>> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN BIT(29)
> >>> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN BIT(28)
> >>> #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 BIT(27)
> >>>
> >>> -#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL BIT(26)
> >>> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK BIT(26)
> >>> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT 26
> >>>
> >>> #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN BIT(25)
> >>> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22)
> >>> #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20)
> >>>
> >>> @@ -146,7 +147,7 @@
> >>>
> >>> struct sun8i_hdmi_phy;
> >>>
> >>> struct sun8i_hdmi_phy_variant {
> >>>
> >>> - bool has_phy_clk;
> >>> + int phy_clk_num;
> >>>
> >>> void (*phy_init)(struct sun8i_hdmi_phy *phy);
> >>> void (*phy_disable)(struct dw_hdmi *hdmi,
> >>>
> >>> struct sun8i_hdmi_phy *phy);
> >>>
> >>> @@ -160,6 +161,7 @@ struct sun8i_hdmi_phy {
> >>>
> >>> struct clk *clk_mod;
> >>> struct clk *clk_phy;
> >>> struct clk *clk_pll0;
> >>>
> >>> + struct clk *clk_pll1;
> >>>
> >>> unsigned int rcal;
> >>> struct regmap *regs;
> >>> struct reset_control *rst_phy;
> >>>
> >>> @@ -188,6 +190,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi
> >>> *hdmi);
> >>>
> >>> void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
> >>> const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
> >>>
> >>> -int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device
> >>> *dev);
> >>> +int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device
> >>> *dev,
> >>> + int clk_num);
> >>>
> >>> #endif /* _SUN8I_DW_HDMI_H_ */
> >>>
> >>> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> >>> b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index
> >>> 5a52fc489a9d..0eadf087fc46
> >>> 100644
> >>> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> >>> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> >>> @@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi
> >>> *hdmi,>
> >>>
> >>> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
> >>>
> >>> SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
> >>>
> >>> - regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
> >>> + /*
> >>> + * NOTE: We have to be careful not to overwrite PHY parent
> >>> + * clock selection bit and clock divider.
> >>> + */
> >>> + regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
> >>> + (u32)~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
> >>> + pll_cfg1_init);
> >>>
> >>> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
> >>>
> >>> (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
> >>> pll_cfg2_init);
> >>>
> >>> @@ -232,7 +238,7 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi
> >>> *hdmi,
> >>> void *data,>
> >>>
> >>> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
> >>>
> >>> SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
> >>>
> >>> - if (phy->variant->has_phy_clk)
> >>> + if (phy->variant->phy_clk_num)
> >>>
> >>> clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000);
> >>>
> >>> return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000);
> >>>
> >>> @@ -393,7 +399,7 @@ static const struct sun8i_hdmi_phy_variant
> >>> sun8i_a83t_hdmi_phy = {>
> >>>
> >>> };
> >>>
> >>> static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
> >>>
> >>> - .has_phy_clk = true,
> >>> + .phy_clk_num = 1,
> >>>
> >>> .phy_init = &sun8i_hdmi_phy_init_h3,
> >>> .phy_disable = &sun8i_hdmi_phy_disable_h3,
> >>> .phy_config = &sun8i_hdmi_phy_config_h3,
> >>>
> >>> @@ -464,7 +470,7 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
> >>> struct device_node *node)>
> >>>
> >>> goto err_put_clk_bus;
> >>>
> >>> }
> >>>
> >>> - if (phy->variant->has_phy_clk) {
> >>> + if (phy->variant->phy_clk_num) {
> >>>
> >>> phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
> >>> if (IS_ERR(phy->clk_pll0)) {
> >>>
> >>> dev_err(dev, "Could not get pll-0 clock\n");
> >>>
> >>> @@ -472,7 +478,16 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi
> >>> *hdmi,
> >>> struct device_node *node)>
> >>>
> >>> goto err_put_clk_mod;
> >>>
> >>> }
> >>>
> >>> - ret = sun8i_phy_clk_create(phy, dev);
> >>> + if (phy->variant->phy_clk_num) {
> >>> + phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
> >>> + if (IS_ERR(phy->clk_pll1)) {
> >>> + dev_err(dev, "Could not get pll-1 clock\n");
> >>> + ret = PTR_ERR(phy->clk_pll1);
> >>> + goto err_put_clk_mod;
> >>> + }
> >>> + }
> >>> +
> >>
> >> You have a bug here. If phy_clk_num == 1, you'll still try to lookup
> >> pll-1.
> >
> > This is actually WIP patch taken from my github. This issue was fixed
> > already locally on disk. I thought Jagan will not use it until SRAM C
> > patches land.>
> >> And this is a bit sloppy, since if phy_clk_num == 3, you won't try to
> >> lookup pll-2 either.
> >
> > It is highly unlikely this will be higher than 2, at least for this HDMI
> > PHY, since it has only 1 bit reserved for parent selection. But since I
> > have to fix it, I'll add ">= 2"
> >
> >>> + ret = sun8i_phy_clk_create(phy, dev, phy->variant->phy_clk_num);
> >>>
> >>> if (ret) {
> >>>
> >>> dev_err(dev, "Couldn't create the PHY clock\n");
> >>> goto err_put_clk_pll0;
> >>>
> >>> @@ -515,8 +530,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
> >>> struct device_node *node)>
> >>>
> >>> err_put_rst_phy:
> >>> reset_control_put(phy->rst_phy);
> >>>
> >>> err_put_clk_pll0:
> >>> - if (phy->variant->has_phy_clk)
> >>> - clk_put(phy->clk_pll0);
> >>> + clk_put(phy->clk_pll0);
> >>> + clk_put(phy->clk_pll1);
> >>>
> >>> err_put_clk_mod:
> >>> clk_put(phy->clk_mod);
> >>>
> >>> err_put_clk_bus:
> >>> @@ -536,8 +551,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi
> >>> *hdmi)
> >>>
> >>> reset_control_put(phy->rst_phy);
> >>>
> >>> - if (phy->variant->has_phy_clk)
> >>> - clk_put(phy->clk_pll0);
> >>> + clk_put(phy->clk_pll0);
> >>> + clk_put(phy->clk_pll1);
> >>>
> >>> clk_put(phy->clk_mod);
> >>> clk_put(phy->clk_bus);
> >>>
> >>> }
> >>>
> >>> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
> >>> b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c index
> >>> faea449812f8..85b12fc96dbc 100644
> >>> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
> >>> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
> >>> @@ -22,29 +22,36 @@ static int sun8i_phy_clk_determine_rate(struct
> >>> clk_hw
> >>> *hw,>
> >>>
> >>> {
> >>>
> >>> unsigned long rate = req->rate;
> >>> unsigned long best_rate = 0;
> >>>
> >>> - struct clk_hw *parent;
> >>> + struct clk_hw *best_parent = NULL;
> >>> + struct clk_hw *parent = NULL;
> >>>
> >>> int best_div = 1;
> >>>
> >>> - int i;
> >>> + int i, p;
> >>>
> >>> - parent = clk_hw_get_parent(hw);
> >>> -
> >>> - for (i = 1; i <= 16; i++) {
> >>> - unsigned long ideal = rate * i;
> >>> - unsigned long rounded;
> >>> -
> >>> - rounded = clk_hw_round_rate(parent, ideal);
> >>> -
> >>> - if (rounded == ideal) {
> >>> - best_rate = rounded;
> >>> - best_div = i;
> >>> - break;
> >>> - }
> >>> + for (p = 0; p < clk_hw_get_num_parents(hw); p++) {
> >>> + parent = clk_hw_get_parent_by_index(hw, p);
> >>> + if (!parent)
> >>> + continue;
> >>>
> >>> - if (!best_rate ||
> >>> - abs(rate - rounded / i) <
> >>> - abs(rate - best_rate / best_div)) {
> >>> - best_rate = rounded;
> >>> - best_div = i;
> >>> + for (i = 1; i <= 16; i++) {
> >>> + unsigned long ideal = rate * i;
> >>> + unsigned long rounded;
> >>> +
> >>> + rounded = clk_hw_round_rate(parent, ideal);
> >>> +
> >>> + if (rounded == ideal) {
> >>> + best_rate = rounded;
> >>> + best_div = i;
> >>> + best_parent = parent;
> >>> + break;
> >>> + }
> >>> +
> >>> + if (!best_rate ||
> >>> + abs(rate - rounded / i) <
> >>> + abs(rate - best_rate / best_div)) {
> >>> + best_rate = rounded;
> >>> + best_div = i;
> >>> + best_parent = parent;
> >>> + }
> >>>
> >>> }
> >>>
> >>> }
> >>>
> >>> @@ -95,22 +102,58 @@ static int sun8i_phy_clk_set_rate(struct clk_hw
> >>> *hw,
> >>> unsigned long rate,>
> >>>
> >>> return 0;
> >>>
> >>> }
> >>>
> >>> +static u8 sun8i_phy_clk_get_parent(struct clk_hw *hw)
> >>> +{
> >>> + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
> >>> + u32 reg;
> >>> +
> >>> + regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, ®);
> >>> + reg = (reg & SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK) >>
> >>> + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT;
> >>> +
> >>> + return reg;
> >>> +}
> >>> +
> >>> +static int sun8i_phy_clk_set_parent(struct clk_hw *hw, u8 index)
> >>> +{
> >>> + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
> >>> +
> >>> + if (index > 1)
> >>> + return -EINVAL;
> >>> +
> >>> + regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
> >>> + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
> >>> + index << SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT);
> >>> +
> >>> + return 0;
> >>> +}
> >>> +
> >>
> >> The DT bindings changes and the clk changes should be part of separate
> >> patches.
> >
> > By DT bindings changes you mean code which reads DT and not DT
> > documentation, right?
> >
> > Ok, I'll split it.
> >
> > BTW, I'll resend fixed version of this patch for my R40 HDMI series, since
> > there is nothing to hold it back, unlike for this.
> >
> > Best regards,
> > Jernej
> >
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> you have been talking about SRAM patches, required for A64 DE2, for
> about a half a year.
> May I ask you to explain in a couple of words why they are so important ?
> I am really curious because I have DE2 already working on my A64 without
> those magic patches..
>
You probably have HDMI enabled in U-Boot, right? If you disable that driver in
U-Boot, Linux driver shouldn't work anymore. There is consensus that Linux A64
DE2 driver shouldn't rely on U-Boot setting bits. Those SRAM C patches will
probably also affect how DT DE2 entries are written, especially if it will be
implemented as a bus, as once proposed by Icenowy.
Best regards,
Jernej
Hi, Jernej,
On 05/18/2018 06:15 PM, Jernej Škrabec wrote:
> Hi,
>
> Dne petek, 18. maj 2018 ob 17:09:40 CEST je Sergey Suloev napisal(a):
>> Hi, guys,
>>
>> On 05/18/2018 05:46 PM, Jernej Škrabec wrote:
>>> Hi,
>>>
>>> Dne petek, 18. maj 2018 ob 12:01:16 CEST je Maxime Ripard napisal(a):
>>>> On Fri, May 18, 2018 at 03:15:22PM +0530, Jagan Teki wrote:
>>>>> From: Jernej Skrabec <[email protected]>
>>>>>
>>>>> Some SoCs with DW HDMI have multiple possible clock parents, like A64
>>>>> and R40.
>>>>>
>>>>> Expand HDMI PHY clock driver to support second clock parent.
>>>>>
>>>>> Signed-off-by: Jernej Skrabec <[email protected]>
>>>>> Signed-off-by: Jagan Teki <[email protected]>
>>>>> ---
>>>>> Changes for v2:
>>>>> - new patch
>>>>>
>>>>> drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 9 ++-
>>>>> drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 33 ++++++++---
>>>>> drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 89
>>>>> ++++++++++++++++++++++-------- 3 files changed, 96 insertions(+), 35
>>>>> deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
>>>>> b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index 79154f0f674a..303189d6602c
>>>>> 100644
>>>>> --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
>>>>> +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
>>>>> @@ -98,7 +98,8 @@
>>>>>
>>>>> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN BIT(29)
>>>>> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN BIT(28)
>>>>> #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 BIT(27)
>>>>>
>>>>> -#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL BIT(26)
>>>>> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK BIT(26)
>>>>> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT 26
>>>>>
>>>>> #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN BIT(25)
>>>>> #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22)
>>>>> #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20)
>>>>>
>>>>> @@ -146,7 +147,7 @@
>>>>>
>>>>> struct sun8i_hdmi_phy;
>>>>>
>>>>> struct sun8i_hdmi_phy_variant {
>>>>>
>>>>> - bool has_phy_clk;
>>>>> + int phy_clk_num;
>>>>>
>>>>> void (*phy_init)(struct sun8i_hdmi_phy *phy);
>>>>> void (*phy_disable)(struct dw_hdmi *hdmi,
>>>>>
>>>>> struct sun8i_hdmi_phy *phy);
>>>>>
>>>>> @@ -160,6 +161,7 @@ struct sun8i_hdmi_phy {
>>>>>
>>>>> struct clk *clk_mod;
>>>>> struct clk *clk_phy;
>>>>> struct clk *clk_pll0;
>>>>>
>>>>> + struct clk *clk_pll1;
>>>>>
>>>>> unsigned int rcal;
>>>>> struct regmap *regs;
>>>>> struct reset_control *rst_phy;
>>>>>
>>>>> @@ -188,6 +190,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi
>>>>> *hdmi);
>>>>>
>>>>> void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
>>>>> const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
>>>>>
>>>>> -int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device
>>>>> *dev);
>>>>> +int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device
>>>>> *dev,
>>>>> + int clk_num);
>>>>>
>>>>> #endif /* _SUN8I_DW_HDMI_H_ */
>>>>>
>>>>> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
>>>>> b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index
>>>>> 5a52fc489a9d..0eadf087fc46
>>>>> 100644
>>>>> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
>>>>> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
>>>>> @@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi
>>>>> *hdmi,>
>>>>>
>>>>> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
>>>>>
>>>>> SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
>>>>>
>>>>> - regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
>>>>> + /*
>>>>> + * NOTE: We have to be careful not to overwrite PHY parent
>>>>> + * clock selection bit and clock divider.
>>>>> + */
>>>>> + regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
>>>>> + (u32)~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
>>>>> + pll_cfg1_init);
>>>>>
>>>>> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
>>>>>
>>>>> (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
>>>>> pll_cfg2_init);
>>>>>
>>>>> @@ -232,7 +238,7 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi
>>>>> *hdmi,
>>>>> void *data,>
>>>>>
>>>>> regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
>>>>>
>>>>> SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
>>>>>
>>>>> - if (phy->variant->has_phy_clk)
>>>>> + if (phy->variant->phy_clk_num)
>>>>>
>>>>> clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000);
>>>>>
>>>>> return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000);
>>>>>
>>>>> @@ -393,7 +399,7 @@ static const struct sun8i_hdmi_phy_variant
>>>>> sun8i_a83t_hdmi_phy = {>
>>>>>
>>>>> };
>>>>>
>>>>> static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
>>>>>
>>>>> - .has_phy_clk = true,
>>>>> + .phy_clk_num = 1,
>>>>>
>>>>> .phy_init = &sun8i_hdmi_phy_init_h3,
>>>>> .phy_disable = &sun8i_hdmi_phy_disable_h3,
>>>>> .phy_config = &sun8i_hdmi_phy_config_h3,
>>>>>
>>>>> @@ -464,7 +470,7 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
>>>>> struct device_node *node)>
>>>>>
>>>>> goto err_put_clk_bus;
>>>>>
>>>>> }
>>>>>
>>>>> - if (phy->variant->has_phy_clk) {
>>>>> + if (phy->variant->phy_clk_num) {
>>>>>
>>>>> phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
>>>>> if (IS_ERR(phy->clk_pll0)) {
>>>>>
>>>>> dev_err(dev, "Could not get pll-0 clock\n");
>>>>>
>>>>> @@ -472,7 +478,16 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi
>>>>> *hdmi,
>>>>> struct device_node *node)>
>>>>>
>>>>> goto err_put_clk_mod;
>>>>>
>>>>> }
>>>>>
>>>>> - ret = sun8i_phy_clk_create(phy, dev);
>>>>> + if (phy->variant->phy_clk_num) {
>>>>> + phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
>>>>> + if (IS_ERR(phy->clk_pll1)) {
>>>>> + dev_err(dev, "Could not get pll-1 clock\n");
>>>>> + ret = PTR_ERR(phy->clk_pll1);
>>>>> + goto err_put_clk_mod;
>>>>> + }
>>>>> + }
>>>>> +
>>>> You have a bug here. If phy_clk_num == 1, you'll still try to lookup
>>>> pll-1.
>>> This is actually WIP patch taken from my github. This issue was fixed
>>> already locally on disk. I thought Jagan will not use it until SRAM C
>>> patches land.>
>>>> And this is a bit sloppy, since if phy_clk_num == 3, you won't try to
>>>> lookup pll-2 either.
>>> It is highly unlikely this will be higher than 2, at least for this HDMI
>>> PHY, since it has only 1 bit reserved for parent selection. But since I
>>> have to fix it, I'll add ">= 2"
>>>
>>>>> + ret = sun8i_phy_clk_create(phy, dev, phy->variant->phy_clk_num);
>>>>>
>>>>> if (ret) {
>>>>>
>>>>> dev_err(dev, "Couldn't create the PHY clock\n");
>>>>> goto err_put_clk_pll0;
>>>>>
>>>>> @@ -515,8 +530,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi,
>>>>> struct device_node *node)>
>>>>>
>>>>> err_put_rst_phy:
>>>>> reset_control_put(phy->rst_phy);
>>>>>
>>>>> err_put_clk_pll0:
>>>>> - if (phy->variant->has_phy_clk)
>>>>> - clk_put(phy->clk_pll0);
>>>>> + clk_put(phy->clk_pll0);
>>>>> + clk_put(phy->clk_pll1);
>>>>>
>>>>> err_put_clk_mod:
>>>>> clk_put(phy->clk_mod);
>>>>>
>>>>> err_put_clk_bus:
>>>>> @@ -536,8 +551,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi
>>>>> *hdmi)
>>>>>
>>>>> reset_control_put(phy->rst_phy);
>>>>>
>>>>> - if (phy->variant->has_phy_clk)
>>>>> - clk_put(phy->clk_pll0);
>>>>> + clk_put(phy->clk_pll0);
>>>>> + clk_put(phy->clk_pll1);
>>>>>
>>>>> clk_put(phy->clk_mod);
>>>>> clk_put(phy->clk_bus);
>>>>>
>>>>> }
>>>>>
>>>>> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
>>>>> b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c index
>>>>> faea449812f8..85b12fc96dbc 100644
>>>>> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
>>>>> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
>>>>> @@ -22,29 +22,36 @@ static int sun8i_phy_clk_determine_rate(struct
>>>>> clk_hw
>>>>> *hw,>
>>>>>
>>>>> {
>>>>>
>>>>> unsigned long rate = req->rate;
>>>>> unsigned long best_rate = 0;
>>>>>
>>>>> - struct clk_hw *parent;
>>>>> + struct clk_hw *best_parent = NULL;
>>>>> + struct clk_hw *parent = NULL;
>>>>>
>>>>> int best_div = 1;
>>>>>
>>>>> - int i;
>>>>> + int i, p;
>>>>>
>>>>> - parent = clk_hw_get_parent(hw);
>>>>> -
>>>>> - for (i = 1; i <= 16; i++) {
>>>>> - unsigned long ideal = rate * i;
>>>>> - unsigned long rounded;
>>>>> -
>>>>> - rounded = clk_hw_round_rate(parent, ideal);
>>>>> -
>>>>> - if (rounded == ideal) {
>>>>> - best_rate = rounded;
>>>>> - best_div = i;
>>>>> - break;
>>>>> - }
>>>>> + for (p = 0; p < clk_hw_get_num_parents(hw); p++) {
>>>>> + parent = clk_hw_get_parent_by_index(hw, p);
>>>>> + if (!parent)
>>>>> + continue;
>>>>>
>>>>> - if (!best_rate ||
>>>>> - abs(rate - rounded / i) <
>>>>> - abs(rate - best_rate / best_div)) {
>>>>> - best_rate = rounded;
>>>>> - best_div = i;
>>>>> + for (i = 1; i <= 16; i++) {
>>>>> + unsigned long ideal = rate * i;
>>>>> + unsigned long rounded;
>>>>> +
>>>>> + rounded = clk_hw_round_rate(parent, ideal);
>>>>> +
>>>>> + if (rounded == ideal) {
>>>>> + best_rate = rounded;
>>>>> + best_div = i;
>>>>> + best_parent = parent;
>>>>> + break;
>>>>> + }
>>>>> +
>>>>> + if (!best_rate ||
>>>>> + abs(rate - rounded / i) <
>>>>> + abs(rate - best_rate / best_div)) {
>>>>> + best_rate = rounded;
>>>>> + best_div = i;
>>>>> + best_parent = parent;
>>>>> + }
>>>>>
>>>>> }
>>>>>
>>>>> }
>>>>>
>>>>> @@ -95,22 +102,58 @@ static int sun8i_phy_clk_set_rate(struct clk_hw
>>>>> *hw,
>>>>> unsigned long rate,>
>>>>>
>>>>> return 0;
>>>>>
>>>>> }
>>>>>
>>>>> +static u8 sun8i_phy_clk_get_parent(struct clk_hw *hw)
>>>>> +{
>>>>> + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
>>>>> + u32 reg;
>>>>> +
>>>>> + regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, ®);
>>>>> + reg = (reg & SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK) >>
>>>>> + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT;
>>>>> +
>>>>> + return reg;
>>>>> +}
>>>>> +
>>>>> +static int sun8i_phy_clk_set_parent(struct clk_hw *hw, u8 index)
>>>>> +{
>>>>> + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
>>>>> +
>>>>> + if (index > 1)
>>>>> + return -EINVAL;
>>>>> +
>>>>> + regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
>>>>> + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
>>>>> + index << SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT);
>>>>> +
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>> The DT bindings changes and the clk changes should be part of separate
>>>> patches.
>>> By DT bindings changes you mean code which reads DT and not DT
>>> documentation, right?
>>>
>>> Ok, I'll split it.
>>>
>>> BTW, I'll resend fixed version of this patch for my R40 HDMI series, since
>>> there is nothing to hold it back, unlike for this.
>>>
>>> Best regards,
>>> Jernej
>>>
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> [email protected]
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>> you have been talking about SRAM patches, required for A64 DE2, for
>> about a half a year.
>> May I ask you to explain in a couple of words why they are so important ?
>> I am really curious because I have DE2 already working on my A64 without
>> those magic patches..
>>
> You probably have HDMI enabled in U-Boot, right? If you disable that driver in
> U-Boot, Linux driver shouldn't work anymore. There is consensus that Linux A64
> DE2 driver shouldn't rely on U-Boot setting bits. Those SRAM C patches will
> probably also affect how DT DE2 entries are written, especially if it will be
> implemented as a bus, as once proposed by Icenowy.
>
> Best regards,
> Jernej
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
thanks, got it. yes , I think U-Boot is handing this for me. And I am
not using the "bus way".
On Fri, May 18, 2018 at 04:46:41PM +0200, Jernej Škrabec wrote:
> > And this is a bit sloppy, since if phy_clk_num == 3, you won't try to
> > lookup pll-2 either.
>
> It is highly unlikely this will be higher than 2, at least for this HDMI PHY,
> since it has only 1 bit reserved for parent selection. But since I have to fix
> it, I'll add ">= 2"
If we're only going to have two parents at most, ever, why don't we
had just a single other boolean. This would be less intrusive, and we
wouldn't have to check for those corner cases.
> BTW, I'll resend fixed version of this patch for my R40 HDMI series, since
> there is nothing to hold it back, unlike for this.
Awesome, thanks!
Maxime
--
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
Hi,
Dne petek, 18. maj 2018 ob 17:26:51 CEST je Maxime Ripard napisal(a):
> On Fri, May 18, 2018 at 04:46:41PM +0200, Jernej Škrabec wrote:
> > > And this is a bit sloppy, since if phy_clk_num == 3, you won't try to
> > > lookup pll-2 either.
> >
> > It is highly unlikely this will be higher than 2, at least for this HDMI
> > PHY, since it has only 1 bit reserved for parent selection. But since I
> > have to fix it, I'll add ">= 2"
>
> If we're only going to have two parents at most, ever, why don't we
> had just a single other boolean. This would be less intrusive, and we
> wouldn't have to check for those corner cases.
That works for me too. And since it's only the code, it can always be reworked
if there is the need.
Best regards,
Jernej
>
> > BTW, I'll resend fixed version of this patch for my R40 HDMI series, since
> > there is nothing to hold it back, unlike for this.
>
> Awesome, thanks!
> Maxime
>
> --
> Maxime Ripard, Bootlin (formerly Free Electrons)
> Embedded Linux and Kernel engineering
> https://bootlin.com
Hi,
Dne petek, 18. maj 2018 ob 17:26:51 CEST je Maxime Ripard napisal(a):
> On Fri, May 18, 2018 at 04:46:41PM +0200, Jernej Škrabec wrote:
> > > And this is a bit sloppy, since if phy_clk_num == 3, you won't try to
> > > lookup pll-2 either.
> >
> > It is highly unlikely this will be higher than 2, at least for this HDMI
> > PHY, since it has only 1 bit reserved for parent selection. But since I
> > have to fix it, I'll add ">= 2"
>
> If we're only going to have two parents at most, ever, why don't we
> had just a single other boolean. This would be less intrusive, and we
> wouldn't have to check for those corner cases.
It seems that usage of "bool" data type in structures is not wanted anymore
according to checkpatch and this: https://lkml.org/lkml/2017/11/21/384
I guess I'll use "unsigned int" as recommended by Linus and named it
"has_second_parent" to be unambigous that it's boolean in reality.
Best regards,
Jernej
>
> > BTW, I'll resend fixed version of this patch for my R40 HDMI series, since
> > there is nothing to hold it back, unlike for this.
>
> Awesome, thanks!
> Maxime
>
> --
> Maxime Ripard, Bootlin (formerly Free Electrons)
> Embedded Linux and Kernel engineering
> https://bootlin.com
On Fri, May 18, 2018 at 03:15:17PM +0530, Jagan Teki wrote:
> Allwinner A64 has DE2 pipeline with tcon0 and tcon1 block
> which is similar Allwinner A83T.
>
> This patch adds dt-binding documentation for A64 DE2 tcon1 blocks.
>
> Mixer1 has different configuration for A64 so use separate compatible
> but tcon1 has similar behaviour with A83T so add fallback compatible.
>
> Signed-off-by: Jagan Teki <[email protected]>
> ---
> Changes for v2:
> - Add fallback compatible for tcon1
> - Add separate compatible for mixer1
>
> Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
> 1 file changed, 3 insertions(+)
Reviewed-by: Rob Herring <[email protected]>
On Fri, May 18, 2018 at 03:15:24PM +0530, Jagan Teki wrote:
> HDMI on Allwinner A64 has similar like H3/H5/A83T.
>
> Add compatible a64 and update A83T compatible as fallback.
>
> Signed-off-by: Jagan Teki <[email protected]>
> ---
> Changes for v2:
> - Add fallback compatible
>
> Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 1 +
> 1 file changed, 1 insertion(+)
Reviewed-by: Rob Herring <[email protected]>
On Fri, May 18, 2018 at 3:29 PM, Maxime Ripard
<[email protected]> wrote:
> On Fri, May 18, 2018 at 03:15:10PM +0530, Jagan Teki wrote:
>> Allwinner A64 has display engine pipeline like other Allwinner SOC's A83T/H3/H5.
>>
>> A64 behaviour similar to Allwinner A83T where
>> Mixer0 => TCON0 => LVDS/RGB/MIPI-DSI
>> Mixer1 => TCON1 => HDMI
>> as per Display System Block DiagramAllwinner_A64_User_Manual_V1.1.pdf
>>
>> This is second patch-set followed with previous RFC[1] and first series[2]
>> and merely concentrated on HDMI pipeline through TCON1 and rest will add eventually.
>>
>> This series fixed previous version comments
>> - about documenting fallback compatibles
>> - adding new compatible for mixer1
>> - support for multiple DW HDMI PHY clock parents (thanks, to Jernej)
>>
>> Note:
>> Pine64 boards are unable to get edid by default like other A64 boards,
>> but forcing 'video=HDMI-A-1:1920x1080@60D' kernel command line can
>> create edid with display on penel.
>
> There's no point in trying to push this without the SRAM issue being
> solved. It is required, and won't be merged unless this is addressed.
is SRAM issue resolved? if so may be I will try to test it on top.
Jagan.
--
Jagan Teki
Senior Linux Kernel Engineer | Amarula Solutions
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.
On Tue, Jun 05, 2018 at 06:23:57PM +0530, Jagan Teki wrote:
> On Fri, May 18, 2018 at 3:29 PM, Maxime Ripard
> <[email protected]> wrote:
> > On Fri, May 18, 2018 at 03:15:10PM +0530, Jagan Teki wrote:
> >> Allwinner A64 has display engine pipeline like other Allwinner SOC's A83T/H3/H5.
> >>
> >> A64 behaviour similar to Allwinner A83T where
> >> Mixer0 => TCON0 => LVDS/RGB/MIPI-DSI
> >> Mixer1 => TCON1 => HDMI
> >> as per Display System Block DiagramAllwinner_A64_User_Manual_V1.1.pdf
> >>
> >> This is second patch-set followed with previous RFC[1] and first series[2]
> >> and merely concentrated on HDMI pipeline through TCON1 and rest will add eventually.
> >>
> >> This series fixed previous version comments
> >> - about documenting fallback compatibles
> >> - adding new compatible for mixer1
> >> - support for multiple DW HDMI PHY clock parents (thanks, to Jernej)
> >>
> >> Note:
> >> Pine64 boards are unable to get edid by default like other A64 boards,
> >> but forcing 'video=HDMI-A-1:1920x1080@60D' kernel command line can
> >> create edid with display on penel.
> >
> > There's no point in trying to push this without the SRAM issue being
> > solved. It is required, and won't be merged unless this is addressed.
>
> is SRAM issue resolved? if so may be I will try to test it on top.
I'd expect the one working on this to push a solution to solve this.
Maxime
--
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
于 2018年6月5日 GMT+08:00 下午9:25:39, Maxime Ripard <[email protected]> 写到:
>On Tue, Jun 05, 2018 at 06:23:57PM +0530, Jagan Teki wrote:
>> On Fri, May 18, 2018 at 3:29 PM, Maxime Ripard
>> <[email protected]> wrote:
>> > On Fri, May 18, 2018 at 03:15:10PM +0530, Jagan Teki wrote:
>> >> Allwinner A64 has display engine pipeline like other Allwinner
>SOC's A83T/H3/H5.
>> >>
>> >> A64 behaviour similar to Allwinner A83T where
>> >> Mixer0 => TCON0 => LVDS/RGB/MIPI-DSI
>> >> Mixer1 => TCON1 => HDMI
>> >> as per Display System Block
>DiagramAllwinner_A64_User_Manual_V1.1.pdf
>> >>
>> >> This is second patch-set followed with previous RFC[1] and first
>series[2]
>> >> and merely concentrated on HDMI pipeline through TCON1 and rest
>will add eventually.
>> >>
>> >> This series fixed previous version comments
>> >> - about documenting fallback compatibles
>> >> - adding new compatible for mixer1
>> >> - support for multiple DW HDMI PHY clock parents (thanks, to
>Jernej)
>> >>
>> >> Note:
>> >> Pine64 boards are unable to get edid by default like other A64
>boards,
>> >> but forcing 'video=HDMI-A-1:1920x1080@60D' kernel command line can
>> >> create edid with display on penel.
>> >
>> > There's no point in trying to push this without the SRAM issue
>being
>> > solved. It is required, and won't be merged unless this is
>addressed.
>>
>> is SRAM issue resolved? if so may be I will try to test it on top.
>
>I'd expect the one working on this to push a solution to solve this.
I'll do it soon. Currently I'm a little busy.
>
>Maxime