Files
2026-09-22 09:38:26 +08:00

1359 lines
42 KiB
Diff
Executable File

From 6f34ef4b6d1647582a1e81f7b5c0f07fd18f5caa Mon Sep 17 00:00:00 2001
From: rui.zhang1 <[email protected]>
Date: Wed, 29 Jul 2026 20:40:52 +0800
Subject: [PATCH] Bug #3548825 - bananapi(2c10) lcd ili9881c porting
[root cause ]: na
[changes ]:na
[side effects]:na
[self test ]:na
[download normally]:na
[power on/off normally]:na
[do common repository/branch inspection]:na
[is there dependence]:na
[confirm dependent commit]:na
[board]:na
[test case]:na
[reviewers]:na
commit_template_version:v1
Change-Id: I74a27a7a5571d87a45855a32d40bf8c9186a9a02
---
diff --git a/arch/arm64/boot/dts/sprd/lcd/lcd_ili9881c_truly_mipi_wxga.dtsi b/arch/arm64/boot/dts/sprd/lcd/lcd_ili9881c_truly_mipi_wxga.dtsi
new file mode 100755
index 0000000..23eb2a8
--- /dev/null
+++ b/arch/arm64/boot/dts/sprd/lcd/lcd_ili9881c_truly_mipi_wxga.dtsi
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Unisoc ili9881c Truly LCD config DTS file
+ *
+ * Copyright (C) 2021, Unisoc Inc.
+ */
+/ {
+ fragment {
+ target-path = "/";
+ __overlay__ {
+ lcds {
+ lcd_ili9881c_truly_mipi_wxga: lcd_ili9881c_truly_mipi_wxga {
+
+ sprd,dsi-work-mode = <1>;
+ sprd,dsi-lane-number = <2>;
+ sprd,dsi-color-format = "rgb888";
+
+ sprd,phy-bit-clock = <921600>;
+ sprd,phy-escape-clock = <20000>;
+
+ sprd,width-mm = <68>;
+ sprd,height-mm = <121>;
+
+ sprd,esd-check-enable = <0>;
+ sprd,esd-check-mode = <3>;
+ sprd,esd-check-period = <1000>;
+ sprd,esd-check-register = <0x0A>;
+ sprd,esd-check-value = <0x9C>;
+
+ sprd,mipi-port = <1>;
+
+ sprd,reset-on-sequence = <1 5>, <0 5>, <1 20>;
+ sprd,reset-off-sequence = <0 20>;
+
+ sprd,initial-command = [
+ 39 00 00 04 FF 98 81 03
+ 39 00 00 04 FF 98 81 03
+ 23 00 00 02 01 00
+ 23 00 00 02 02 00
+ 23 00 00 02 03 73
+ 23 00 00 02 04 13
+ 23 00 00 02 05 00
+ 23 00 00 02 06 0A
+ 23 00 00 02 07 05
+ 23 00 00 02 08 00
+ 23 00 00 02 09 28
+ 23 00 00 02 0a 00
+ 23 00 00 02 0b 00
+ 23 00 00 02 0c 00
+ 23 00 00 02 0d 28
+ 23 00 00 02 0e 00
+ 23 00 00 02 0f 28
+ 23 00 00 02 10 28
+ 23 00 00 02 11 00
+ 23 00 00 02 12 00
+ 23 00 00 02 13 00
+ 23 00 00 02 14 00
+ 23 00 00 02 15 00
+ 23 00 00 02 16 00
+ 23 00 00 02 17 00
+ 23 00 00 02 18 00
+ 23 00 00 02 19 00
+ 23 00 00 02 1a 00
+ 23 00 00 02 1b 00
+ 23 00 00 02 1c 00
+ 23 00 00 02 1d 00
+ 23 00 00 02 1e 40
+ 23 00 00 02 1f 80
+ 23 00 00 02 20 06
+ 23 00 00 02 21 01
+ 23 00 00 02 22 00
+ 23 00 00 02 23 00
+ 23 00 00 02 24 00
+ 23 00 00 02 25 00
+ 23 00 00 02 26 00
+ 23 00 00 02 27 00
+ 23 00 00 02 28 33
+ 23 00 00 02 29 33
+ 23 00 00 02 2a 00
+ 23 00 00 02 2b 00
+ 23 00 00 02 2c 04
+ 23 00 00 02 2d 04
+ 23 00 00 02 2e 05
+ 23 00 00 02 2f 05
+ 23 00 00 02 30 00
+ 23 00 00 02 31 00
+ 23 00 00 02 32 31
+ 23 00 00 02 33 00
+ 23 00 00 02 34 00
+ 23 00 00 02 35 0A
+ 23 00 00 02 36 00
+ 23 00 00 02 37 08
+ 23 00 00 02 38 00
+ 23 00 00 02 39 00
+ 23 00 00 02 3a 00
+ 23 00 00 02 3b 00
+ 23 00 00 02 3c 00
+ 23 00 00 02 3d 00
+ 23 00 00 02 3e 00
+ 23 00 00 02 3f 00
+ 23 00 00 02 40 00
+ 23 00 00 02 41 00
+ 23 00 00 02 42 00
+ 23 00 00 02 43 08
+ 23 00 00 02 44 00
+ 23 00 00 02 50 01
+ 23 00 00 02 51 23
+ 23 00 00 02 52 44
+ 23 00 00 02 53 67
+ 23 00 00 02 54 89
+ 23 00 00 02 55 ab
+ 23 00 00 02 56 01
+ 23 00 00 02 57 23
+ 23 00 00 02 58 45
+ 23 00 00 02 59 67
+ 23 00 00 02 5a 89
+ 23 00 00 02 5b ab
+ 23 00 00 02 5c cd
+ 23 00 00 02 5d ef
+ 23 00 00 02 5e 11
+ 23 00 00 02 5f 02
+ 23 00 00 02 60 08
+ 23 00 00 02 61 0E
+ 23 00 00 02 62 0F
+ 23 00 00 02 63 0C
+ 23 00 00 02 64 0D
+ 23 00 00 02 65 17
+ 23 00 00 02 66 01
+ 23 00 00 02 67 01
+ 23 00 00 02 68 02
+ 23 00 00 02 69 02
+ 23 00 00 02 6a 00
+ 23 00 00 02 6b 00
+ 23 00 00 02 6c 02
+ 23 00 00 02 6d 02
+ 23 00 00 02 6e 16
+ 23 00 00 02 6f 16
+ 23 00 00 02 70 06
+ 23 00 00 02 71 06
+ 23 00 00 02 72 07
+ 23 00 00 02 73 07
+ 23 00 00 02 74 02
+ 23 00 00 02 75 02
+ 23 00 00 02 76 08
+ 23 00 00 02 77 0E
+ 23 00 00 02 78 0F
+ 23 00 00 02 79 0C
+ 23 00 00 02 7a 0D
+ 23 00 00 02 7b 17
+ 23 00 00 02 7c 01
+ 23 00 00 02 7d 01
+ 23 00 00 02 7e 02
+ 23 00 00 02 7f 02
+ 23 00 00 02 80 00
+ 23 00 00 02 81 00
+ 23 00 00 02 82 02
+ 23 00 00 02 83 02
+ 23 00 00 02 84 16
+ 23 00 00 02 85 16
+ 23 00 00 02 86 06
+ 23 00 00 02 87 06
+ 23 00 00 02 88 07
+ 23 00 00 02 89 07
+ 23 00 00 02 8A 02
+ 39 00 00 04 FF 98 81 04
+ 23 00 00 02 6E 1A
+ 23 00 00 02 6F 37
+ 23 00 00 02 3B C0
+ 23 00 00 02 8D 1F
+ 23 00 00 02 87 BA
+ 23 00 00 02 B2 D1
+ 23 00 00 02 88 0B
+ 23 00 00 02 38 01
+ 23 00 00 02 39 00
+ 23 00 00 02 B5 02
+ 23 00 00 02 31 25
+ 23 00 00 02 3B 98
+ 39 00 00 04 FF 98 81 01
+ 23 00 00 02 22 0A
+ 23 00 00 02 31 00
+ 23 00 00 02 53 62
+ 23 00 00 02 55 7B
+ 23 00 00 02 50 9E
+ 23 00 00 02 51 99
+ 23 00 00 02 60 06
+ 23 00 00 02 62 20
+ 23 00 00 02 B7 03
+ 23 00 00 02 A0 00
+ 23 00 00 02 A1 17
+ 23 00 00 02 A2 26
+ 23 00 00 02 A3 13
+ 23 00 00 02 A4 16
+ 23 00 00 02 A5 29
+ 23 00 00 02 A6 1E
+ 23 00 00 02 A7 1F
+ 23 00 00 02 A8 8B
+ 23 00 00 02 A9 1D
+ 23 00 00 02 AA 2A
+ 23 00 00 02 AB 7B
+ 23 00 00 02 AC 1A
+ 23 00 00 02 AD 19
+ 23 00 00 02 AE 4E
+ 23 00 00 02 AF 24
+ 23 00 00 02 B0 29
+ 23 00 00 02 B1 4F
+ 23 00 00 02 B2 5C
+ 23 00 00 02 B3 23
+ 23 00 00 02 C0 00
+ 23 00 00 02 C1 17
+ 23 00 00 02 C2 26
+ 23 00 00 02 C3 13
+ 23 00 00 02 C4 16
+ 23 00 00 02 C5 29
+ 23 00 00 02 C6 1E
+ 23 00 00 02 C7 1F
+ 23 00 00 02 C8 8B
+ 23 00 00 02 C9 1D
+ 23 00 00 02 CA 2A
+ 23 00 00 02 CB 7B
+ 23 00 00 02 CC 1A
+ 23 00 00 02 CD 19
+ 23 00 00 02 CE 4E
+ 23 00 00 02 CF 24
+ 23 00 00 02 D0 29
+ 23 00 00 02 D1 4F
+ 23 00 00 02 D2 5C
+ 23 00 00 02 D3 23
+ 39 00 00 04 FF 98 81 00
+ 23 78 00 02 11 00
+ 23 32 00 02 29 00
+ ];
+ sprd,sleep-in-command = [
+ 13 0A 00 01 28
+ 13 78 00 01 10
+ ];
+ sprd,sleep-out-command = [
+ 13 78 00 01 11
+ 13 64 00 01 29
+ ];
+
+ display-timings {
+ native-mode = <&ili9881c_truly_timing0>;
+
+ ili9881c_truly_timing0: timing0 {
+ clock-frequency = <64000000>;
+ hactive = <800>;
+ vactive = <1280>;
+ hback-porch = <8>;
+ hfront-porch = <24>;
+ vback-porch = <8>;
+ vfront-porch = <24>;
+ hsync-len = <18>;
+ vsync-len = <4>;
+ };
+ };
+ };
+ };
+ };
+ };
+};
+
diff --git a/arch/arm64/boot/dts/sprd/qogirn6pro.dtsi b/arch/arm64/boot/dts/sprd/qogirn6pro.dtsi
index 67743bc..a70019b 100644
--- a/arch/arm64/boot/dts/sprd/qogirn6pro.dtsi
+++ b/arch/arm64/boot/dts/sprd/qogirn6pro.dtsi
@@ -755,11 +755,23 @@
#power-domain-cells = <0>;
power-domains = <&vpu_pd_top>;
- dpu_port: port {
- dpu_out: endpoint {
- remote-endpoint = <&dsi_in>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpu_port: port@0 {
+ reg = <0>;
+ dpu0_out: endpoint {
+ remote-endpoint = <&dsi_in>;
};
};
+
+ dpu_port1: port@1 {
+ reg = <1>;
+ dpu_s_out: endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+
};
iommu_dispc: iommu@31001800 {
@@ -820,9 +832,8 @@
reg = <0x0 0x31300000 0x0 0x1000>;
reset-syscon = <&dpu_vsp_apb_regs REG_DPU_VSP_APB_RST
MASK_DPU_VSP_APB_DSI0_SOFT_RST>;
-
- interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
@@ -843,7 +854,42 @@
port@1 {
reg = <1>;
dsi_in: endpoint {
- remote-endpoint = <&dpu_out>;
+ remote-endpoint = <&dpu0_out>;
+ };
+ };
+ };
+ };
+
+ dsi1: dsi1@31400000 {
+ compatible = "sprd,qogirn6pro-s-dsi-host";
+ reg = <0x0 0x31400000 0x0 0x1000>;
+ reset-syscon = <&dpu_vsp_apb_regs REG_DPU_VSP_APB_RST
+ MASK_DPU_VSP_APB_DSI1_SOFT_RST>;
+ enable-syscon = <&dpu_vsp_apb_regs REG_DPU_VSP_APB_EN
+ MASK_DPU_VSP_APB_DSI1_SOFT_RST>;
+ interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+
+ status = "disabled";
+
+ #power-domain-cells = <0>;
+ power-domains = <&vpu_pd_top>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi1_out: endpoint {
+ remote-endpoint = <&dphy1_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi1_in: endpoint {
+ remote-endpoint = <&dpu_s_out>;
};
};
};
@@ -883,6 +929,39 @@
};
};
};
+ dphy1: dphy1 {
+ compatible = "sprd,qogirn6pro-s-dsi-phy";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x31400000 0x0 0x1000>;
+ enable-syscon = <&dpu_vsp_apb_regs REG_DPU_VSP_APB_MISC_CKG_EB
+ (MASK_DPU_VSP_APB_DPHY1_REF_CKG_EN |
+ MASK_DPU_VSP_APB_DPHY1_CFG_CKG_EN)>;
+ power-syscon = <&pmu_apb_regs REG_PMU_APB_RF_ANALOG_PHY_PD_CFG MASK_PMU_APB_RF_DSI0_PD_REG>;
+ aod_mode-syscon = <&aon_apb_regs REG_AON_APB_MIPI_DSI8_CTRL
+ (MASK_AON_APB_MIPI_DSI_8LANE_DSI_AOD_EN_M |
+ MASK_AON_APB_MIPI_DSI_8LANE_DSI_AOD_MOD_M)>;
+ aod_pd-syscon = <&aon_apb_regs REG_AON_APB_MIPI_DSI8_CTRL
+ MASK_AON_APB_MIPI_DSI_8LANE_DSI_AOD_PD_M>;
+ status = "disabled";
+ sprd,mipi-drive-capability = <7>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ dphy1_out: endpoint {
+ remote-endpoint = <&panel1_in>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ dphy1_in: endpoint {
+ remote-endpoint = <&dsi1_out>;
+ };
+ };
+ };
+ };
};
mm {
diff --git a/arch/arm64/boot/dts/sprd/uis7885-mach.dtsi b/arch/arm64/boot/dts/sprd/uis7885-mach.dtsi
index 1d70d82..211143e 100755
--- a/arch/arm64/boot/dts/sprd/uis7885-mach.dtsi
+++ b/arch/arm64/boot/dts/sprd/uis7885-mach.dtsi
@@ -878,7 +878,7 @@
display-subsystem {
compatible = "sprd,display-subsystem";
- ports = <&dpu_port>;
+ ports = <&dpu_port>,<&dpu_port1>;
/*gsp = <&gsp0>, <&gsp1>;*/
};
@@ -916,6 +916,25 @@
};
};
+&dsi1 {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel1: panel1 {
+ compatible = "sprd,generic-mipi-panel";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ port@1 {
+ reg = <1>;
+ panel1_in: endpoint {
+ remote-endpoint = <&dphy1_out>;
+ };
+ };
+ };
+};
&dpu1 {
status = "okay";
@@ -941,6 +960,10 @@
status = "okay";
};
+&dphy1 {
+ status = "okay";
+};
+
&jpg {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/sprd/uis7885.dtsi b/arch/arm64/boot/dts/sprd/uis7885.dtsi
index b16a9bb..1f5ad5a 100755
--- a/arch/arm64/boot/dts/sprd/uis7885.dtsi
+++ b/arch/arm64/boot/dts/sprd/uis7885.dtsi
@@ -1024,6 +1024,19 @@
<&dpu_vsp_gate CLK_DPU_EB>;
};
+&dsi1 {
+ clock-names = "clk_dsi1_eb",
+ "clk_dpu_dpi",
+ "clk_src_384m",
+ "clk_dpuvsp_eb",
+ "clk_dpuvsp_disp_eb";
+ clocks = <&dpu_vsp_gate CLK_DSI1_EB>,
+ <&dpu_vsp_clk CLK_DISPC0_DPI>,
+ <&g5l_pll CLK_TGPLL_384M>,
+ <&aonapb_gate CLK_DPU_VSP_EB>,
+ <&dpu_vsp_gate CLK_DPU_EB>;
+};
+
&gsp0_core0 {
clock-names = "clk_src_512m",
"clk_gsp0_eb",
diff --git a/arch/arm64/boot/dts/sprd/ums9620-mach.dtsi b/arch/arm64/boot/dts/sprd/ums9620-mach.dtsi
index 514c124..32ec777 100644
--- a/arch/arm64/boot/dts/sprd/ums9620-mach.dtsi
+++ b/arch/arm64/boot/dts/sprd/ums9620-mach.dtsi
@@ -912,6 +912,25 @@
};
};
+&dsi1 {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel1: panel1 {
+ compatible = "sprd,generic-mipi-panel";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ port@1 {
+ reg = <1>;
+ panel1_in: endpoint {
+ remote-endpoint = <&dphy1_out>;
+ };
+ };
+ };
+};
&dpu1 {
status = "okay";
@@ -937,6 +956,10 @@
status = "okay";
};
+&dphy1 {
+ status = "okay";
+};
+
&jpg {
status = "okay";
};
diff --git a/drivers/gpu/drm/sprd/disp_lib.c b/drivers/gpu/drm/sprd/disp_lib.c
index 02711a7..4c0f9db 100644
--- a/drivers/gpu/drm/sprd/disp_lib.c
+++ b/drivers/gpu/drm/sprd/disp_lib.c
@@ -199,9 +199,9 @@
return sprd_disp_pipe_get_by_port(dev, 1);
}
-struct device *sprd_disp_pipe_get_output(struct device *dev)
+struct device *sprd_disp_pipe_get_output(struct device *dev,u32 swtich_port)
{
- return sprd_disp_pipe_get_by_port(dev, 0);
+ return sprd_disp_pipe_get_by_port(dev, swtich_port);
}
MODULE_AUTHOR("Leon He <[email protected]>");
diff --git a/drivers/gpu/drm/sprd/disp_lib.h b/drivers/gpu/drm/sprd/disp_lib.h
index 2f31dcd..52d454d 100644
--- a/drivers/gpu/drm/sprd/disp_lib.h
+++ b/drivers/gpu/drm/sprd/disp_lib.h
@@ -24,6 +24,6 @@
struct device *sprd_disp_pipe_get_by_port(struct device *dev, int port);
struct device *sprd_disp_pipe_get_input(struct device *dev);
-struct device *sprd_disp_pipe_get_output(struct device *dev);
+struct device *sprd_disp_pipe_get_output(struct device *dev,u32 port);
#endif /* _DISP_LIB_H_ */
diff --git a/drivers/gpu/drm/sprd/dpu/dpu_r6p0.c b/drivers/gpu/drm/sprd/dpu/dpu_r6p0.c
index aec1598..4327dfc9 100644
--- a/drivers/gpu/drm/sprd/dpu/dpu_r6p0.c
+++ b/drivers/gpu/drm/sprd/dpu/dpu_r6p0.c
@@ -1943,10 +1943,16 @@
{
struct sprd_dpu *dpu = container_of(ctx, struct sprd_dpu, ctx);
struct sprd_dsi *dsi = dpu->dsi;
- struct sprd_panel *panel = container_of(dsi->panel, struct sprd_panel, base);
+ //struct sprd_panel *panel = container_of(dsi->panel, struct sprd_panel, base);
+ struct sprd_panel *panel;
u32 int_mask = 0;
u32 reg_val;
+ if (!dsi || !dsi->panel) {
+ pr_err("dsi or panel is NULL, skip dpu_dpi_init\n");
+ return;
+ }
+ panel = container_of(dsi->panel, struct sprd_panel, base);
if (ctx->if_type == SPRD_DPU_IF_DPI) {
/* use dpi as interface */
DPU_REG_CLR(ctx->base + REG_DPU_CFG0, BIT_DPU_IF_EDPI);
@@ -1954,6 +1960,9 @@
/* enable Halt function for SPRD DSI */
DPU_REG_SET(ctx->base + REG_DPI_CTRL, BIT_DPU_DPI_HALT_EN);
+ if(panel->info.mipi_port == SPRD_DSI_1)
+ DPU_REG_SET(ctx->base + REG_DPI_CTRL, BIT_DPU_INT_TE);
+
if (ctx->is_single_run)
DPU_REG_SET(ctx->base + REG_DPU_CTRL, BIT(0));
diff --git a/drivers/gpu/drm/sprd/dsi/sprd_dsi_api.c b/drivers/gpu/drm/sprd/dsi/sprd_dsi_api.c
index d7ab66e..a2d2f73 100644
--- a/drivers/gpu/drm/sprd/dsi/sprd_dsi_api.c
+++ b/drivers/gpu/drm/sprd/dsi/sprd_dsi_api.c
@@ -191,8 +191,10 @@
data_hs2lp = ns_to_cycle(ctx->data_hs2lp, ctx->byte_clk);
data_lp2hs = ns_to_cycle(ctx->data_lp2hs, ctx->byte_clk);
- clk_hs2lp = ns_to_cycle(ctx->clk_hs2lp, ctx->byte_clk);
- clk_lp2hs = ns_to_cycle(ctx->clk_lp2hs, ctx->byte_clk);
+ //clk_hs2lp = ns_to_cycle(ctx->clk_hs2lp, ctx->byte_clk);
+ //clk_lp2hs = ns_to_cycle(ctx->clk_lp2hs, ctx->byte_clk);
+ clk_hs2lp = ctx->clk_hs2lp;
+ clk_lp2hs = ctx->clk_lp2hs;
dsi_hal_datalane_hs2lp_config(dsi, data_hs2lp);
dsi_hal_datalane_lp2hs_config(dsi, data_lp2hs);
dsi_hal_clklane_hs2lp_config(dsi, clk_hs2lp);
diff --git a/drivers/gpu/drm/sprd/qogirn6pro/global_dphy.c b/drivers/gpu/drm/sprd/qogirn6pro/global_dphy.c
index 78b1d39..77fe120 100755
--- a/drivers/gpu/drm/sprd/qogirn6pro/global_dphy.c
+++ b/drivers/gpu/drm/sprd/qogirn6pro/global_dphy.c
@@ -9,9 +9,15 @@
#include <linux/slab.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
-
+#include <linux/io.h>
#include "sprd_dphy.h"
+#define Analog_Reg_G3_BASE 0x64314000UL
+#define Analog_Reg_G3_SIZE 0x100
+#define REG_SEL_CFG_0 0x64
+#define REG_DBG_SEL_MASK 0xff
+static void __iomem *analog_reg_g3_base;
+
static struct dphy_glb_context {
unsigned int ctrl_reg;
unsigned int ctrl_mask;
@@ -83,6 +89,15 @@
s_ctx_power.ctrl_reg = syscon_args[0];
s_ctx_power.ctrl_mask = syscon_args[1];
}
+ if (!analog_reg_g3_base) {
+ analog_reg_g3_base = ioremap_nocache(Analog_Reg_G3_BASE,
+ Analog_Reg_G3_SIZE);
+ if (!analog_reg_g3_base)
+ pr_err("ioremap analog_reg_g3 (0x%lx) failed\n",
+ Analog_Reg_G3_BASE);
+ else
+ pr_info("analog_reg_g3 base mapped for mipi dsi workaround\n");
+ }
return 0;
}
@@ -107,10 +122,28 @@
static void dphy_s_glb_enable(struct dphy_context *ctx)
{
+ void __iomem *reg;
+ u32 val;
+
+ if (!analog_reg_g3_base) {
+ pr_err("force DSI analog mmio not mapped\n");
+ return;
+ }
+
+ reg = analog_reg_g3_base + REG_SEL_CFG_0;
+
+ val = readl_relaxed(reg);
+ val = val & ~REG_DBG_SEL_MASK;
+ writel_relaxed(val, reg);
+
+ /* read-back flush, then re-read to confirm */
+ val = readl_relaxed(reg);
+
regmap_update_bits(s_ctx_enable.regmap,
s_ctx_enable.ctrl_reg,
s_ctx_enable.ctrl_mask,
s_ctx_enable.ctrl_mask);
+ pr_info("drm dphy_s_glb_enable\n");
}
static void dphy_glb_disable(struct dphy_context *ctx)
@@ -159,6 +192,7 @@
static void dphy_s_power_domain(struct dphy_context *ctx, int enable)
{
+ pr_info("dphy_s_power_domain enable=%d\n",enable);
if (enable) {
regmap_update_bits(s_ctx_power.regmap,
s_ctx_power.ctrl_reg,
diff --git a/drivers/gpu/drm/sprd/qogirn6pro/global_dpu.c b/drivers/gpu/drm/sprd/qogirn6pro/global_dpu.c
index b43ccce..d5e1094 100755
--- a/drivers/gpu/drm/sprd/qogirn6pro/global_dpu.c
+++ b/drivers/gpu/drm/sprd/qogirn6pro/global_dpu.c
@@ -13,6 +13,14 @@
#include "sprd_dpu.h"
+/* DPU_VSP clock-controller (ums9620 dpu_vsp_clk) register block @ 0x30110000. */
+#define DPU_VSP_CLK_BASE 0x30110000UL
+#define DPU_VSP_CLK_SIZE 0x3000
+/* dispc0_dpi pixel-clock divider: offset 0x78, bits[3:0] (value 3 = div-by-4). */
+#define REG_DISPC0_DPI_DIV 0x78
+#define REG_DISPC0_DPI_DIV_MASK 0xf
+static void __iomem *dpu_vsp_clk_base;
+
static struct clk *clk_dpuvsp_eb;
static struct clk *clk_dpuvsp_disp_eb;
static struct clk *clk_master_div6_eb;
@@ -155,6 +163,20 @@
clk_ctx->clk_dpu_dpi = NULL;
}
+ /* Map the DPU_VSP clock-controller MMIO so the DPI-divider workaround
+ * can write register 0x30110078 directly. pr_err on failure - the ioremap
+ * must succeed or the workaround cannot fire at all.
+ */
+ if (!dpu_vsp_clk_base) {
+ dpu_vsp_clk_base = ioremap_nocache(DPU_VSP_CLK_BASE,
+ DPU_VSP_CLK_SIZE);
+ if (!dpu_vsp_clk_base)
+ pr_err("ioremap dpu_vsp_clk (0x%lx) failed\n",
+ DPU_VSP_CLK_BASE);
+ else
+ pr_info("dpu_vsp_clk base mapped for dpi-div workaround\n");
+ }
+
return 0;
}
@@ -188,6 +210,41 @@
return NULL;
}
}
+
+/*
+ * Most direct path to force the dispc0_dpi pixel-clock divider to 3
+ * (divide-by-4): write bits[3:0] of register 0x30110078 (= DPU_VSP clock
+ * controller base 0x30110000 + offset 0x78). This bypasses the CCF and writes
+ * the MMIO register directly; the value is read back to confirm it latched.
+ * Returns the final divider value (should be 3 on success) or a negative errno.
+ */
+static int dpu_force_dpi_div3(void)
+{
+ void __iomem *reg;
+ u32 val;
+
+ if (!dpu_vsp_clk_base) {
+ pr_err("force dpi div=3: clk mmio not mapped\n");
+ return -ENXIO;
+ }
+
+ reg = dpu_vsp_clk_base + REG_DISPC0_DPI_DIV;
+
+ val = readl_relaxed(reg);
+ val = (val & ~REG_DISPC0_DPI_DIV_MASK) | 3;
+ writel_relaxed(val, reg);
+
+ /* read-back flush, then re-read to confirm */
+ val = readl_relaxed(reg);
+ if ((val & REG_DISPC0_DPI_DIV_MASK) != 3) {
+ pr_err("force dpi div=3 (0x30110078) failed, readback=0x%x\n", val);
+ return -EIO;
+ }
+
+ pr_info("force dpi div=3 (0x30110078) ok, reg=0x%x\n", val);
+ return 0;
+}
+
static int dpu_clk_init(struct dpu_context *ctx)
{
int ret;
@@ -229,6 +286,17 @@
ret = clk_set_rate(clk_ctx->clk_dpu_dpi, ctx->vm.pixelclock);
if (ret)
pr_err("dpu update dpi clk rate failed\n");
+
+ /* Workaround: on resume (suspend->on), the DPI pixel-clock divider
+ * at 0x30110078 (dispc0_dpi div, bits[3:0]) is not re-applied and
+ * the panel lights up black. Force divider value 3 (div-by-4) by
+ * writing the MMIO register directly (most-direct path). Only acted
+ * upon when flagged from the resume path.
+ */
+ if (ctx->dpi_div_force3) {
+ ctx->dpi_div_force3 = false;
+ dpu_force_dpi_div3();
+ }
}
return ret;
diff --git a/drivers/gpu/drm/sprd/qogirn6pro/global_dsi.c b/drivers/gpu/drm/sprd/qogirn6pro/global_dsi.c
index 8eee971..f655b77 100755
--- a/drivers/gpu/drm/sprd/qogirn6pro/global_dsi.c
+++ b/drivers/gpu/drm/sprd/qogirn6pro/global_dsi.c
@@ -22,7 +22,7 @@
unsigned int ctrl_reg;
unsigned int ctrl_mask;
struct regmap *regmap;
-} ctx_reset, s_ctx_reset;
+} ctx_reset, s_ctx_reset, s_ctx_enable;
static int dsi_glb_parse_dt(struct dsi_context *ctx,
struct device_node *np)
@@ -82,7 +82,6 @@
unsigned int syscon_args[2];
pr_info("%s enter\n", __func__);
-
clk_dsi1_eb =
of_clk_get_by_name(np, "clk_dsi1_eb");
if (IS_ERR(clk_dsi1_eb)) {
@@ -90,14 +89,48 @@
clk_dsi1_eb = NULL;
}
- s_ctx_reset.regmap = syscon_regmap_lookup_by_phandle_args(np, "reset", 2,syscon_args);
+ clk_dpu_dpi =
+ of_clk_get_by_name(np, "clk_dpu_dpi");
+ if (IS_ERR(clk_dpu_dpi)) {
+ pr_warn("read clk_dpu_dpi failed\n");
+ clk_dpu_dpi = NULL;
+ }
+
+ clk_src_384m =
+ of_clk_get_by_name(np, "clk_src_384m");
+ if (IS_ERR(clk_src_384m)) {
+ pr_warn("read clk_src_384m failed\n");
+ clk_src_384m = NULL;
+ }
+
+ clk_dpuvsp_eb =
+ of_clk_get_by_name(np, "clk_dpuvsp_eb");
+ if (IS_ERR(clk_dpuvsp_eb)) {
+ pr_warn("read clk_dpuvsp_eb failed\n");
+ clk_dpuvsp_eb = NULL;
+ }
+
+ clk_dpuvsp_disp_eb =
+ of_clk_get_by_name(np, "clk_dpuvsp_disp_eb");
+ if (IS_ERR(clk_dpuvsp_disp_eb)) {
+ pr_warn("read clk_dpuvsp_disp_eb failed\n");
+ clk_dpuvsp_disp_eb = NULL;
+ }
+
+ s_ctx_reset.regmap = syscon_regmap_lookup_by_phandle_args(np, "reset-syscon", 2,syscon_args);
if (IS_ERR(s_ctx_reset.regmap)) {
pr_warn("failed to map dsi glb reg\n");
} else {
s_ctx_reset.ctrl_reg = syscon_args[0];
s_ctx_reset.ctrl_mask = syscon_args[1];
}
-
+ s_ctx_enable.regmap = syscon_regmap_lookup_by_phandle_args(np, "enable-syscon", 2,syscon_args);
+ if (IS_ERR(s_ctx_enable.regmap)) {
+ pr_warn("failed to map dsi glb enable reg\n");
+ } else {
+ s_ctx_enable.ctrl_reg = syscon_args[0];
+ s_ctx_enable.ctrl_mask = syscon_args[1];
+ }
return 0;
}
@@ -143,10 +176,28 @@
static void dsi_s_glb_enable(struct dsi_context *ctx)
{
int ret;
+ pr_info("drm dsi_s_glb_enable\n");
+ if (!ctx->is_esd_rst) {
+ ret = clk_prepare_enable(clk_dpuvsp_eb);
+ if (ret) {
+ pr_err("enable clk_dpuvsp_eb failed!\n");
+ return;
+ }
+ ret = clk_prepare_enable(clk_dpuvsp_disp_eb);
+ if (ret) {
+ pr_err("enable clk_dpuvsp_disp_eb failed!\n");
+ return;
+ }
+ }
ret = clk_prepare_enable(clk_dsi1_eb);
if (ret)
pr_err("enable clk_dsi1_eb failed!\n");
+
+ regmap_update_bits(s_ctx_enable.regmap,
+ s_ctx_enable.ctrl_reg,
+ s_ctx_enable.ctrl_mask,
+ s_ctx_enable.ctrl_mask);
}
static void dsi_glb_disable(struct dsi_context *ctx)
@@ -161,7 +212,16 @@
static void dsi_s_glb_disable(struct dsi_context *ctx)
{
- clk_disable_unprepare(clk_dsi1_eb);
+ regmap_update_bits(s_ctx_enable.regmap,
+ s_ctx_enable.ctrl_reg,
+ s_ctx_enable.ctrl_mask,
+ (unsigned int)(~s_ctx_enable.ctrl_mask));
+ if (ctx->clk_dpi_384m) {
+ dsi_core_clk_switch(ctx);
+ ctx->clk_dpi_384m = false;
+ } else {
+ clk_disable_unprepare(clk_dsi1_eb);
+ }
}
static void dsi_reset(struct dsi_context *ctx)
diff --git a/drivers/gpu/drm/sprd/sprd_dphy.c b/drivers/gpu/drm/sprd/sprd_dphy.c
index a069d0f..d2c3380 100644
--- a/drivers/gpu/drm/sprd/sprd_dphy.c
+++ b/drivers/gpu/drm/sprd/sprd_dphy.c
@@ -134,7 +134,13 @@
dphy->dev.class = display_class;
dphy->dev.parent = parent;
dphy->dev.of_node = parent->of_node;
- dev_set_name(&dphy->dev, "dphy0");
+ if (of_device_is_compatible(parent->of_node, "sprd,qogirn6pro-s-dsi-phy")){
+ dev_set_name(&dphy->dev, "dphy1");
+ }
+ else{
+ dev_set_name(&dphy->dev, "dphy0");
+ }
+
dev_set_drvdata(&dphy->dev, dphy);
ret = device_register(&dphy->dev);
@@ -236,6 +242,12 @@
.glb = &qogirn6pro_dphy_glb_ops,
};
+static const struct sprd_dphy_ops qogirn6pro_s_dphy = {
+ .ppi = &dsi_ctrl_ppi_ops,
+ .pll = &sharkl5_dphy_pll_ops,
+ .glb = &qogirn6pro_dphy_s_glb_ops,
+};
+
static const struct of_device_id dphy_match_table[] = {
{ .compatible = "sprd,sharkle-dsi-phy",
.data = &sharkle_dphy },
@@ -251,6 +263,8 @@
.data = &qogirl6_dphy },
{ .compatible = "sprd,qogirn6pro-dsi-phy",
.data = &qogirn6pro_dphy },
+ { .compatible = "sprd,qogirn6pro-s-dsi-phy",
+ .data = &qogirn6pro_s_dphy },
{ /* sentinel */ },
};
diff --git a/drivers/gpu/drm/sprd/sprd_dphy.h b/drivers/gpu/drm/sprd/sprd_dphy.h
index 281a26d..9e7e559 100644
--- a/drivers/gpu/drm/sprd/sprd_dphy.h
+++ b/drivers/gpu/drm/sprd/sprd_dphy.h
@@ -102,4 +102,5 @@
extern const struct dphy_glb_ops sharkl5pro_dphy_glb_ops;
extern const struct dphy_glb_ops qogirl6_dphy_glb_ops;
extern const struct dphy_glb_ops qogirn6pro_dphy_glb_ops;
+extern const struct dphy_glb_ops qogirn6pro_dphy_s_glb_ops;
#endif /* _SPRD_DPHY_H_ */
diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
old mode 100644
new mode 100755
index 819c839..ac2649b
--- a/drivers/gpu/drm/sprd/sprd_dpu.c
+++ b/drivers/gpu/drm/sprd/sprd_dpu.c
@@ -199,8 +199,8 @@
DRM_INFO("%s()\n", __func__);
#ifdef CONFIG_DRM_SPRD_DSI
- if (!dpu || !dpu->dsi) {
- DRM_ERROR("dpu or dsi ptr is NULL\n");
+ if (!dpu || !dpu->dsi || !dpu->dsi->panel) {
+ DRM_ERROR("dpu or dsi or panel ptr is NULL\n");
return;
}
@@ -378,6 +378,18 @@
void sprd_dpu_resume(struct sprd_dpu *dpu)
{
+ struct dpu_context *ctx = &dpu->ctx;
+ u32 mipi_port = 0;
+ /* Flag the DPI-divider workaround: force value 3 at 0x30110078 on the
+ * next dpu_clk_init() to avoid black screen on wake.
+ */
+ if (dpu->dsi && dpu->dsi->panel) {
+ struct sprd_panel *panel = (struct sprd_panel *)container_of(dpu->dsi->panel, struct sprd_panel, base);
+ mipi_port = panel->info.mipi_port;
+ }
+ if(mipi_port == 1){
+ ctx->dpi_div_force3 = true;
+ }
sprd_dpu_enable(dpu);
enable_irq(dpu->ctx.irq);
sprd_iommu_restore(&dpu->dev);
@@ -463,11 +475,37 @@
{
struct device *dev;
struct sprd_dsi *dsi;
+ struct device_node *chosen, *lcd_node;
+ const char *bootargs, *p;
+ char lcd_name[64], lcd_path[80];
+ u32 mipi_port = 0;
DRM_INFO("dpu attach dsi\n");
- dev = sprd_disp_pipe_get_output(&dpu->dev);
+ /*
+ * Two DSI paths coexist: dsi0->dphy0 = HDMI/LT8912B, dsi1->dphy1 = MIPI panel.
+ * Pick the one selected by cmdline lcd_name: read "sprd,mipi-port" from
+ * /lcds/<lcd_name> and attach the dpu output port that maps to that dsi host
+ * (port0 -> dsi0, port1 -> dsi1). dpu->dsi is not assigned yet here, so the
+ * mipi-port must be read from the /lcds node itself, exactly like the panel
+ * driver parses cmdline.
+ */
+ chosen = of_find_node_by_path("/chosen");
+ if (chosen && !of_property_read_string(chosen, "bootargs", &bootargs)) {
+ p = strstr(bootargs, "lcd_name=");
+ if (p) {
+ sscanf(p, "lcd_name=%s", lcd_name);
+ snprintf(lcd_path, sizeof(lcd_path), "/lcds/%s", lcd_name);
+ lcd_node = of_find_node_by_path(lcd_path);
+ if (lcd_node) {
+ of_property_read_u32(lcd_node, "sprd,mipi-port", &mipi_port);
+ DRM_INFO("dpu attach dsi mipi_port=%d\n", mipi_port);
+ }
+ }
+ }
+
+ dev = sprd_disp_pipe_get_output(&dpu->dev, mipi_port);
if (!dev) {
- DRM_ERROR("dpu pipe get output failed\n");
+ DRM_ERROR("dpu pipe get output (port=%d) failed\n", mipi_port);
return NULL;
}
@@ -484,9 +522,11 @@
{
struct device *dev;
struct sprd_spi *spi;
+ struct sprd_panel *panel;
DRM_INFO("%s()\n", __func__);
- dev = sprd_disp_pipe_get_output(&dpu->dev);
+ panel = (struct sprd_panel *)container_of(dpu->dsi->panel, struct sprd_panel, base);
+ dev = sprd_disp_pipe_get_output(&dpu->dev,0);
if (!dev) {
DRM_ERROR("dpu pipe get output failed\n");
return NULL;
diff --git a/drivers/gpu/drm/sprd/sprd_dpu.h b/drivers/gpu/drm/sprd/sprd_dpu.h
old mode 100644
new mode 100755
index d8174be..7ffc889
--- a/drivers/gpu/drm/sprd/sprd_dpu.h
+++ b/drivers/gpu/drm/sprd/sprd_dpu.h
@@ -219,6 +219,13 @@
/* spi frame refresh parameters */
unsigned int flag_mask_refresh;
+
+ /* DPI pixel-clock divider force workaround.
+ * Set true from the resume path so dpu_clk_init() re-applies divider
+ * value 3 to register 0x30110078 (dispc0_dpi div, bits[3:0]) which is
+ * lost/missing on resume and causes a black screen on wake.
+ */
+ bool dpi_div_force3;
};
struct sprd_dpu_ops {
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
old mode 100644
new mode 100755
index 85e56d5..3eca9f0
--- a/drivers/gpu/drm/sprd/sprd_dsi.c
+++ b/drivers/gpu/drm/sprd/sprd_dsi.c
@@ -197,8 +197,9 @@
* its current contents indefinitely. If call sprd_dpu_run, background color will appear
* that will cause panel flickering. So we should call sprd_dpu_run when flip in edpi mode.
*/
- if (dsi->ctx.last_dpms != DRM_MODE_DPMS_SUSPEND)
+ if (dsi->ctx.last_dpms != DRM_MODE_DPMS_SUSPEND){
sprd_dpu_run(crtc->priv);
+ }
dsi->ctx.enabled = true;
dsi->ctx.last_dpms = dsi->ctx.dpms;
@@ -384,12 +385,21 @@
struct device *dev = dsi->host.dev;
struct device_node *child, *lcds_node;
struct drm_panel *panel;
+ struct sprd_panel *p;
/* search /lcds child node first */
lcds_node = of_find_node_by_path("/lcds");
for_each_child_of_node(lcds_node, child) {
panel = of_drm_find_panel(child);
if (!IS_ERR(panel)) {
+ p = container_of(panel, struct sprd_panel, base);
+ /*
+ * Two hosts can share the same /lcds of_node; only accept
+ * the panel attaching to THIS dsi host (its device parent
+ * is this host's dsi slave, set in sprd_dsi_host_attach).
+ */
+ if (dsi->slave && p->dev.parent != &dsi->slave->dev)
+ continue;
dsi->panel = panel;
return 0;
}
@@ -402,6 +412,9 @@
for_each_child_of_node(dev->of_node, child) {
panel = of_drm_find_panel(child);
if (!IS_ERR(panel)) {
+ p = container_of(panel, struct sprd_panel, base);
+ if (dsi->slave && p->dev.parent != &dsi->slave->dev)
+ continue;
dsi->panel = panel;
return 0;
}
@@ -415,7 +428,7 @@
{
struct device *dev;
- dev = sprd_disp_pipe_get_output(&dsi->dev);
+ dev = sprd_disp_pipe_get_output(&dsi->dev,0);
if (!dev)
return -ENODEV;
@@ -550,7 +563,10 @@
struct sprd_dsi *dsi = connector_to_dsi(connector);
DRM_INFO("%s()\n", __func__);
-
+ /* unused host in two-way pick-one has no panel bound */
+ if (!dsi->panel){
+ return 0;
+ }
return drm_panel_get_modes(dsi->panel);
}
@@ -796,7 +812,12 @@
dsi->dev.class = display_class;
dsi->dev.parent = parent;
dsi->dev.of_node = parent->of_node;
- dev_set_name(&dsi->dev, "dsi");
+ if (of_device_is_compatible(parent->of_node, "sprd,qogirn6pro-s-dsi-host")){
+ dev_set_name(&dsi->dev, "dsi1");
+ }
+ else{
+ dev_set_name(&dsi->dev, "dsi");
+ }
dev_set_drvdata(&dsi->dev, dsi);
ret = device_register(&dsi->dev);
@@ -840,7 +861,7 @@
ctx->clk_hs2lp = tmp;
else
ctx->clk_hs2lp = 4;
-
+
if (!of_property_read_u32(np, "sprd,clk-lp2hs", &tmp))
ctx->clk_lp2hs = tmp;
else
@@ -898,7 +919,12 @@
static const struct sprd_dsi_ops qogirn6pro_dsi = {
.core = &dsi_ctrl_r1p0_ops,
- .glb = &qogirn6pro_dsi_glb_ops
+ .glb = &qogirn6pro_dsi_glb_ops,
+};
+
+static const struct sprd_dsi_ops qogirn6pro_s_dsi = {
+ .core = &dsi_ctrl_r1p0_ops,
+ .glb = &qogirn6pro_dsi_s_glb_ops,
};
static const struct of_device_id dsi_match_table[] = {
@@ -916,6 +942,8 @@
.data = &qogirl6_dsi },
{ .compatible = "sprd,qogirn6pro-dsi-host",
.data = &qogirn6pro_dsi },
+ { .compatible = "sprd,qogirn6pro-s-dsi-host",
+ .data = &qogirn6pro_s_dsi },
{ /* sentinel */ },
};
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.h b/drivers/gpu/drm/sprd/sprd_dsi.h
index e5964b0..3b99cee 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.h
+++ b/drivers/gpu/drm/sprd/sprd_dsi.h
@@ -228,4 +228,5 @@
extern const struct dsi_glb_ops sharkl5pro_dsi_glb_ops;
extern const struct dsi_glb_ops qogirl6_dsi_glb_ops;
extern const struct dsi_glb_ops qogirn6pro_dsi_glb_ops;
+extern const struct dsi_glb_ops qogirn6pro_dsi_s_glb_ops;
#endif /* _SPRD_DSI_H_ */
diff --git a/drivers/gpu/drm/sprd/sprd_dsi_panel.c b/drivers/gpu/drm/sprd/sprd_dsi_panel.c
index 1772f84..6c36ae4 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi_panel.c
+++ b/drivers/gpu/drm/sprd/sprd_dsi_panel.c
@@ -75,14 +75,16 @@
mdelay(timing[i].delay);
}
}
-
+ if (panel->info.avdd_gpio) {
+ gpiod_direction_output(panel->info.avdd_gpio, 0);
+ mdelay(5);
+ }
if (panel->info.avee_gpio) {
gpiod_direction_output(panel->info.avee_gpio, 0);
mdelay(5);
}
-
- if (panel->info.avdd_gpio) {
- gpiod_direction_output(panel->info.avdd_gpio, 0);
+ if (panel->info.iovdd_gpio) {
+ gpiod_direction_output(panel->info.iovdd_gpio, 0);
mdelay(5);
}
@@ -100,17 +102,21 @@
DRM_INFO("%s()\n", __func__);
ret = regulator_enable(panel->supply);
- if (ret < 0)
+ if (ret < 0){
DRM_ERROR("enable lcd regulator failed\n");
-
+ }
+ if (panel->info.iovdd_gpio) {
+ gpiod_direction_output(panel->info.iovdd_gpio, 1);
+ mdelay(10);
+ }
if (panel->info.avdd_gpio) {
gpiod_direction_output(panel->info.avdd_gpio, 1);
- mdelay(5);
+ mdelay(20);
}
if (panel->info.avee_gpio) {
gpiod_direction_output(panel->info.avee_gpio, 1);
- mdelay(5);
+ mdelay(20);
}
if (panel->info.reset_gpio) {
@@ -477,6 +483,12 @@
static int sprd_panel_gpio_request(struct device *dev,
struct sprd_panel *panel)
{
+ panel->info.iovdd_gpio = devm_gpiod_get_optional(dev,
+ "iovdd", GPIOD_ASIS);
+ if (IS_ERR_OR_NULL(panel->info.iovdd_gpio))
+ DRM_WARN("can't get panel iovdd gpio: %ld\n",
+ PTR_ERR(panel->info.iovdd_gpio));
+
panel->info.avdd_gpio = devm_gpiod_get_optional(dev,
"avdd", GPIOD_ASIS);
if (IS_ERR_OR_NULL(panel->info.avdd_gpio))
@@ -868,6 +880,12 @@
else
info->mode.height_mm = 121;
+ rc = of_property_read_u32(lcd_node, "sprd,mipi-port", &val);
+ if (!rc)
+ info->mipi_port = val;
+ else
+ info->mipi_port = 0;
+
rc = of_property_read_u32(lcd_node, "sprd,esd-check-enable", &val);
if (!rc)
info->esd_check_en = val;
@@ -992,7 +1010,9 @@
panel->dev.class = display_class;
panel->dev.parent = parent;
panel->dev.of_node = panel->info.of_node;
- dev_set_name(&panel->dev, "panel0");
+ /* name per dsi host so two hosts never collide on -EEXIST */
+ dev_set_name(&panel->dev,
+ panel->info.mipi_port == SPRD_DSI_1 ? "panel1" : "panel0");
dev_set_drvdata(&panel->dev, panel);
return device_register(&panel->dev);
@@ -1042,7 +1062,23 @@
DRM_ERROR("parse panel info failed\n");
return ret;
}
+ /*
+ * Two-way pick-one: only the panel sitting on the dsi host whose physical
+ * id matches the /lcds "sprd,mipi-port" of the cmdline-selected lcd is
+ * allowed to register. The panel on the other host bails out before
+ * drm_panel_add()/mipi_dsi_attach(), so there is exactly one panel in the
+ * system on the correct dsi -- no dual-host collision (-EEXIST / shared
+ * of_node -> first-match-wins confusion in of_drm_find_panel).
+ */
+ {
+ bool host_is_dsi1 = of_device_is_compatible(slave->host->dev->of_node,"sprd,qogirn6pro-s-dsi-host");
+ u32 host_port = host_is_dsi1 ? SPRD_DSI_1 : SPRD_DSI_0;
+ if (host_port != panel->info.mipi_port) {
+ DRM_INFO("panel on dsi%d skipped, lcd_name selects dsi%d\n",host_port, panel->info.mipi_port);
+ return -ENODEV;
+ }
+ }
ret = sprd_panel_gpio_request(&slave->dev, panel);
if (ret) {
DRM_WARN("gpio is not ready, panel probe deferred\n");
diff --git a/drivers/gpu/drm/sprd/sprd_dsi_panel.h b/drivers/gpu/drm/sprd/sprd_dsi_panel.h
index 62f86794..6f4866d 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi_panel.h
+++ b/drivers/gpu/drm/sprd/sprd_dsi_panel.h
@@ -39,6 +39,11 @@
};
enum {
+ SPRD_DSI_0 = 0,
+ SPRD_DSI_1,
+};
+
+enum {
ESD_MODE_REG_CHECK,
ESD_MODE_TE_CHECK,
ESD_MODE_MIX_CHECK,
@@ -69,6 +74,7 @@
struct drm_display_mode *buildin_modes;
int display_mode_count;
int num_buildin_modes;
+ struct gpio_desc *iovdd_gpio;
struct gpio_desc *avdd_gpio;
struct gpio_desc *avee_gpio;
struct gpio_desc *reset_gpio;
@@ -82,7 +88,8 @@
u32 output_bpc;
u32 dsc_en;
u32 dual_dsi_en;
-
+ /* dsi choose*/
+ u32 mipi_port;
/* esd check parameters*/
bool esd_check_en;
u8 esd_check_mode;
diff --git a/include/dt-bindings/soc/sprd,qogirn6pro-mask.h b/include/dt-bindings/soc/sprd,qogirn6pro-mask.h
index fb49e7ef..c35ecf0 100644
--- a/include/dt-bindings/soc/sprd,qogirn6pro-mask.h
+++ b/include/dt-bindings/soc/sprd,qogirn6pro-mask.h
@@ -4421,6 +4421,7 @@
#define MASK_DPU_VSP_APB_DISPC_SOFT_RST 0x0001
#define MASK_DPU_VSP_APB_DSI0_SOFT_RST 0x0002
#define MASK_DPU_VSP_APB_DSI1_SOFT_RST 0x0004
+#define MASK_DPU_VSP_APB_DSI1_SOFT_EN 0x0004
#define MASK_DPU_VSP_APB_DISPC_VAU_SOFT_RST 0x40000
#define MASK_DPU_VSP_APB_DPHY0_CFG_CKG_EN 0x0001
#define MASK_DPU_VSP_APB_DPHY0_REF_CKG_EN 0x0002
diff --git a/include/dt-bindings/soc/sprd,qogirn6pro-regs.h b/include/dt-bindings/soc/sprd,qogirn6pro-regs.h
index 424d13f..7522e48 100644
--- a/include/dt-bindings/soc/sprd,qogirn6pro-regs.h
+++ b/include/dt-bindings/soc/sprd,qogirn6pro-regs.h
@@ -926,6 +926,7 @@
#define REG_DISPC1_GLB_APB_AP2IPA_S0_LPC 0x00AC
#define REG_DISPC1_GLB_APB_DPTX_CTRL 0x00B0
#define REG_DPU_VSP_APB_RST 0x0004
+#define REG_DPU_VSP_APB_EN 0x0000
#define REG_IPA_GLB_APB_IPA_IP_RST 0x0000
#define REG_IPA_GLB_APB_IPA_IP_EB 0x0004
#define REG_IPA_GLB_APB_IPA_IP_LPC_CTRL 0x0008