* [PATCH 1/5] ARM: dts: cygnus: Fix I2C controller interrupt type
From: Ray Jui @ 2018-06-12 20:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528834891-17807-1-git-send-email-ray.jui@broadcom.com>
Fix I2C controller interrupt to use IRQ_TYPE_LEVEL_HIGH for Broadcom
Cygnus SoC
Fixes: b51c05a331ff ("ARM: dts: add I2C device nodes for Broadcom Cygnus")
Fixes: 0f0b21a83ad2 ("ARM: dts: Move all Cygnus peripherals into axi bus")
Fixes: 9c5101f7a253 ("ARM: dts: Reorder Cygnus peripherals")
Signed-off-by: Ray Jui <ray.jui@broadcom.com>
---
arch/arm/boot/dts/bcm-cygnus.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi
index 9fe4f5a..835a6f7 100644
--- a/arch/arm/boot/dts/bcm-cygnus.dtsi
+++ b/arch/arm/boot/dts/bcm-cygnus.dtsi
@@ -216,7 +216,7 @@
reg = <0x18008000 0x100>;
#address-cells = <1>;
#size-cells = <0>;
- interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <100000>;
status = "disabled";
};
@@ -245,7 +245,7 @@
reg = <0x1800b000 0x100>;
#address-cells = <1>;
#size-cells = <0>;
- interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <100000>;
status = "disabled";
};
--
2.1.4
^ permalink raw reply related
* [PATCH 0/5] Fix Cygnus, NS2, Stingray interrupt type
From: Ray Jui @ 2018-06-12 20:21 UTC (permalink / raw)
To: linux-arm-kernel
This patch series fixes incorrect interrupt types for I2C and PCIe in DT
for Broadcom Cygnus, NS2, and Stingray SoCs
This patch series is based off v4.17 and is available on GIHUB:
repo: https://github.com/Broadcom/arm64-linux.git
branch: cygnus-ns2-dt-irq-type-fix-v1
Ray Jui (5):
ARM: dts: cygnus: Fix I2C controller interrupt type
ARM: dts: cygnus: Fix PCIe controller interrupt type
ARM64: dts: ns2: Fix I2C controller interrupt type
ARM64: dts: ns2: Fix PCIe controller interrupt type
ARM64: dts: Stingray: Fix I2C controller interrupt type
arch/arm/boot/dts/bcm-cygnus.dtsi | 24 +++++++++++-----------
arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi | 8 ++++----
.../arm64/boot/dts/broadcom/stingray/stingray.dtsi | 4 ++--
3 files changed, 18 insertions(+), 18 deletions(-)
--
2.1.4
^ permalink raw reply
* [PATCH 1/2] media: dt-bindings: media: xilinx: Add Xilinx MIPI CSI-2 Rx Subsystem
From: Rob Herring @ 2018-06-12 20:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527620084-94864-2-git-send-email-vishal.sagar@xilinx.com>
On Wed, May 30, 2018 at 12:24:43AM +0530, Vishal Sagar wrote:
> Add bindings documentation for Xilinx MIPI CSI-2 Rx Subsystem.
>
> The Xilinx MIPI CSI-2 Rx Subsystem consists of a DPHY, CSI-2 Rx, an
> optional I2C controller and an optional Video Format Bridge (VFB). The
> active lanes can be configured at run time if enabled in the IP. The
> DPHY register interface may also be enabled.
>
> Signed-off-by: Vishal Sagar <vishal.sagar@xilinx.com>
> ---
> .../bindings/media/xilinx/xlnx,csi2rxss.txt | 117 +++++++++++++++++++++
> 1 file changed, 117 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.txt
>
> diff --git a/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.txt b/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.txt
> new file mode 100644
> index 0000000..31ed721
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.txt
> @@ -0,0 +1,117 @@
> +
> +Xilinx MIPI CSI2 Receiver Subsystem Device Tree Bindings
> +--------------------------------------------------------
> +
> +The Xilinx MIPI CSI2 Receiver Subsystem is used to capture MIPI CSI2 traffic
> +from compliant camera sensors and send the output as AXI4 Stream video data
> +for image processing.
> +
> +The subsystem consists of a MIPI DPHY in slave mode which captures the
> +data packets. This is passed along the MIPI CSI2 Rx IP which extracts the
> +packet data. This data is taken in by the Video Format Bridge (VFB),
> +if selected, and converted into AXI4 Stream video data at selected
> +pixels per clock as per AXI4-Stream Video IP and System Design UG934.
> +
> +For more details, please refer to PG232 MIPI CSI-2 Receiver Subsystem.
> +https://www.xilinx.com/support/documentation/ip_documentation/mipi_csi2_rx_subsystem/v3_0/pg232-mipi-csi2-rx.pdf
> +
> +Required properties:
> +
> +- compatible: Must contain "xlnx,mipi-csi2-rx-subsystem-2.0" or
> + "xlnx,mipi-csi2-rx-subsystem-3.0"
> +
> +- reg: Physical base address and length of the registers set for the device.
> +
> +- interrupt-parent: specifies the phandle to the parent interrupt controller
> +
> +- interrupts: Property with a value describing the interrupt number.
> +
> +- xlnx,max-lanes: Maximum active lanes in the design.
There's already a property defined in video-interfaces.txt to limit
lanes.
> +
> +- xlnx,vc: Virtual Channel, specifies virtual channel number to be filtered.
> + If this is 4 then all virtual channels are allowed.
> +
> +- xlnx,csi-pxl-format: This denotes the CSI Data type selected in hw design.
> + Packets other than this data type (except for RAW8 and User defined data
> + types) will be filtered out. Possible values are RAW6, RAW7, RAW8, RAW10,
> + RAW12, RAW14, RGB444, RGB555, RGB565, RGB666, RGB888 and YUV4228bit.
This should be standard property.
> +
> +- xlnx,axis-tdata-width: AXI Stream width, This denotes the AXI Stream width.
> + It depends on Data type chosen, Video Format Bridge enabled/disabled and
> + pixels per clock. If VFB is disabled then its value is either 0x20 (32 bit)
> + or 0x40(64 bit) width.
> +
> +- xlnx,video-format, xlnx,video-width: Video format and width, as defined in
> + video.txt.
This doc needs to define what are valid values.
Why do you need this on both ports? Can there be a conversion in this
block? At least for the MIPI CSI interface part, this should be a common
property. Not sure offhand if we have defined one. We have for parallel
interfaces.
And 'width' doesn't seem like the right term for what this is defined to
be.
> +
> +- port: Video port, using the DT bindings defined in ../video-interfaces.txt.
port is not a property. It goes in its own section. And port properties
should be under it.
> + The CSI 2 Rx Subsystem has a two ports, one input port for connecting to
> + camera sensor and other is output port.
Need be specific port #0 is ?? and port #1 is ??.
> +
> +- data-lanes: The number of data lanes through which CSI2 Rx Subsystem is
> + connected to the camera sensor as per video-interfaces.txt
Why do you need both this and max-lanes?
> +
> +Optional properties:
> +
> +- xlnx,en-active-lanes: Enable Active lanes configuration in Protocol
> + Configuration Register.
> +
> +- xlnx,dphy-present: This is equivalent to whether DPHY register interface is
> + enabled or not.
> +
> +- xlnx,iic-present: This shows whether subsystem's IIC is present or not. This
> + affects the base address of the DPHY.
Perhaps you should break up reg into ranges for each submodule (or make
the DPHY a separate node and use the phy binding.
> +
> +- xlnx,vfb: Video Format Bridge, Denotes if Video Format Bridge is selected
> + so that output is as per AXI stream documented in UG934.
> +
> +- xlnx,ppc: Pixels per clock, Number of pixels to be transferred per pixel
> + clock. This is valid only if xlnx,vfb property is present.
> +
> +Example:
> +
> + csiss_1: csiss at a0020000 {
> + compatible = "xlnx,mipi-csi2-rx-subsystem-3.0";
> + reg = <0x0 0xa0020000 0x0 0x20000>;
> + interrupt-parent = <&gic>;
> + interrupts = <0 95 4>;
> +
> + xlnx,max-lanes = <0x4>;
> + xlnx,en-active-lanes;
> + xlnx,dphy-present;
> + xlnx,iic-present;
> + xlnx,vc = <0x4>;
> + xlnx,csi-pxl-format = "RAW8";
> + xlnx,vfb;
> + xlnx,ppc = <0x4>;
> + xlnx,axis-tdata-width = <0x20>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port at 0 {
> + reg = <0>;
> +
> + xlnx,video-format = <XVIP_VF_YUV_422>;
> + xlnx,video-width = <8>;
> + csiss_out: endpoint {
> + remote-endpoint = <&vcap_csiss_in>;
> + };
> + };
> + port at 1 {
> + reg = <1>;
> +
> + xlnx,video-format = <XVIP_VF_YUV_422>;
> + xlnx,video-width = <8>;
> +
> + csiss_in: endpoint {
> + data-lanes = <1 2 3 4>;
> + /* MIPI CSI2 Camera handle */
> + remote-endpoint = <&vs2016_out>;
> + };
> +
> + };
> +
> + };
> + };
> --
> 2.7.4
>
> This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v2 27/27] ARM: dts: sun8i: r40: Enable HDMI output on BananaPi M2 Ultra
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
Since HDMI can be considered as main output, most capable mixer is
connected to it (mixer0).
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
.../boot/dts/sun8i-r40-bananapi-m2-ultra.dts | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
index 27d9ccd0ef2f..0ebc2f9a980e 100644
--- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
+++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
@@ -58,6 +58,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";
@@ -93,6 +104,10 @@
};
};
+&de {
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -101,6 +116,16 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&i2c0 {
status = "okay";
@@ -195,6 +220,26 @@
status = "okay";
};
+&tcon_top_hdmi_in_tcon_tv0 {
+ remote-endpoint = <&tcon_tv0_out_tcon_top>;
+};
+
+&tcon_top_mixer0_out_tcon_tv0 {
+ remote-endpoint = <&tcon_tv0_in_tcon_top>;
+};
+
+&tcon_tv0_in {
+ tcon_tv0_in_tcon_top: endpoint {
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
+ };
+};
+
+&tcon_tv0_out {
+ tcon_tv0_out_tcon_top: endpoint {
+ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
+ };
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pb_pins>;
--
2.17.1
^ permalink raw reply related
* [PATCH v2 26/27] ARM: dts: sun8i: r40: Add HDMI pipeline
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
Add all entries needed for HDMI to function properly.
Since R40 has highly configurable pipeline, both mixers and both TCON
TVs are added. Board specific DT should then connect them together
trough TCON TOP muxers to best fit the purpose of the board.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm/boot/dts/sun8i-r40.dtsi | 257 +++++++++++++++++++++++++++++++
1 file changed, 257 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index 173dcc1652d2..17171c82457e 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -42,8 +42,11 @@
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun8i-de2.h>
#include <dt-bindings/clock/sun8i-r40-ccu.h>
+#include <dt-bindings/clock/sun8i-tcon-top.h>
#include <dt-bindings/reset/sun8i-r40-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
/ {
#address-cells = <1>;
@@ -99,12 +102,76 @@
};
};
+ de: display-engine {
+ compatible = "allwinner,sun8i-r40-display-engine",
+ "allwinner,sun8i-h3-display-engine";
+ allwinner,pipelines = <&mixer0>, <&mixer1>;
+ status = "disabled";
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
+ display_clocks: clock at 1000000 {
+ compatible = "allwinner,sun8i-r40-de2-clk",
+ "allwinner,sun8i-h3-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>;
+ };
+
+ mixer0: mixer at 1100000 {
+ compatible = "allwinner,sun8i-r40-de2-mixer-0";
+ reg = <0x01100000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER0>,
+ <&display_clocks CLK_MIXER0>;
+ clock-names = "bus",
+ "mod";
+ resets = <&display_clocks RST_MIXER0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer0_out: port at 1 {
+ reg = <1>;
+ mixer0_out_tcon_top: endpoint {
+ remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
+ };
+ };
+ };
+ };
+
+ mixer1: mixer at 1200000 {
+ compatible = "allwinner,sun8i-r40-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 at 1 {
+ reg = <1>;
+ mixer1_out_tcon_top: endpoint {
+ remote-endpoint = <&tcon_top_mixer1_in_mixer1>;
+ };
+ };
+ };
+ };
+
nmi_intc: interrupt-controller at 1c00030 {
compatible = "allwinner,sun7i-a20-sc-nmi";
interrupt-controller;
@@ -451,6 +518,151 @@
#size-cells = <0>;
};
+ tcon_top: tcon-top at 1c70000 {
+ compatible = "allwinner,sun8i-r40-tcon-top";
+ reg = <0x01c70000 0x1000>;
+ clocks = <&ccu CLK_BUS_TCON_TOP>;
+ clock-names = "bus";
+ resets = <&ccu RST_BUS_TCON_TOP>;
+ reset-names = "rst";
+ #clock-cells = <1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_in: port at 0 {
+ reg = <0>;
+
+ tcon_top_mixer0_in_mixer0: endpoint {
+ remote-endpoint = <&mixer0_out_tcon_top>;
+ };
+ };
+
+ tcon_top_mixer0_out: port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ tcon_top_mixer0_out_tcon_lcd0: endpoint at 0 {
+ reg = <0>;
+ };
+
+ tcon_top_mixer0_out_tcon_lcd1: endpoint at 1 {
+ reg = <1>;
+ };
+
+ tcon_top_mixer0_out_tcon_tv0: endpoint at 2 {
+ reg = <2>;
+ };
+
+ tcon_top_mixer0_out_tcon_tv1: endpoint at 3 {
+ reg = <3>;
+ };
+ };
+
+ tcon_top_mixer1_in: port at 2 {
+ reg = <2>;
+
+ tcon_top_mixer1_in_mixer1: endpoint {
+ remote-endpoint = <&mixer1_out_tcon_top>;
+ };
+ };
+
+ tcon_top_mixer1_out: port at 3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ tcon_top_mixer1_out_tcon_lcd0: endpoint at 0 {
+ reg = <0>;
+ };
+
+ tcon_top_mixer1_out_tcon_lcd1: endpoint at 1 {
+ reg = <1>;
+ };
+
+ tcon_top_mixer1_out_tcon_tv0: endpoint at 2 {
+ reg = <2>;
+ };
+
+ tcon_top_mixer1_out_tcon_tv1: endpoint at 3 {
+ reg = <3>;
+ };
+ };
+
+ tcon_top_hdmi_in: port at 4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+
+ tcon_top_hdmi_in_tcon_tv0: endpoint at 0 {
+ reg = <0>;
+ };
+
+ tcon_top_hdmi_in_tcon_tv1: endpoint at 1 {
+ reg = <1>;
+ };
+ };
+
+ tcon_top_hdmi_out: port at 5 {
+ reg = <5>;
+
+ tcon_top_hdmi_out_hdmi: endpoint {
+ remote-endpoint = <&hdmi_in_tcon_top>;
+ };
+ };
+ };
+ };
+
+ tcon_tv0: lcd-controller at 1c73000 {
+ compatible = "allwinner,sun8i-r40-tcon-tv";
+ reg = <0x01c73000 0x1000>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_TV0>, <&ccu CLK_TCON_TV0>,
+ <&tcon_top 1>;
+ clock-names = "ahb", "tcon-ch1", "tcon-top";
+ resets = <&ccu RST_BUS_TCON_TV0>;
+ reset-names = "lcd";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv0_in: port at 0 {
+ reg = <0>;
+ };
+
+ tcon_tv0_out: port at 1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ tcon_tv1: lcd-controller at 1c74000 {
+ compatible = "allwinner,sun8i-r40-tcon-tv";
+ reg = <0x01c74000 0x1000>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_TV1>, <&ccu CLK_TCON_TV1>,
+ <&tcon_top 2>;
+ clock-names = "ahb", "tcon-ch1", "tcon-top";
+ resets = <&ccu RST_BUS_TCON_TV1>;
+ reset-names = "lcd";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv1_in: port at 0 {
+ reg = <0>;
+ };
+
+ tcon_tv1_out: port at 1 {
+ reg = <1>;
+ };
+ };
+ };
+
gic: interrupt-controller at 1c81000 {
compatible = "arm,gic-400";
reg = <0x01c81000 0x1000>,
@@ -461,6 +673,51 @@
#interrupt-cells = <3>;
interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
+
+ hdmi: hdmi at 1ee0000 {
+ compatible = "allwinner,sun8i-r40-dw-hdmi",
+ "allwinner,sun8i-a83t-dw-hdmi";
+ reg = <0x01ee0000 0x10000>;
+ reg-io-width = <1>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_HDMI0>, <&ccu CLK_HDMI_SLOW>,
+ <&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";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi_in: port at 0 {
+ reg = <0>;
+
+ hdmi_in_tcon_top: endpoint {
+ remote-endpoint = <&tcon_top_hdmi_out_hdmi>;
+ };
+ };
+
+ hdmi_out: port at 1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ hdmi_phy: hdmi-phy at 1ef0000 {
+ compatible = "allwinner,sun8i-r40-hdmi-phy",
+ "allwinner,sun50i-a64-hdmi-phy";
+ reg = <0x01ef0000 0x10000>;
+ clocks = <&ccu CLK_BUS_HDMI1>, <&ccu CLK_HDMI_SLOW>,
+ <&ccu 7>, <&ccu 16>;
+ clock-names = "bus", "mod", "pll-0", "pll-1";
+ resets = <&ccu RST_BUS_HDMI0>;
+ reset-names = "phy";
+ #phy-cells = <0>;
+ };
};
timer {
--
2.17.1
^ permalink raw reply related
* [PATCH v2 25/27] drm/sun4i: DW HDMI: Expand algorithm for possible crtcs
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
drm_of_find_possible_crtcs() doesn't work when DW HDMI encoder is
connected to TCON (crtc) through mux in TCON TOP.
In that case TCON TOP HDMI mux input port has to be manually traversed
and checked if it matches any known crtc.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 46 ++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 9f40a44b456b..d443886e055b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -12,6 +12,7 @@
#include <drm/drm_crtc_helper.h>
#include "sun8i_dw_hdmi.h"
+#include "sun8i_tcon_top.h"
static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
@@ -41,6 +42,48 @@ sun8i_dw_hdmi_mode_valid(struct drm_connector *connector,
return MODE_OK;
}
+static bool sun8i_dw_hdmi_node_is_tcon_top(struct device_node *node)
+{
+ return !!of_match_node(sun8i_tcon_top_of_table, node);
+}
+
+static u32 sun8i_dw_hdmi_find_possible_crtcs(struct drm_device *drm,
+ struct device_node *node)
+{
+ struct device_node *port, *ep, *remote, *remote_port;
+ u32 crtcs = 0;
+
+ port = of_graph_get_port_by_id(node, 0);
+ if (!port)
+ return 0;
+
+ ep = of_get_next_available_child(port, NULL);
+ if (!ep)
+ return 0;
+
+ remote = of_graph_get_remote_port_parent(ep);
+ if (!remote)
+ return 0;
+
+ if (sun8i_dw_hdmi_node_is_tcon_top(remote)) {
+ port = of_graph_get_port_by_id(remote, 4);
+ if (!port)
+ return 0;
+
+ for_each_child_of_node(port, ep) {
+ remote_port = of_graph_get_remote_port(ep);
+ if (remote_port) {
+ crtcs |= drm_crtc_port_mask(drm, remote_port);
+ of_node_put(remote_port);
+ }
+ }
+ } else {
+ crtcs = drm_of_find_possible_crtcs(drm, node);
+ }
+
+ return crtcs;
+}
+
static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
void *data)
{
@@ -63,7 +106,8 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
hdmi->dev = &pdev->dev;
encoder = &hdmi->encoder;
- encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+ encoder->possible_crtcs =
+ sun8i_dw_hdmi_find_possible_crtcs(drm, dev->of_node);
/*
* If we failed to find the CRTC(s) which this encoder is
* supposed to be connected to, it's because the CRTC has
--
2.17.1
^ permalink raw reply related
* [PATCH v2 24/27] drm: of: Export drm_crtc_port_mask()
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
Function is useful when drm_of_find_possible_crtcs() can't be used and
custom parsing is needed. This can happen for example when there is a
node with multiple muxes between crtc and encoder.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/drm_of.c | 4 ++--
include/drm/drm_of.h | 8 ++++++++
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 1fe122461298..2e9cea3287b2 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -22,8 +22,8 @@ static void drm_release_of(struct device *dev, void *data)
* Given a port OF node, return the possible mask of the corresponding
* CRTC within a device's list of CRTCs. Returns zero if not found.
*/
-static uint32_t drm_crtc_port_mask(struct drm_device *dev,
- struct device_node *port)
+uint32_t drm_crtc_port_mask(struct drm_device *dev,
+ struct device_node *port)
{
unsigned int index = 0;
struct drm_crtc *tmp;
diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h
index b93c239afb60..a61fd77e46ba 100644
--- a/include/drm/drm_of.h
+++ b/include/drm/drm_of.h
@@ -17,6 +17,8 @@ struct drm_bridge;
struct device_node;
#ifdef CONFIG_OF
+uint32_t drm_crtc_port_mask(struct drm_device *dev,
+ struct device_node *port);
uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port);
void drm_of_component_match_add(struct device *master,
@@ -34,6 +36,12 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
struct drm_panel **panel,
struct drm_bridge **bridge);
#else
+static inline uint32_t drm_crtc_port_mask(struct drm_device *dev,
+ struct device_node *port)
+{
+ return 0;
+}
+
static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port)
{
--
2.17.1
^ permalink raw reply related
* [PATCH v2 23/27] drm/sun4i: Add support for A64 HDMI PHY
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
PHY is the same as in H3, except it can switch between two clock
parents.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index e1b7196d4587..457f0a121684 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -396,6 +396,14 @@ static struct regmap_config sun8i_hdmi_phy_regmap_config = {
.name = "phy"
};
+static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
+ .has_phy_clk = true,
+ .has_second_pll = true,
+ .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,
@@ -410,6 +418,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.17.1
^ permalink raw reply related
* [PATCH v2 22/27] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
Expand HDMI PHY clock driver to support second clock parent.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 4 +-
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 3 +-
drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 90 ++++++++++++++++------
3 files changed, 73 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 46a3aa6a53a9..aadbe0a10b0c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -99,6 +99,7 @@
#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_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)
@@ -190,6 +191,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,
+ bool second_parent);
#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 f50072ae054a..e1b7196d4587 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -491,7 +491,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
}
}
- ret = sun8i_phy_clk_create(phy, dev);
+ ret = sun8i_phy_clk_create(phy, dev,
+ phy->variant->has_second_pll);
if (ret) {
dev_err(dev, "Couldn't create the PHY clock\n");
goto err_put_clk_pll1;
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
index faea449812f8..a4d31fe3abff 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
@@ -22,35 +22,45 @@ static int sun8i_phy_clk_determine_rate(struct clk_hw *hw,
{
unsigned long rate = req->rate;
unsigned long best_rate = 0;
+ struct clk_hw *best_parent = NULL;
struct clk_hw *parent;
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);
+ for (p = 0; p < clk_hw_get_num_parents(hw); p++) {
+ parent = clk_hw_get_parent_by_index(hw, p);
+ if (!parent)
+ continue;
- if (rounded == ideal) {
- best_rate = rounded;
- best_div = i;
- break;
+ 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;
+ }
}
- if (!best_rate ||
- abs(rate - rounded / i) <
- abs(rate - best_rate / best_div)) {
- best_rate = rounded;
- best_div = i;
- }
+ if (best_rate / best_div == rate)
+ break;
}
req->rate = best_rate / best_div;
req->best_parent_rate = best_rate;
- req->best_parent_hw = parent;
+ req->best_parent_hw = best_parent;
return 0;
}
@@ -95,22 +105,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,
+ bool second_parent)
{
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 (second_parent) {
+ 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 +164,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 = second_parent ? 2 : 1;
init.flags = CLK_SET_RATE_PARENT;
priv->phy = phy;
--
2.17.1
^ permalink raw reply related
* [PATCH v2 21/27] drm/sun4i: DW HDMI PHY: Add support for second PLL
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
Some DW HDMI PHYs, like those found in A64 and R40 SoCs, can select
between two clock parents.
Add code which reads second PLL from DT.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 ++
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 20 +++++++++++++++-----
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 3ba71aff92fc..46a3aa6a53a9 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -147,6 +147,7 @@ struct sun8i_hdmi_phy;
struct sun8i_hdmi_phy_variant {
bool has_phy_clk;
+ bool has_second_pll;
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;
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index cd07ceb71601..f50072ae054a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -482,10 +482,19 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
goto err_put_clk_mod;
}
+ if (phy->variant->has_second_pll) {
+ 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_pll0;
+ }
+ }
+
ret = sun8i_phy_clk_create(phy, dev);
if (ret) {
dev_err(dev, "Couldn't create the PHY clock\n");
- goto err_put_clk_pll0;
+ goto err_put_clk_pll1;
}
clk_prepare_enable(phy->clk_phy);
@@ -528,9 +537,10 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
reset_control_put(phy->rst_phy);
err_disable_clk_phy:
clk_disable_unprepare(phy->clk_phy);
+err_put_clk_pll1:
+ clk_put(phy->clk_pll1);
err_put_clk_pll0:
- if (phy->variant->has_phy_clk)
- clk_put(phy->clk_pll0);
+ clk_put(phy->clk_pll0);
err_put_clk_mod:
clk_put(phy->clk_mod);
err_put_clk_bus:
@@ -551,8 +561,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);
}
--
2.17.1
^ permalink raw reply related
* [PATCH v2 20/27] drm/sun4i: Don't change clock bits in DW HDMI PHY driver
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
DW HDMI PHY driver and PHY clock driver share same registers. Make sure
that DW HDMI PHY setup code doesn't change any clock related bits and
set them to 0 during initialization.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 +-
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 12 +++++++++++-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 79154f0f674a..3ba71aff92fc 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -98,7 +98,7 @@
#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_PLLEN BIT(25)
#define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22)
#define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20)
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 966688f04741..cd07ceb71601 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);
@@ -352,6 +358,10 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy)
SUN8I_HDMI_PHY_ANA_CFG3_SCLEN |
SUN8I_HDMI_PHY_ANA_CFG3_SDAEN);
+ /* reset PLL clock configuration */
+ regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 0);
+ regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, 0);
+
/* set HW control of CEC pins */
regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG, 0);
--
2.17.1
^ permalink raw reply related
* [PATCH v2 19/27] drm/sun4i: Enable DW HDMI PHY clock
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
Current DW HDMI PHY code never prepares and enables PHY clock after it is
created. It's just used as it is. This may work in some cases, but it's
clearly wrong. Fix it by adding proper calls to enable/disable PHY
clock.
Fixes: 4f86e81748fe ("drm/sun4i: Add support for H3 HDMI PHY variant")
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 5a52fc489a9d..966688f04741 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -477,13 +477,15 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
dev_err(dev, "Couldn't create the PHY clock\n");
goto err_put_clk_pll0;
}
+
+ clk_prepare_enable(phy->clk_phy);
}
phy->rst_phy = of_reset_control_get_shared(node, "phy");
if (IS_ERR(phy->rst_phy)) {
dev_err(dev, "Could not get phy reset control\n");
ret = PTR_ERR(phy->rst_phy);
- goto err_put_clk_pll0;
+ goto err_disable_clk_phy;
}
ret = reset_control_deassert(phy->rst_phy);
@@ -514,6 +516,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
reset_control_assert(phy->rst_phy);
err_put_rst_phy:
reset_control_put(phy->rst_phy);
+err_disable_clk_phy:
+ clk_disable_unprepare(phy->clk_phy);
err_put_clk_pll0:
if (phy->variant->has_phy_clk)
clk_put(phy->clk_pll0);
@@ -531,6 +535,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
clk_disable_unprepare(phy->clk_mod);
clk_disable_unprepare(phy->clk_bus);
+ clk_disable_unprepare(phy->clk_phy);
reset_control_assert(phy->rst_phy);
--
2.17.1
^ permalink raw reply related
* [PATCH v2 18/27] dt-bindings: display: sun4i-drm: Add description of A64 HDMI PHY
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
A64 HDMI PHY is similar to H3 HDMI PHY except it has two possible PLL
clock parents. It is compatible to other HDMI PHYs, like that found in
R40.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index d84df6d808c2..6fb45c7a9ac8 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -101,6 +101,7 @@ DWC HDMI PHY
Required properties:
- compatible: value must be one of:
+ * allwinner,sun50i-a64-hdmi-phy
* allwinner,sun8i-a83t-hdmi-phy
* allwinner,sun8i-h3-hdmi-phy
- reg: base address and size of memory-mapped region
@@ -111,8 +112,9 @@ Required properties:
- resets: phandle to the reset controller driving the PHY
- reset-names: must be "phy"
-H3 HDMI PHY requires additional clock:
+H3 and A64 HDMI PHY require additional clocks:
- pll-0: parent of phy clock
+ - pll-1: second possible phy clock parent (A64 only)
TV Encoder
----------
--
2.17.1
^ permalink raw reply related
* [PATCH v2 17/27] drm/sun4i: Add support for R40 mixers
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
Both mixers have similar capabilities as others SoCs with DE2.
First mixer has 1 VI and 3 UI planes and supports HW scaling on all
planes.
Second mixer has 1 VI and 1 UI planes and also supports HW scaling on
all planes.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun8i_mixer.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 126899d6f0d3..ee8febb25903 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -500,6 +500,22 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
.vi_num = 1,
};
+static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
+ .ccsc = 0,
+ .mod_rate = 297000000,
+ .scaler_mask = 0xf,
+ .ui_num = 3,
+ .vi_num = 1,
+};
+
+static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
+ .ccsc = 1,
+ .mod_rate = 297000000,
+ .scaler_mask = 0x3,
+ .ui_num = 1,
+ .vi_num = 1,
+};
+
static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
.vi_num = 2,
.ui_num = 1,
@@ -521,6 +537,14 @@ static const struct of_device_id sun8i_mixer_of_table[] = {
.compatible = "allwinner,sun8i-h3-de2-mixer-0",
.data = &sun8i_h3_mixer0_cfg,
},
+ {
+ .compatible = "allwinner,sun8i-r40-de2-mixer-0",
+ .data = &sun8i_r40_mixer0_cfg,
+ },
+ {
+ .compatible = "allwinner,sun8i-r40-de2-mixer-1",
+ .data = &sun8i_r40_mixer1_cfg,
+ },
{
.compatible = "allwinner,sun8i-v3s-de2-mixer",
.data = &sun8i_v3s_mixer_cfg,
--
2.17.1
^ permalink raw reply related
* [PATCH v2 16/27] dt-bindings: display: sun4i-drm: Add R40 mixer compatibles
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
R40 DE2 mixers are similar to those found in A83T, except it needs
different clock settings.
Add a compatibles for them.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 68c4b2995624..d84df6d808c2 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -358,6 +358,8 @@ Required properties:
* allwinner,sun8i-a83t-de2-mixer-0
* allwinner,sun8i-a83t-de2-mixer-1
* allwinner,sun8i-h3-de2-mixer-0
+ * allwinner,sun8i-r40-de2-mixer-0
+ * allwinner,sun8i-r40-de2-mixer-1
* allwinner,sun8i-v3s-de2-mixer
- reg: base address and size of the memory-mapped region.
- clocks: phandles to the clocks feeding the mixer
--
2.17.1
^ permalink raw reply related
* [PATCH v2 15/27] drm/sun4i: Add support for R40 TV TCON
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
R40 TV TCON is similar to the A83T TV TCON, except that it needs
additional gate to be enabled.
Add support for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index c9ffa5381185..f20da2aa2165 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1326,6 +1326,11 @@ static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
.has_channel_1 = true,
};
+static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
+ .has_channel_1 = true,
+ .has_tcon_top_gate = true,
+};
+
static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
.has_channel_0 = true,
};
@@ -1350,6 +1355,7 @@ const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
{ .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
{ .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks },
+ { .compatible = "allwinner,sun8i-r40-tcon-tv", .data = &sun8i_r40_tv_quirks },
{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks },
--
2.17.1
^ permalink raw reply related
* [PATCH v2 14/27] drm/sun4i: Don't check for panel or bridge on TV TCONs
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
TV TCONs are always connected to TV or HDMI encoder, so it doesn't make
sense to check if panel or bridge is connected to them.
Check if TCON has channel 0 and only then check for connected panel or
bridges.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index b1205a7bc20f..c9ffa5381185 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1189,13 +1189,19 @@ static const struct component_ops sun4i_tcon_ops = {
static int sun4i_tcon_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
+ const struct sun4i_tcon_quirks *quirks;
struct drm_bridge *bridge;
struct drm_panel *panel;
int ret;
- ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
- if (ret == -EPROBE_DEFER)
- return ret;
+ quirks = of_device_get_match_data(&pdev->dev);
+
+ /* panels and bridges are present only on TCONs with channel 0 */
+ if (quirks->has_channel_0) {
+ ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ }
return component_add(&pdev->dev, &sun4i_tcon_ops);
}
--
2.17.1
^ permalink raw reply related
* [PATCH v2 13/27] drm/sun4i: Don't check for LVDS and RGB when TCON has only ch1
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
LVDS and RGB interfaces are always connected to TCONs which have channel
0. It doesn't make sense to try to init them on TV TCONs.
Add a check if TCON has channel 0 before trying to init LVDS or RGB
interface.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 32 ++++++++++++++++--------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 5dae623968f7..b1205a7bc20f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1117,23 +1117,25 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
goto err_free_dotclock;
}
- /*
- * If we have an LVDS panel connected to the TCON, we should
- * just probe the LVDS connector. Otherwise, just probe RGB as
- * we used to.
- */
- remote = of_graph_get_remote_node(dev->of_node, 1, 0);
- if (of_device_is_compatible(remote, "panel-lvds"))
- if (can_lvds)
- ret = sun4i_lvds_init(drm, tcon);
+ if (tcon->quirks->has_channel_0) {
+ /*
+ * If we have an LVDS panel connected to the TCON, we should
+ * just probe the LVDS connector. Otherwise, just probe RGB as
+ * we used to.
+ */
+ remote = of_graph_get_remote_node(dev->of_node, 1, 0);
+ if (of_device_is_compatible(remote, "panel-lvds"))
+ if (can_lvds)
+ ret = sun4i_lvds_init(drm, tcon);
+ else
+ ret = -EINVAL;
else
- ret = -EINVAL;
- else
- ret = sun4i_rgb_init(drm, tcon);
- of_node_put(remote);
+ ret = sun4i_rgb_init(drm, tcon);
+ of_node_put(remote);
- if (ret < 0)
- goto err_free_dotclock;
+ if (ret < 0)
+ goto err_free_dotclock;
+ }
if (tcon->quirks->needs_de_be_mux) {
/*
--
2.17.1
^ permalink raw reply related
* [PATCH v2 12/27] drm/sun4i: tcon: Generalize engine search algorithm
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
Current "old" method to find engine worked pretty well for DE2. However,
it doesn't work when TCON TOP is between mixer (engine) and TCON. TCON
TOP has multiple input ports, but current engine search algorithm
expects only one.
This can be fixed by first looking for output port id and selecting
matching input by subtracting 1 for the next round. This work even if
there is only one input and output.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 0afb5a94a414..5dae623968f7 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -802,12 +802,14 @@ static int sun4i_tcon_init_regmap(struct device *dev,
*/
static struct sunxi_engine *
sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
- struct device_node *node)
+ struct device_node *node,
+ u32 port_id)
{
struct device_node *port, *ep, *remote;
struct sunxi_engine *engine = ERR_PTR(-EINVAL);
+ u32 reg = 0;
- port = of_graph_get_port_by_id(node, 0);
+ port = of_graph_get_port_by_id(node, port_id);
if (!port)
return ERR_PTR(-EINVAL);
@@ -837,8 +839,20 @@ sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
if (remote == engine->node)
goto out_put_remote;
+ /*
+ * According to device tree binding input ports have even id
+ * number and output ports have odd id. Since component with
+ * more than one input and one output (TCON TOP) exits, correct
+ * remote input id has to be calculated by subtracting 1 from
+ * remote output id. If this for some reason can't be done, 0
+ * is used as input port id.
+ */
+ port = of_graph_get_remote_port(ep);
+ if (!of_property_read_u32(port, "reg", ®) && reg > 0)
+ reg -= 1;
+
/* keep looking through upstream ports */
- engine = sun4i_tcon_find_engine_traverse(drv, remote);
+ engine = sun4i_tcon_find_engine_traverse(drv, remote, reg);
out_put_remote:
of_node_put(remote);
@@ -961,7 +975,7 @@ static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
/* Fallback to old method by traversing input endpoints */
of_node_put(port);
- return sun4i_tcon_find_engine_traverse(drv, node);
+ return sun4i_tcon_find_engine_traverse(drv, node, 0);
}
static int sun4i_tcon_bind(struct device *dev, struct device *master,
--
2.17.1
^ permalink raw reply related
* [PATCH v2 11/27] drm/sun4i: tcon: Add support for tcon-top gate
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
TV TCONs connected to TCON TOP have to enable additional gate in order
to work.
Add support for such TCONs.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 11 +++++++++++
drivers/gpu/drm/sun4i/sun4i_tcon.h | 4 ++++
2 files changed, 15 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 08747fc3ee71..0afb5a94a414 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -688,6 +688,16 @@ static int sun4i_tcon_init_clocks(struct device *dev,
dev_err(dev, "Couldn't get the TCON bus clock\n");
return PTR_ERR(tcon->clk);
}
+
+ if (tcon->quirks->has_tcon_top_gate) {
+ tcon->top_clk = devm_clk_get(dev, "tcon-top");
+ if (IS_ERR(tcon->top_clk)) {
+ dev_err(dev, "Couldn't get the TCON TOP bus clock\n");
+ return PTR_ERR(tcon->top_clk);
+ }
+ clk_prepare_enable(tcon->top_clk);
+ }
+
clk_prepare_enable(tcon->clk);
if (tcon->quirks->has_channel_0) {
@@ -712,6 +722,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
{
clk_disable_unprepare(tcon->clk);
+ clk_disable_unprepare(tcon->top_clk);
}
static int sun4i_tcon_init_irq(struct device *dev,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index f6a071cd5a6f..652d5c37d7b4 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -224,6 +224,7 @@ struct sun4i_tcon_quirks {
bool needs_de_be_mux; /* sun6i needs mux to select backend */
bool needs_edp_reset; /* a80 edp reset needed for tcon0 access */
bool supports_lvds; /* Does the TCON support an LVDS output? */
+ bool has_tcon_top_gate; /* TCON TOP holds additional gate to enable */
/* callback to handle tcon muxing options */
int (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
@@ -249,6 +250,9 @@ struct sun4i_tcon {
u8 dclk_max_div;
u8 dclk_min_div;
+ /* TCON TOP clock */
+ struct clk *top_clk;
+
/* Reset control */
struct reset_control *lcd_rst;
struct reset_control *lvds_rst;
--
2.17.1
^ permalink raw reply related
* [PATCH v2 10/27] dt-bindings: display: sun4i-drm: Add R40 TV TCON description
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
TCON description is expanded with R40 TV TCON compatibles. TV TCONs,
which are connected to TCON TOP muxes, such as those on R40 SoC, also
needs additional clock gate to be specified.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
.../devicetree/bindings/display/sunxi/sun4i-drm.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index ef64c589a4b3..68c4b2995624 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -145,6 +145,7 @@ Required properties:
* allwinner,sun8i-a33-tcon
* allwinner,sun8i-a83t-tcon-lcd
* allwinner,sun8i-a83t-tcon-tv
+ * allwinner,sun8i-r40-tcon-tv
* allwinner,sun8i-v3s-tcon
* allwinner,sun9i-a80-tcon-lcd
* allwinner,sun9i-a80-tcon-tv
@@ -178,8 +179,10 @@ For TCONs with channel 0, there is one more clock required:
- 'tcon-ch0': The clock driving the TCON channel 0
For TCONs with channel 1, there is one more clock required:
- 'tcon-ch1': The clock driving the TCON channel 1
+TV TCONs which are connected to TCON TOP (found in R40 SoC) need one more clock:
+ - 'tcon-top': TV TCON gate found in TCON TOP unit
-When TCON support LVDS (all TCONs except TV TCON on A83T and those found
+When TCON support LVDS (all TCONs except TV TCONs on A83T, R40 and those found
in A13, H3, H5 and V3s SoCs), you need one more reset line:
- 'lvds': The reset line driving the LVDS logic
--
2.17.1
^ permalink raw reply related
* [PATCH v2 09/27] drm/sun4i: Don't skip TCONs if they don't have channel 0
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
TV TCONs (channel 1 only) are always connected to TV or HDMI encoder.
Because of that, all output endpoints on such TCON node will point to a
encoder which is part of component framework.
Correct current graph traversing algorithm in such way that it doesn't
skip output enpoints with id 0 on TV TCONs.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun4i_drv.c | 52 +++++++++++++++++++++----------
1 file changed, 35 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index e6c62c079146..6ddf4eaccb40 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -198,6 +198,22 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
return !!of_match_node(sun4i_tcon_of_table, node);
}
+static bool sun4i_drv_node_is_tcon_with_ch0(struct device_node *node)
+{
+ const struct of_device_id *match;
+
+ match = of_match_node(sun4i_tcon_of_table, node);
+ if (match) {
+ struct sun4i_tcon_quirks *quirks;
+
+ quirks = (struct sun4i_tcon_quirks *)match->data;
+
+ return quirks->has_channel_0;
+ }
+
+ return false;
+}
+
static bool sun4i_drv_node_is_tcon_top(struct device_node *node)
{
return !!of_match_node(sun8i_tcon_top_of_table, node);
@@ -256,14 +272,7 @@ static void sun4i_drv_traverse_endpoints(struct endpoint_list *list,
continue;
}
- /*
- * If the node is our TCON, the first port is used for
- * panel or bridges, and will not be part of the
- * component framework.
- */
if (sun4i_drv_node_is_tcon(node)) {
- struct of_endpoint endpoint;
-
/*
* TCON TOP is always probed before TCON. However, TCON
* points back to TCON TOP when it is source for HDMI.
@@ -276,16 +285,25 @@ static void sun4i_drv_traverse_endpoints(struct endpoint_list *list,
continue;
}
- if (of_graph_parse_endpoint(ep, &endpoint)) {
- DRM_DEBUG_DRIVER("Couldn't parse endpoint\n");
- of_node_put(remote);
- continue;
- }
-
- if (!endpoint.id) {
- DRM_DEBUG_DRIVER("Endpoint is our panel... skipping\n");
- of_node_put(remote);
- continue;
+ /*
+ * If the node is our TCON with channel 0, the first
+ * port is used for panel or bridges, and will not be
+ * part of the component framework.
+ */
+ if (sun4i_drv_node_is_tcon_with_ch0(node)) {
+ struct of_endpoint endpoint;
+
+ if (of_graph_parse_endpoint(ep, &endpoint)) {
+ DRM_DEBUG_DRIVER("Couldn't parse endpoint\n");
+ of_node_put(remote);
+ continue;
+ }
+
+ if (!endpoint.id) {
+ DRM_DEBUG_DRIVER("Endpoint is our panel... skipping\n");
+ of_node_put(remote);
+ continue;
+ }
}
}
--
2.17.1
^ permalink raw reply related
* [PATCH v2 08/27] drm/sun4i: Add support for traversing graph with TCON TOP
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
TCON TOP is different from other nodes in graph by having 3 input and 3
output ports. Additionally, connection to TV TCON might lead back to
HDMI mux input port, creating loops.
Add support for traversing such graph.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun4i_drv.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 20193d6f33ba..e6c62c079146 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -26,6 +26,7 @@
#include "sun4i_frontend.h"
#include "sun4i_framebuffer.h"
#include "sun4i_tcon.h"
+#include "sun8i_tcon_top.h"
DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
@@ -197,6 +198,11 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
return !!of_match_node(sun4i_tcon_of_table, node);
}
+static bool sun4i_drv_node_is_tcon_top(struct device_node *node)
+{
+ return !!of_match_node(sun8i_tcon_top_of_table, node);
+}
+
static int compare_of(struct device *dev, void *data)
{
DRM_DEBUG_DRIVER("Comparing of node %pOF with %pOF\n",
@@ -258,6 +264,18 @@ static void sun4i_drv_traverse_endpoints(struct endpoint_list *list,
if (sun4i_drv_node_is_tcon(node)) {
struct of_endpoint endpoint;
+ /*
+ * TCON TOP is always probed before TCON. However, TCON
+ * points back to TCON TOP when it is source for HDMI.
+ * We have to skip it here to prevent infinite looping
+ * between TCON TOP and TCON.
+ */
+ if (sun4i_drv_node_is_tcon_top(remote)) {
+ DRM_DEBUG_DRIVER("TCON output endpoint is TCON TOP... skipping\n");
+ of_node_put(remote);
+ continue;
+ }
+
if (of_graph_parse_endpoint(ep, &endpoint)) {
DRM_DEBUG_DRIVER("Couldn't parse endpoint\n");
of_node_put(remote);
@@ -318,6 +336,12 @@ static int sun4i_drv_add_endpoints(struct device *dev,
/* each node has at least one output */
sun4i_drv_traverse_endpoints(list, node, 1);
+ /* TCON TOP has second and third output */
+ if (sun4i_drv_node_is_tcon_top(node)) {
+ sun4i_drv_traverse_endpoints(list, node, 3);
+ sun4i_drv_traverse_endpoints(list, node, 5);
+ }
+
return count;
}
--
2.17.1
^ permalink raw reply related
* [PATCH v2 07/27] drm/sun4i: Split out code for enumerating endpoints in output port
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
Until now, each node has one input port and one output port. However,
with TCON TOP this is no longer true. It has 3 input and 3 output ports.
In order to prepare to this situation, split out the code which checks
all endpoints in input port and adds available components to fifo.
This patch doesn't do any functional change.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun4i_drv.c | 84 +++++++++++++++++--------------
1 file changed, 46 insertions(+), 38 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index e15fa2389e3f..20193d6f33ba 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -231,12 +231,55 @@ struct endpoint_list {
DECLARE_KFIFO(fifo, struct device_node *, 16);
};
+static void sun4i_drv_traverse_endpoints(struct endpoint_list *list,
+ struct device_node *node,
+ int port_id)
+{
+ struct device_node *ep, *remote, *port;
+
+ port = of_graph_get_port_by_id(node, port_id);
+ if (!port) {
+ DRM_DEBUG_DRIVER("No output to bind on port %d\n", port_id);
+ return;
+ }
+
+ for_each_available_child_of_node(port, ep) {
+ remote = of_graph_get_remote_port_parent(ep);
+ if (!remote) {
+ DRM_DEBUG_DRIVER("Error retrieving the output node\n");
+ continue;
+ }
+
+ /*
+ * If the node is our TCON, the first port is used for
+ * panel or bridges, and will not be part of the
+ * component framework.
+ */
+ if (sun4i_drv_node_is_tcon(node)) {
+ struct of_endpoint endpoint;
+
+ if (of_graph_parse_endpoint(ep, &endpoint)) {
+ DRM_DEBUG_DRIVER("Couldn't parse endpoint\n");
+ of_node_put(remote);
+ continue;
+ }
+
+ if (!endpoint.id) {
+ DRM_DEBUG_DRIVER("Endpoint is our panel... skipping\n");
+ of_node_put(remote);
+ continue;
+ }
+ }
+
+ kfifo_put(&list->fifo, remote);
+ }
+}
+
static int sun4i_drv_add_endpoints(struct device *dev,
struct endpoint_list *list,
struct component_match **match,
struct device_node *node)
{
- struct device_node *port, *ep, *remote;
int count = 0;
/*
@@ -272,43 +315,8 @@ static int sun4i_drv_add_endpoints(struct device *dev,
count++;
}
- /* Inputs are listed first, then outputs */
- port = of_graph_get_port_by_id(node, 1);
- if (!port) {
- DRM_DEBUG_DRIVER("No output to bind\n");
- return count;
- }
-
- for_each_available_child_of_node(port, ep) {
- remote = of_graph_get_remote_port_parent(ep);
- if (!remote) {
- DRM_DEBUG_DRIVER("Error retrieving the output node\n");
- continue;
- }
-
- /*
- * If the node is our TCON, the first port is used for
- * panel or bridges, and will not be part of the
- * component framework.
- */
- if (sun4i_drv_node_is_tcon(node)) {
- struct of_endpoint endpoint;
-
- if (of_graph_parse_endpoint(ep, &endpoint)) {
- DRM_DEBUG_DRIVER("Couldn't parse endpoint\n");
- of_node_put(remote);
- continue;
- }
-
- if (!endpoint.id) {
- DRM_DEBUG_DRIVER("Endpoint is our panel... skipping\n");
- of_node_put(remote);
- continue;
- }
- }
-
- kfifo_put(&list->fifo, remote);
- }
+ /* each node has at least one output */
+ sun4i_drv_traverse_endpoints(list, node, 1);
return count;
}
--
2.17.1
^ permalink raw reply related
* [PATCH v2 06/27] drm/sun4i: Fix releasing node when enumerating enpoints
From: Jernej Skrabec @ 2018-06-12 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612200036.21483-1-jernej.skrabec@siol.net>
sun4i_drv_add_endpoints() has a memory leak since it uses of_node_put()
when remote is equal to NULL and does nothing when remote has a valid
pointer.
Invert the logic to fix memory leak.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun4i_drv.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 50d19605c38f..e15fa2389e3f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -283,7 +283,6 @@ static int sun4i_drv_add_endpoints(struct device *dev,
remote = of_graph_get_remote_port_parent(ep);
if (!remote) {
DRM_DEBUG_DRIVER("Error retrieving the output node\n");
- of_node_put(remote);
continue;
}
@@ -297,11 +296,13 @@ static int sun4i_drv_add_endpoints(struct device *dev,
if (of_graph_parse_endpoint(ep, &endpoint)) {
DRM_DEBUG_DRIVER("Couldn't parse endpoint\n");
+ of_node_put(remote);
continue;
}
if (!endpoint.id) {
DRM_DEBUG_DRIVER("Endpoint is our panel... skipping\n");
+ of_node_put(remote);
continue;
}
}
--
2.17.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox