linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v11 0/7] drm/lsdc: add drm driver for loongson display controller
@ 2022-03-21 16:29 Sui Jingfeng
  2022-03-21 16:29 ` [PATCH v11 1/7] MIPS: Loongson64: dts: update the display controller device node Sui Jingfeng
                   ` (6 more replies)
  0 siblings, 7 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-21 16:29 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter, Rob Herring,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel

There is a display controller in loongson's LS2K1000 SoC and LS7A1000
bridge chip, the display controller is a PCI device in those chips. It
has two display pipes but with only one hardware cursor. Each way has
a DVO interface which provide RGB888 signals, vertical & horizontal
synchronisations, data enable and the pixel clock. Each CRTC is able to
scanout from 1920x1080 resolution at 60Hz, the maxmium resolution is
2048x2048 according to the hardware spec. Loongson display controllers
are simple which require scanout buffers to be physically contiguous.

For LS7A1000 bridge chip, the DC is equipped with a dedicated video RAM
which is typically 64MB or more. In this case, VRAM helper based driver
is suppose to be used. While LS2K1000 is a SoC, only system memory is
available, therefore CMA helper based driver is intend to be used. It is
possible to use VRAM helper based solution by carving out part of system
memory as VRAM though.

For LS7A1000, there are 4 dedicated GPIOs whose control register is
located at the DC register space, They are used to emulate two way i2c.
One for DVO0, another for DVO1. LS2K1000 and LS2K0500 SoC don't have such
GPIO hardwared, they grab i2c adapter from other module, either general
purpose GPIO emulated i2c or hardware i2c adapter.

    +------+            +-----------------------------------+
    | DDR4 |            |  +-------------------+            |
    +------+            |  | PCIe Root complex |   LS7A1000 |
       || MC0           |  +--++---------++----+            |
  +----------+  HT 3.0  |     ||         ||                 |
  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
  +----------+          | +--------+  +-+--+-+    +---------+   +------+
       || MC1           +---------------|--|----------------+
    +------+                            |  |
    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
                      +-------+                      +------+

The above picture give a simple usage of LS7A1000, note that the encoder
is not necessary adv7125 or tfp410, other candicates can be ch7034b,
sil9022, ite66121 and lt8618 etc.

v2: Fixup warnings reported by kernel test robot

v3: Fix more grammar mistakes in Kconfig reported by Randy Dunlap and give
    more details about lsdc.

v4:
   1) Add dts required and explain why device tree is required.
   2) Give more description about lsdc and VRAM helper based driver.
   3) Fix warnings reported by kernel test robot.
   4) Introduce stride_alignment member into struct lsdc_chip_desc, the
      stride alignment is 256 bytes for ls7a1000, ls2k1000 and ls2k0500.

v5:
   1) Using writel and readl replace writeq and readq, to fix kernel test
      robot report build error on other archtecture.
   2) Set default fb format to XRGB8888 at crtc reset time.

v6:
   1) Explain why we are not switch to drm dridge subsystem on ls2k1000.
   2) Explain why tiny drm driver is not suitable for us.
   3) Give a short description of the trival dirty uppdate implement based
      on CMA helper.

v7:
   1) Remove select I2C_GPIO and I2C_LS2X in Kconfig, it is not ready now
   2) Licensing issues are fixed suggested by Krzysztof Kozlowski.
   3) Remove lsdc_pixpll_print(), part of it move to debugfs.
   4) Set prefer_shadow to true if vram based driver is in using.
   5) Replace double blank lines with single line in all files.
   6) Verbose cmd line parameter is replaced with drm_dbg()
   7) All warnnings reported by ./scripts/checkpatch.pl --strict are fixed
   8) Get edid from dtb support is removed as suggested by Maxime Ripard
   9) Fix typos and various improvement

v8:
   1) Drop damage update implement and its command line.
   2) Drop DRM_LSDC_VRAM_DRIVER config option as suggested by Maxime.
   3) Deduce DC's identification from its compatible property.
   4) Drop the board specific dts patch.
   5) Add documention about the display controller device node.

v9:
   1) Fix the warnings reported by checkpatch script and fix typos

v10:
   1) Pass `make dt_binding_check` validation
   2) Fix warnings reported by kernel test robot

v11:
   1) Convert the driver to use drm bridge and of graph framework.
   2) Dump register value support through debugfs.

Below is a brief introduction of loongson's CPU, bridge chip and SoC.
LS2K1000 is a double core 1.0Ghz mips64r2 compatible SoC[1]. LS7A1000 is
a bridge chip made by Loongson corporation which act as north and/or south
bridge of loongson's desktop and server level processor. It is equivalent
to AMD RS780E+SB710 or something like that. More details can be read from
its user manual[2].

This bridge chip is typically use with LS3A3000, LS3A4000 and LS3A5000 cpu.
LS3A3000 is 4 core 1.45gHz mips64r2 compatible cpu.
LS3A4000 is 4 core 1.8gHz mips64r5 compatible cpu[3].
LS3A5000 is 4 core 2.5gHz loongarch cpu[4].

Nearly all loongson cpu has the hardware maintain the cache coherency,
except for early version of ls2k1000 or ls3a2000. This is the most distinct
feature from other Mips cpu.

[1] https://wiki.debian.org/InstallingDebianOn/Lemote/Loongson2K1000
[2] https://loongson.github.io/LoongArch-Documentation/Loongson-7A1000-usermanual-EN.html
[3] https://ee-paper.com/loongson-3a4000-3b4000-motherboard-products-are-compatible-with-uos-system/
[4] https://loongson.github.io/LoongArch-Documentation/Loongson-3A5000-usermanual-EN.html
[5] https://github.com/loongson-community/pmon

suijingfeng (7):
  MIPS: Loongson64: dts: update the display controller device node
  MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  MIPS: Loongson64: dts: introduce lemote A1901 motherboard
  MIPS: Loongson64: dts: introduce ls2k1000 pai evaluation board
  dt-bindings: display: Add Loongson display controller
  MIPS: Loongson64: defconfig: enable display bridge drivers on Loongson64
  drm/lsdc: add drm driver for loongson display controller

 .../loongson/loongson,display-controller.yaml | 230 +++++++
 arch/mips/boot/dts/loongson/lemote_a1901.dts  |  92 +++
 .../boot/dts/loongson/loongson64-2k1000.dtsi  |  24 +
 arch/mips/boot/dts/loongson/ls2k1000_pai.dts  | 102 ++++
 .../boot/dts/loongson/ls3a4000_7a1000_evb.dts | 136 +++++
 arch/mips/boot/dts/loongson/ls7a-pch.dtsi     |  36 +-
 arch/mips/configs/loongson2k_defconfig        |   5 +
 arch/mips/configs/loongson3_defconfig         |   5 +
 drivers/gpu/drm/Kconfig                       |   2 +
 drivers/gpu/drm/Makefile                      |   1 +
 drivers/gpu/drm/lsdc/Kconfig                  |  23 +
 drivers/gpu/drm/lsdc/Makefile                 |  13 +
 drivers/gpu/drm/lsdc/lsdc_crtc.c              | 396 ++++++++++++
 drivers/gpu/drm/lsdc/lsdc_drv.c               | 547 +++++++++++++++++
 drivers/gpu/drm/lsdc/lsdc_drv.h               | 197 ++++++
 drivers/gpu/drm/lsdc/lsdc_i2c.c               | 235 +++++++
 drivers/gpu/drm/lsdc/lsdc_i2c.h               |  42 ++
 drivers/gpu/drm/lsdc/lsdc_irq.c               |  58 ++
 drivers/gpu/drm/lsdc/lsdc_irq.h               |  18 +
 drivers/gpu/drm/lsdc/lsdc_output.c            | 262 ++++++++
 drivers/gpu/drm/lsdc/lsdc_output.h            |  24 +
 drivers/gpu/drm/lsdc/lsdc_pci_drv.c           | 328 ++++++++++
 drivers/gpu/drm/lsdc/lsdc_plane.c             | 470 ++++++++++++++
 drivers/gpu/drm/lsdc/lsdc_pll.c               | 574 ++++++++++++++++++
 drivers/gpu/drm/lsdc/lsdc_pll.h               |  88 +++
 drivers/gpu/drm/lsdc/lsdc_regs.h              | 220 +++++++
 26 files changed, 4123 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
 create mode 100644 arch/mips/boot/dts/loongson/lemote_a1901.dts
 create mode 100644 arch/mips/boot/dts/loongson/ls2k1000_pai.dts
 create mode 100644 arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts
 create mode 100644 drivers/gpu/drm/lsdc/Kconfig
 create mode 100644 drivers/gpu/drm/lsdc/Makefile
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_crtc.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_pci_drv.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_plane.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_regs.h

-- 
2.25.1


^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v11 1/7] MIPS: Loongson64: dts: update the display controller device node
  2022-03-21 16:29 [PATCH v11 0/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
@ 2022-03-21 16:29 ` Sui Jingfeng
  2022-03-21 16:29 ` [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board Sui Jingfeng
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-21 16:29 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter, Rob Herring,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel

From: suijingfeng <suijingfeng@loongson.cn>

The display controller is a pci device, it is used in ls2k1000 SoC and
LS7A1000 bridge. Its PCI vendor id is 0x0014, Tts PCI device id is 0x7a06.
In order to let the driver to know which chip the DC is contained in,
the compatible of the display controller is named according to the chip's
name.

For LS7A1000, there are 4 dedicated GPIOs whose control register is
located at the DC register space. They are used to emulate i2c for reading
edid from the monitor. One for DVO0, another for DVO1.

LS2K1000 and LS2K0500 SoC don't have such GPIOs, they grab i2c adapter
from other module, either general purpose GPIO emulated i2c or hardware
i2c adapter.

Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
Signed-off-by: Sui Jingfeng <15330273260@189.cn>
---
 .../boot/dts/loongson/loongson64-2k1000.dtsi  | 24 +++++++++++++
 arch/mips/boot/dts/loongson/ls7a-pch.dtsi     | 36 ++++++++++++++++---
 2 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
index 8143a61111e3..b168cccc3399 100644
--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
@@ -198,6 +198,30 @@ sata@8,0 {
 				interrupt-parent = <&liointc0>;
 			};
 
+			lsdc: display-controller@6,0 {
+				compatible = "loongson,ls2k1000-dc";
+
+				reg = <0x3000 0x0 0x0 0x0 0x0>;
+				interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
+				interrupt-parent = <&liointc0>;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+						dc_out_rgb0: endpoint {
+						};
+					};
+					port@1 {
+						reg = <1>;
+						dc_out_rgb1: endpoint {
+						};
+					};
+				};
+			};
+
 			pci_bridge@9,0 {
 				compatible = "pci0014,7a19.0",
 						   "pci0014,7a19",
diff --git a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
index 2f45fce2cdc4..fcea73006f7a 100644
--- a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
+++ b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
@@ -160,15 +160,41 @@ gpu@6,0 {
 				interrupt-parent = <&pic>;
 			};
 
-			dc@6,1 {
-				compatible = "pci0014,7a06.0",
-						   "pci0014,7a06",
-						   "pciclass030000",
-						   "pciclass0300";
+			lsdc: display-controller@6,1 {
+				compatible = "loongson,ls7a1000-dc";
 
 				reg = <0x3100 0x0 0x0 0x0 0x0>;
 				interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
 				interrupt-parent = <&pic>;
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				i2c6: i2c-gpio@0 {
+					compatible = "lsdc,i2c-gpio-0";
+					reg = <6>;
+				};
+
+				i2c7: i2c-gpio@1 {
+					compatible = "lsdc,i2c-gpio-1";
+					reg = <7>;
+				};
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+						dc_out_rgb0: endpoint {
+						};
+					};
+					port@1 {
+						reg = <1>;
+						dc_out_rgb1: endpoint {
+						};
+					};
+				};
 			};
 
 			hda@7,0 {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-21 16:29 [PATCH v11 0/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
  2022-03-21 16:29 ` [PATCH v11 1/7] MIPS: Loongson64: dts: update the display controller device node Sui Jingfeng
@ 2022-03-21 16:29 ` Sui Jingfeng
  2022-03-22 13:05   ` Jiaxun Yang
  2022-03-21 16:29 ` [PATCH v11 3/7] MIPS: Loongson64: dts: introduce lemote A1901 motherboard Sui Jingfeng
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-21 16:29 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter, Rob Herring,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel

From: suijingfeng <suijingfeng@loongson.cn>

The board name is LS3A4000_7A1000_EVB_BOARD_V1.4, it consist of 1.8Ghz
mips64r5 4-core CPU and LS7A1000 bridge chip. It has PCIe GEN2 x8 slot,
therefore can play with discrete graphics card.

While the integrated display copntroller is equipped with a VGA output
and a DVI output, the VGA is connect to the DVO0 output port of the
display controller, the DVI is connected to DVO1 output port of the
display controller.

    +------+            +-----------------------------------+
    | DDR4 |            |  +-------------------+            |
    +------+            |  | PCIe Root complex |   LS7A1000 |
       || MC0           |  +--++---------++----+            |
  +----------+  HT 3.0  |     ||         ||                 |
  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
  +----------+          | +--------+  +-+--+-+    +---------+   +------+
       || MC1           +---------------|--|----------------+
    +------+                            |  |
    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
                      +-------+                      +------+

Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
Signed-off-by: Sui Jingfeng <15330273260@189.cn>
---
 .../boot/dts/loongson/ls3a4000_7a1000_evb.dts | 136 ++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100644 arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts

diff --git a/arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts b/arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts
new file mode 100644
index 000000000000..f467eddccdac
--- /dev/null
+++ b/arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+
+#include "loongson64g-package.dtsi"
+#include "ls7a-pch.dtsi"
+
+/ {
+	compatible = "loongson,loongson64g-4core-ls7a";
+	model = "LS3A4000_7A1000_EVB_BOARD_V1.4";
+
+	vga-encoder {
+		compatible = "adi,adv7123", "dumb-vga-dac";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7123_in: endpoint {
+					remote-endpoint = <&dc_out_rgb0>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				adv7123_out: endpoint {
+					remote-endpoint = <&vga_connector_in>;
+				};
+			};
+		};
+	};
+
+	vga-connector {
+		compatible = "vga-connector";
+		label = "vga";
+
+		ddc-i2c-bus = <&i2c6>;
+
+		port {
+			vga_connector_in: endpoint {
+				remote-endpoint = <&adv7123_out>;
+			};
+		};
+	};
+
+	tfp410: dvi-encoder {
+		compatible = "ti,tfp410";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				tfp410_in: endpoint {
+					pclk-sample = <1>;
+					bus-width = <24>;
+					remote-endpoint = <&dc_out_rgb1>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				tfp410_out: endpoint {
+					remote-endpoint = <&dvi_connector_in>;
+				};
+			};
+		};
+	};
+
+	dvi-connector {
+		compatible = "dvi-connector";
+		label = "dvi";
+		digital;
+
+		ddc-i2c-bus = <&i2c7>;
+
+		port {
+			dvi_connector_in: endpoint {
+				remote-endpoint = <&tfp410_out>;
+			};
+		};
+	};
+};
+
+&package0 {
+	htvec: interrupt-controller@efdfb000080 {
+		compatible = "loongson,htvec-1.0";
+		reg = <0xefd 0xfb000080 0x40>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		interrupt-parent = <&liointc>;
+		interrupts = <24 IRQ_TYPE_LEVEL_HIGH>,
+			     <25 IRQ_TYPE_LEVEL_HIGH>,
+			     <26 IRQ_TYPE_LEVEL_HIGH>,
+			     <27 IRQ_TYPE_LEVEL_HIGH>,
+			     <28 IRQ_TYPE_LEVEL_HIGH>,
+			     <29 IRQ_TYPE_LEVEL_HIGH>,
+			     <30 IRQ_TYPE_LEVEL_HIGH>,
+			     <31 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&pch {
+	msi: msi-controller@2ff00000 {
+		compatible = "loongson,pch-msi-1.0";
+		reg = <0 0x2ff00000 0 0x8>;
+		interrupt-controller;
+		msi-controller;
+		loongson,msi-base-vec = <64>;
+		loongson,msi-num-vecs = <192>;
+		interrupt-parent = <&htvec>;
+	};
+};
+
+&lsdc {
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			endpoint {
+				remote-endpoint = <&adv7123_in>;
+			};
+		};
+
+		port@1 {
+			endpoint {
+				remote-endpoint = <&tfp410_in>;
+			};
+		};
+	};
+};
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v11 3/7] MIPS: Loongson64: dts: introduce lemote A1901 motherboard
  2022-03-21 16:29 [PATCH v11 0/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
  2022-03-21 16:29 ` [PATCH v11 1/7] MIPS: Loongson64: dts: update the display controller device node Sui Jingfeng
  2022-03-21 16:29 ` [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board Sui Jingfeng
@ 2022-03-21 16:29 ` Sui Jingfeng
  2022-03-21 16:29 ` [PATCH v11 4/7] MIPS: Loongson64: dts: introduce ls2k1000 pai evaluation board Sui Jingfeng
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-21 16:29 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter, Rob Herring,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel

From: suijingfeng <suijingfeng@loongson.cn>

This board is made by LEMOTE corporation, it has two name, one
is LX-6901, another is A1901.

This board has only one VGA output which is connected to the DVO1 of
the display controller.

    +------+            +-----------------------------------+
    | DDR4 |            |  +-------------------+            |
    +------+            |  | PCIe Root complex |   LS7A1000 |
       || MC0           |  +--++---------++----+            |
  +----------+  HT 3.0  |     ||         ||                 |
  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
  +----------+          | +--------+  +-+--+-+    +---------+   +------+
       || MC1           +---------------|--|----------------+
    +------+                            |  |
    | DDR4 |       DVO0 is not get used |  |  DVO1   +-------+
    +------+       <--------------------+  +-------->|ADV7125|---> VGA
                                                     +-------+
The model property added can provided board specific information,
mips kernel use it as machine name.

$ cat /proc/cpuinfo

system type             : Generic Loongson64 System
machine                 : LX-6901  <-------------------- notice here
processor               : 0
cpu model               : ICT Loongson-3 V0.1  FPU V0.1
BogoMIPS                : 3594.02
tlb_entries             : 2112
isa                     : mips64r2
ASEs implemented        : vz msa loongson-ext2
...

Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
Signed-off-by: Sui Jingfeng <15330273260@189.cn>
---
 arch/mips/boot/dts/loongson/lemote_a1901.dts | 92 ++++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100644 arch/mips/boot/dts/loongson/lemote_a1901.dts

diff --git a/arch/mips/boot/dts/loongson/lemote_a1901.dts b/arch/mips/boot/dts/loongson/lemote_a1901.dts
new file mode 100644
index 000000000000..f0443bc43af9
--- /dev/null
+++ b/arch/mips/boot/dts/loongson/lemote_a1901.dts
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+
+#include "loongson64g-package.dtsi"
+#include "ls7a-pch.dtsi"
+
+/ {
+	model = "LX-6901";
+
+	vga-encoder {
+		compatible = "adi,adv7123", "dumb-vga-dac";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7123_in: endpoint {
+					remote-endpoint = <&dc_out_rgb1>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				adv7123_out: endpoint {
+					remote-endpoint = <&vga_connector_in>;
+				};
+			};
+		};
+	};
+
+	vga-connector {
+		compatible = "vga-connector";
+		label = "vga";
+
+		ddc-i2c-bus = <&i2c7>;
+
+		port {
+			vga_connector_in: endpoint {
+				remote-endpoint = <&adv7123_out>;
+			};
+		};
+	};
+};
+
+&package0 {
+	htvec: interrupt-controller@efdfb000080 {
+		compatible = "loongson,htvec-1.0";
+		reg = <0xefd 0xfb000080 0x40>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		interrupt-parent = <&liointc>;
+		interrupts = <24 IRQ_TYPE_LEVEL_HIGH>,
+			     <25 IRQ_TYPE_LEVEL_HIGH>,
+			     <26 IRQ_TYPE_LEVEL_HIGH>,
+			     <27 IRQ_TYPE_LEVEL_HIGH>,
+			     <28 IRQ_TYPE_LEVEL_HIGH>,
+			     <29 IRQ_TYPE_LEVEL_HIGH>,
+			     <30 IRQ_TYPE_LEVEL_HIGH>,
+			     <31 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&pch {
+	msi: msi-controller@2ff00000 {
+		compatible = "loongson,pch-msi-1.0";
+		reg = <0 0x2ff00000 0 0x8>;
+		interrupt-controller;
+		msi-controller;
+		loongson,msi-base-vec = <64>;
+		loongson,msi-num-vecs = <192>;
+		interrupt-parent = <&htvec>;
+	};
+};
+
+&lsdc {
+	ports {
+		port@0 {
+			status = "disabled";
+		};
+
+		port@1 {
+			status = "ok";
+			endpoint {
+				remote-endpoint = <&adv7123_in>;
+			};
+		};
+	};
+};
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v11 4/7] MIPS: Loongson64: dts: introduce ls2k1000 pai evaluation board
  2022-03-21 16:29 [PATCH v11 0/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
                   ` (2 preceding siblings ...)
  2022-03-21 16:29 ` [PATCH v11 3/7] MIPS: Loongson64: dts: introduce lemote A1901 motherboard Sui Jingfeng
@ 2022-03-21 16:29 ` Sui Jingfeng
  2022-03-21 16:29 ` [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller Sui Jingfeng
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-21 16:29 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter, Rob Herring,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel

From: suijingfeng <suijingfeng@loongson.cn>

   ___________________                           ____________________
  |            -------|                         |                    |
  |  CRTC0 --> | DVO0 ------------------------> | 1024x600 DPI Panel |
  |  _   _     -------|  | Which panel to use   |____________________|
  | | | | |           |  | with this board is a  ___________________
  | |_| |_|           |  | choice of the user   |                   |
  |                   |  +--------------------> | 800x480 DPI Panel |
  |   DC In LS2K1000  |                         |___________________|
  |  _   _            |     +------+
  | | | | |           <---->| i2c1 |-----------+
  | |_| |_|           |     +------+           |
  |                   |        |               |               _________
  |            -------|    +---------+         |              |         |
  |  CRTC1 --> | DVO1 ---> | sii9022 | --> HDMI connector --> | Monitor |
  |            -------|    +---------+                        |_________|
  |___________________|

The sii9022 HDMI transmitter working in transparent mode, in this case
the edid is read from the monitor directly, not through sil9022's ddc
channel. The PMON[2] firmware of this board is responsible for configure
the sii9022 encoder at boot time. Due to i2c driver for lsk2000 SoC is
not upstream yet, we simply replace the sii9022 with a 1024x768 panel.

The i2c0 is not get used by lsdc driver for this board, so there no
need to worry about DVO0.

[1] https://wiki.debian.org/InstallingDebianOn/Lemote/Loongson2K1000
[2] https://github.com/loongson-community/pmon

Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
Signed-off-by: Sui Jingfeng <15330273260@189.cn>
---
 arch/mips/boot/dts/loongson/ls2k1000_pai.dts | 102 +++++++++++++++++++
 1 file changed, 102 insertions(+)
 create mode 100644 arch/mips/boot/dts/loongson/ls2k1000_pai.dts

diff --git a/arch/mips/boot/dts/loongson/ls2k1000_pai.dts b/arch/mips/boot/dts/loongson/ls2k1000_pai.dts
new file mode 100644
index 000000000000..0b0172d90677
--- /dev/null
+++ b/arch/mips/boot/dts/loongson/ls2k1000_pai.dts
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+
+#include "loongson64-2k1000.dtsi"
+
+/ {
+	model = "LS2K1000_PAI_UDB_V1.5";
+
+	panel: display@0 {
+		compatible = "hontron,070JII2135-A2", "panel-dpi";
+		label = "LCD070CG1024600+DC21";
+
+		rotation = <0>;
+		width-mm = <86>;
+		height-mm = <154>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			panel_in: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&dc_out_rgb0>;
+			};
+		};
+
+		panel-timing {
+			clock-frequency = <51200000>;
+			hactive = <1024>;
+			vactive = <600>;
+			hsync-len = <4>;
+			hfront-porch = <160>;
+			hback-porch = <156>;
+			vfront-porch = <11>;
+			vback-porch = <23>;
+			vsync-len = <1>;
+
+			hsync-active = <0>;
+			vsync-active = <0>;
+			de-active = <1>;
+			pixelclk-active = <1>;
+		};
+	};
+
+	monitor: display@1 {
+		compatible = "panel-dpi";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			monitor_in: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&dc_out_rgb1>;
+			};
+		};
+
+		panel-timing {
+			clock-frequency = <65000000>;
+			hactive = <1024>;
+			vactive = <768>;
+			hfront-porch = <24>;
+			hsync-len = <136>;
+			hback-porch = <160>;
+			vfront-porch = <3>;
+			vback-porch = <6>;
+			vsync-len = <29>;
+
+			hsync-active = <0>;
+			vsync-active = <0>;
+			de-active = <1>;
+			pixelclk-active = <1>;
+		};
+	};
+};
+
+&lsdc {
+	ports {
+		port@0 {
+			endpoint {
+				remote-endpoint = <&panel_in>;
+			};
+		};
+
+		port@1 {
+			endpoint {
+				remote-endpoint = <&monitor_in>;
+			};
+		};
+	};
+};
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-21 16:29 [PATCH v11 0/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
                   ` (3 preceding siblings ...)
  2022-03-21 16:29 ` [PATCH v11 4/7] MIPS: Loongson64: dts: introduce ls2k1000 pai evaluation board Sui Jingfeng
@ 2022-03-21 16:29 ` Sui Jingfeng
  2022-03-21 23:20   ` Rob Herring
  2022-03-21 16:29 ` [PATCH v11 6/7] MIPS: Loongson64: defconfig: enable display bridge drivers on Loongson64 Sui Jingfeng
  2022-03-21 16:29 ` [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
  6 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-21 16:29 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter, Rob Herring,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel

From: suijingfeng <suijingfeng@loongson.cn>

Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
Signed-off-by: Sui Jingfeng <15330273260@189.cn>
---
 .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
 1 file changed, 230 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml

diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
new file mode 100644
index 000000000000..7be63346289e
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
@@ -0,0 +1,230 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
+
+maintainers:
+  - Sui Jingfeng <suijingfeng@loongson.cn>
+
+description: |+
+
+  Loongson display controllers are simple which require scanout buffers
+  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
+  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
+  with a dedicated video RAM which is 64MB or more, precise size can be
+  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
+  chip.
+
+  LSDC has two display pipes, each way has a DVO interface which provide
+  RGB888 signals, vertical & horizontal synchronisations, data enable and
+  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
+  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
+
+  For LS7A1000, there are 4 dedicated GPIOs whose control register is
+  located at the DC register space. They are used to emulate two way i2c,
+  One for DVO0, another for DVO1.
+
+  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
+  general purpose GPIO emulated i2c or hardware i2c in the SoC.
+
+  LSDC's display pipeline have several components as below description,
+
+  The display controller in LS7A1000:
+     ___________________                                     _________
+    |            -------|                                   |         |
+    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
+    |  _   _     -------|        ^             ^            |_________|
+    | | | | |    -------|        |             |
+    | |_| |_|    | i2c0 <--------+-------------+
+    |            -------|
+    |   DC IN LS7A1000  |
+    |  _   _     -------|
+    | | | | |    | i2c1 <--------+-------------+
+    | |_| |_|    -------|        |             |             _________
+    |            -------|        |             |            |         |
+    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
+    |            -------|                                   |_________|
+    |___________________|
+
+  Simple usage of LS7A1000 with LS3A4000 CPU:
+
+    +------+            +-----------------------------------+
+    | DDR4 |            |  +-------------------+            |
+    +------+            |  | PCIe Root complex |   LS7A1000 |
+       || MC0           |  +--++---------++----+            |
+  +----------+  HT 3.0  |     ||         ||                 |
+  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
+  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
+  +----------+          | +--------+  +-+--+-+    +---------+   +------+
+       || MC1           +---------------|--|----------------+
+    +------+                            |  |
+    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
+    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
+                      +-------+                      +------+
+
+  The display controller in LS2K1000/LS2K0500:
+     ___________________                                     _________
+    |            -------|                                   |         |
+    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
+    |  _   _     -------|        ^              ^           |_________|
+    | | | | |           |        |              |
+    | |_| |_|           |     +------+          |
+    |                   <---->| i2c0 |<---------+
+    |   DC IN LS2K1000  |     +------+
+    |  _   _            |     +------+
+    | | | | |           <---->| i2c1 |----------+
+    | |_| |_|           |     +------+          |            _________
+    |            -------|        |              |           |         |
+    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
+    |            -------|                                   |_________|
+    |___________________|
+
+properties:
+  $nodename:
+    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
+
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - loongson,ls7a1000-dc
+              - loongson,ls2k1000-dc
+              - loongson,ls2k0500-dc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  i2c-gpio@0:
+    description: |
+      Built-in GPIO emulate i2c exported for external display bridge
+      configuration, onitor detection and edid read back etc, for ls7a1000
+      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
+      used to specify a I2c adapter bus number, if you don't specify one
+      i2c driver core will dynamically assign a bus number. Please specify
+      it only when its bus number matters. Bus number greater than 6 is safe
+      because ls7a1000 bridge have 6 hardware I2C controller integrated.
+
+  i2c-gpio@1:
+    description: |
+      Built-in GPIO emulate i2c exported for external display bridge
+      configuration, onitor detection and edid read back etc, for ls7a1000
+      only. Its compatible must be lsdc,i2c-gpio-1.
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: output port node connected with DPI panels or external encoders, with only one endpoint.
+
+      port@1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: output port node connected with DPI panels or external encoders, with only one endpoint.
+
+    required:
+      - port@0
+      - port@1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    bus {
+
+        #address-cells = <3>;
+        #size-cells = <2>;
+        #interrupt-cells = <2>;
+
+        display-controller@6,1 {
+            compatible = "loongson,ls7a1000-dc";
+            reg = <0x3100 0x0 0x0 0x0 0x0>;
+            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
+
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            i2c-gpio@0 {
+                compatible = "lsdc,i2c-gpio-0";
+                reg = <6>;
+                sda = <0>;
+                scl = <1>;
+            };
+
+            i2c-gpio@1 {
+                compatible = "lsdc,i2c-gpio-1";
+                reg = <7>;
+                sda = <2>;
+                scl = <3>;
+            };
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+                port@0 {
+                    reg = <0>;
+                    endpoint {
+                            remote-endpoint = <&vga_encoder_in>;
+                    };
+                };
+                port@1 {
+                    reg = <1>;
+                    endpoint {
+                            remote-endpoint = <&dvi_encoder_in>;
+                    };
+                };
+            };
+        };
+    };
+
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    bus {
+
+        #address-cells = <3>;
+        #size-cells = <2>;
+        #interrupt-cells = <2>;
+
+        display-controller@6,0 {
+            compatible = "loongson,ls2k1000-dc";
+            reg = <0x3100 0x0 0x0 0x0 0x0>;
+            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+                port@0 {
+                    reg = <0>;
+                    endpoint {
+                            remote-endpoint = <&panel_in>;
+                    };
+                };
+                port@1 {
+                    reg = <1>;
+                    endpoint {
+                            remote-endpoint = <&hdmi_encoder_in>;
+                    };
+                };
+            };
+        };
+    };
+...
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v11 6/7] MIPS: Loongson64: defconfig: enable display bridge drivers on Loongson64
  2022-03-21 16:29 [PATCH v11 0/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
                   ` (4 preceding siblings ...)
  2022-03-21 16:29 ` [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller Sui Jingfeng
@ 2022-03-21 16:29 ` Sui Jingfeng
  2022-03-21 16:29 ` [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
  6 siblings, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-21 16:29 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter, Rob Herring,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel

From: suijingfeng <suijingfeng@loongson.cn>

ls3A4000 evb board is shipped with adv7123 and tfp410 while ls2k1000
PI board use a DPI panel from FORLINX and a sii9022 HDMI transmitter.

Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
Signed-off-by: Sui Jingfeng <15330273260@189.cn>
---
 arch/mips/configs/loongson2k_defconfig | 5 +++++
 arch/mips/configs/loongson3_defconfig  | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/arch/mips/configs/loongson2k_defconfig b/arch/mips/configs/loongson2k_defconfig
index e948ca487e2d..0a97c332a5c3 100644
--- a/arch/mips/configs/loongson2k_defconfig
+++ b/arch/mips/configs/loongson2k_defconfig
@@ -243,6 +243,11 @@ CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
 CONFIG_DRM=y
 CONFIG_DRM_RADEON=y
+CONFIG_DRM_DISPLAY_CONNECTOR=m
+CONFIG_DRM_PANEL_SIMPLE=m
+CONFIG_DRM_SII902X=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
+CONFIG_DRM_TI_TFP410=m
 CONFIG_FB_RADEON=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_PLATFORM=m
diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig
index 25ecd15bc952..35e2fc998768 100644
--- a/arch/mips/configs/loongson3_defconfig
+++ b/arch/mips/configs/loongson3_defconfig
@@ -280,6 +280,11 @@ CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
 CONFIG_DRM=y
 CONFIG_DRM_RADEON=m
+CONFIG_DRM_DISPLAY_CONNECTOR=m
+CONFIG_DRM_PANEL_SIMPLE=m
+CONFIG_DRM_SII902X=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
+CONFIG_DRM_TI_TFP410=m
 CONFIG_DRM_QXL=y
 CONFIG_DRM_VIRTIO_GPU=y
 CONFIG_FB=y
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-21 16:29 [PATCH v11 0/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
                   ` (5 preceding siblings ...)
  2022-03-21 16:29 ` [PATCH v11 6/7] MIPS: Loongson64: defconfig: enable display bridge drivers on Loongson64 Sui Jingfeng
@ 2022-03-21 16:29 ` Sui Jingfeng
  2022-03-22 20:49   ` Rob Herring
  6 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-21 16:29 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter, Rob Herring,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel, kernel test robot

From: suijingfeng <suijingfeng@loongson.cn>

There is a display controller in loongson's LS2K1000 SoC and LS7A1000
bridge chip, the display controller is a PCI device in those chips. It
has two display pipes but with only one hardware cursor. Each way has
a DVO interface which provide RGB888 signals, vertical & horizontal
synchronisations, data enable and the pixel clock. Each CRTC is able to
scanout from 1920x1080 resolution at 60Hz, the maxmium resolution is
2048x2048 according to the hardware spec. Loongson display controllers
are simple which require scanout buffers to be physically contiguous.

For LS7A1000 bridge chip, the DC is equipped with a dedicated video RAM
which is typically 64MB or more. In this case, VRAM helper based driver
is intend to be used. While LS2K1000 is a SoC, only system memory is
available. Therefore CMA helper based driver is intend to be used. It is
possible to use VRAM helper based solution by carving out part of system
memory as VRAM though.

For LS7A1000, there are 4 dedicated GPIOs whose control register is
located at the DC register space, They are used to emulate two way i2c.
One for DVO0, another for DVO1. LS2K1000 and LS2K0500 SoC don't have such
GPIO hardwared, they grab i2c adapter from other module, either general
purpose GPIO emulated i2c or hardware i2c adapter.

    +------+            +-----------------------------------+
    | DDR4 |            |  +-------------------+            |
    +------+            |  | PCIe Root complex |   LS7A1000 |
       || MC0           |  +--++---------++----+            |
  +----------+  HT 3.0  |     ||         ||                 |
  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
  +----------+          | +--------+  +-+--+-+    +---------+   +------+
       || MC1           +---------------|--|----------------+
    +------+                            |  |
    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
                      +-------+                      +------+

The above picture give a simple usage of LS7A1000, note that the encoder
is not necessary adv7125 or tfp410, other candicates can be ch7034b,
sil9022, ite66121 and lt8618 etc.

v2: Fixup warnings reported by kernel test robot

v3: Fix more grammar mistakes in Kconfig reported by Randy Dunlap and give
    more details about lsdc.

v4:
   1) Add dts required and explain why device tree is required.
   2) Give more description about lsdc and VRAM helper based driver.
   3) Fix warnings reported by kernel test robot.
   4) Introduce stride_alignment member into struct lsdc_chip_desc, the
      stride alignment is 256 bytes for ls7a1000, ls2k1000 and ls2k0500.

v5:
   1) Using writel and readl replace writeq and readq, to fix kernel test
      robot report build error on other archtecture.
   2) Set default fb format to XRGB8888 at crtc reset time.

v6:
   1) Explain why we are not switch to drm dridge subsystem on ls2k1000.
   2) Explain why tiny drm driver is not suitable for us.
   3) Give a short description of the trival dirty uppdate implement based
      on CMA helper.

v7:
   1) Remove select I2C_GPIO and I2C_LS2X in Kconfig, it is not ready now
   2) Licensing issues are fixed suggested by Krzysztof Kozlowski.
   3) Remove lsdc_pixpll_print(), part of it move to debugfs.
   4) Set prefer_shadow to true if vram based driver is in using.
   5) Replace double blank lines with single line in all files.
   6) Verbose cmd line parameter is replaced with drm_dbg()
   7) All warnnings reported by ./scripts/checkpatch.pl --strict are fixed
   8) Get edid from dtb support is removed as suggested by Maxime Ripard
   9) Fix typos and various improvement

v8:
   1) Drop damage update implement and its command line.
   2) Drop DRM_LSDC_VRAM_DRIVER config option as suggested by Maxime.
   3) Deduce DC's identification from its compatible property.
   4) Drop the board specific dts patch.
   5) Add documention about the display controller device node.

v9:
   1) Fix the warnings reported by checkpatch script and fix typos

v10:
   1) Pass `make dt_binding_check` validation
   2) Fix warnings reported by kernel test robot

v11:
   1) Convert the driver to use drm bridge and of graph framework.
   2) Dump register value support through debugfs.

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
Signed-off-by: Sui Jingfeng <15330273260@189.cn>
Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
---
 drivers/gpu/drm/Kconfig             |   2 +
 drivers/gpu/drm/Makefile            |   1 +
 drivers/gpu/drm/lsdc/Kconfig        |  23 ++
 drivers/gpu/drm/lsdc/Makefile       |  13 +
 drivers/gpu/drm/lsdc/lsdc_crtc.c    | 396 +++++++++++++++++++
 drivers/gpu/drm/lsdc/lsdc_drv.c     | 547 ++++++++++++++++++++++++++
 drivers/gpu/drm/lsdc/lsdc_drv.h     | 197 ++++++++++
 drivers/gpu/drm/lsdc/lsdc_i2c.c     | 235 ++++++++++++
 drivers/gpu/drm/lsdc/lsdc_i2c.h     |  42 ++
 drivers/gpu/drm/lsdc/lsdc_irq.c     |  58 +++
 drivers/gpu/drm/lsdc/lsdc_irq.h     |  18 +
 drivers/gpu/drm/lsdc/lsdc_output.c  | 262 +++++++++++++
 drivers/gpu/drm/lsdc/lsdc_output.h  |  24 ++
 drivers/gpu/drm/lsdc/lsdc_pci_drv.c | 328 ++++++++++++++++
 drivers/gpu/drm/lsdc/lsdc_plane.c   | 470 +++++++++++++++++++++++
 drivers/gpu/drm/lsdc/lsdc_pll.c     | 574 ++++++++++++++++++++++++++++
 drivers/gpu/drm/lsdc/lsdc_pll.h     |  88 +++++
 drivers/gpu/drm/lsdc/lsdc_regs.h    | 220 +++++++++++
 18 files changed, 3498 insertions(+)
 create mode 100644 drivers/gpu/drm/lsdc/Kconfig
 create mode 100644 drivers/gpu/drm/lsdc/Makefile
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_crtc.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_pci_drv.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_plane.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.c
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.h
 create mode 100644 drivers/gpu/drm/lsdc/lsdc_regs.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f1422bee3dcc..e1395ad7db2f 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -408,6 +408,8 @@ source "drivers/gpu/drm/solomon/Kconfig"
 
 source "drivers/gpu/drm/sprd/Kconfig"
 
+source "drivers/gpu/drm/lsdc/Kconfig"
+
 config DRM_HYPERV
 	tristate "DRM Support for Hyper-V synthetic video device"
 	depends on DRM && PCI && MMU && HYPERV
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index c2ef5f9fce54..8ef234183efc 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -134,3 +134,4 @@ obj-y			+= gud/
 obj-$(CONFIG_DRM_HYPERV) += hyperv/
 obj-y			+= solomon/
 obj-$(CONFIG_DRM_SPRD) += sprd/
+obj-$(CONFIG_DRM_LSDC) += lsdc/
diff --git a/drivers/gpu/drm/lsdc/Kconfig b/drivers/gpu/drm/lsdc/Kconfig
new file mode 100644
index 000000000000..4704481143cc
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/Kconfig
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config DRM_LSDC
+	tristate "DRM Support for loongson's display controller"
+	depends on DRM && PCI
+	depends on MACH_LOONGSON64 || LOONGARCH || MIPS || COMPILE_TEST
+	select OF
+	select CMA if HAVE_DMA_CONTIGUOUS
+	select DMA_CMA if HAVE_DMA_CONTIGUOUS
+	select DRM_KMS_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_GEM_CMA_HELPER
+	select DRM_TTM
+	select DRM_TTM_HELPER
+	select DRM_VRAM_HELPER
+	select VIDEOMODE_HELPERS
+	default m
+	help
+	  This is a KMS driver for the display controller in the LS7A1000
+	  bridge chip and LS2K1000/LS2K0500 SoC.
+	  If "M" is selected, the module will be called lsdc.
+
+	  If in doubt, say "Y".
diff --git a/drivers/gpu/drm/lsdc/Makefile b/drivers/gpu/drm/lsdc/Makefile
new file mode 100644
index 000000000000..71ef58985647
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+
+lsdc-y := \
+	lsdc_drv.o \
+	lsdc_crtc.o \
+	lsdc_irq.o \
+	lsdc_plane.o \
+	lsdc_pll.o \
+	lsdc_i2c.o \
+	lsdc_output.o \
+	lsdc_pci_drv.o \
+
+obj-$(CONFIG_DRM_LSDC) += lsdc.o
diff --git a/drivers/gpu/drm/lsdc/lsdc_crtc.c b/drivers/gpu/drm/lsdc/lsdc_crtc.c
new file mode 100644
index 000000000000..e85c783b5ac5
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_crtc.c
@@ -0,0 +1,396 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+#include <drm/drm_vblank.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "lsdc_drv.h"
+#include "lsdc_regs.h"
+#include "lsdc_pll.h"
+
+static int lsdc_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+	struct lsdc_device *ldev = to_lsdc(crtc->dev);
+	unsigned int index = drm_crtc_index(crtc);
+	struct drm_crtc_state *state = crtc->state;
+	u32 val;
+
+	if (state->enable) {
+		val = lsdc_reg_read32(ldev, LSDC_INT_REG);
+
+		if (index == 0)
+			val |= INT_CRTC0_VS_EN;
+		else if (index == 1)
+			val |= INT_CRTC1_VS_EN;
+
+		lsdc_reg_write32(ldev, LSDC_INT_REG, val);
+	}
+
+	return 0;
+}
+
+static void lsdc_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+	struct lsdc_device *ldev = to_lsdc(crtc->dev);
+	unsigned int index = drm_crtc_index(crtc);
+	u32 val;
+
+	val = lsdc_reg_read32(ldev, LSDC_INT_REG);
+
+	if (index == 0)
+		val &= ~INT_CRTC0_VS_EN;
+	else if (index == 1)
+		val &= ~INT_CRTC1_VS_EN;
+
+	lsdc_reg_write32(ldev, LSDC_INT_REG, val);
+}
+
+static void lsdc_crtc_reset(struct drm_crtc *crtc)
+{
+	struct drm_device *ddev = crtc->dev;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+	unsigned int index = drm_crtc_index(crtc);
+	struct lsdc_crtc_state *priv_crtc_state;
+	u32 val = CFG_RESET_BIT | CFG_OUTPUT_EN_BIT | LSDC_PF_XRGB8888;
+
+	if (ldev->enable_gamma)
+		val |= CFG_GAMMAR_EN_BIT;
+
+	/* The crtc get soft reset if bit 20 of CRTC*_CFG_REG
+	 * is write with falling edge.
+	 *
+	 * Doing this to switch from soft reset state to working state
+	 */
+	if (index == 0)
+		lsdc_reg_write32(ldev, LSDC_CRTC0_CFG_REG, val);
+	else if (index == 1)
+		lsdc_reg_write32(ldev, LSDC_CRTC1_CFG_REG, val);
+
+	if (crtc->state) {
+		priv_crtc_state = to_lsdc_crtc_state(crtc->state);
+		__drm_atomic_helper_crtc_destroy_state(&priv_crtc_state->base);
+		kfree(priv_crtc_state);
+	}
+
+	priv_crtc_state = kzalloc(sizeof(*priv_crtc_state), GFP_KERNEL);
+	if (!priv_crtc_state)
+		return;
+
+	__drm_atomic_helper_crtc_reset(crtc, &priv_crtc_state->base);
+
+	drm_dbg(ddev, "crtc%u reset\n", index);
+}
+
+static void lsdc_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state)
+{
+	struct lsdc_crtc_state *priv_crtc_state = to_lsdc_crtc_state(state);
+
+	__drm_atomic_helper_crtc_destroy_state(&priv_crtc_state->base);
+
+	kfree(priv_crtc_state);
+}
+
+static struct drm_crtc_state *lsdc_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
+{
+	struct lsdc_crtc_state *new_priv_state;
+	struct lsdc_crtc_state *old_priv_state;
+	struct drm_device *ddev = crtc->dev;
+
+	if (drm_WARN_ON(ddev, !crtc->state))
+		return NULL;
+
+	new_priv_state = kmalloc(sizeof(*new_priv_state), GFP_KERNEL);
+	if (!new_priv_state)
+		return NULL;
+
+	__drm_atomic_helper_crtc_duplicate_state(crtc, &new_priv_state->base);
+
+	old_priv_state = to_lsdc_crtc_state(crtc->state);
+
+	memcpy(&new_priv_state->pparams, &old_priv_state->pparams, sizeof(new_priv_state->pparams));
+
+	return &new_priv_state->base;
+}
+
+static const struct drm_crtc_funcs lsdc_crtc_funcs = {
+	.reset = lsdc_crtc_reset,
+	.destroy = drm_crtc_cleanup,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.atomic_duplicate_state = lsdc_crtc_atomic_duplicate_state,
+	.atomic_destroy_state = lsdc_crtc_atomic_destroy_state,
+	.enable_vblank = lsdc_crtc_enable_vblank,
+	.disable_vblank = lsdc_crtc_disable_vblank,
+};
+
+static enum drm_mode_status
+lsdc_crtc_helper_mode_valid(struct drm_crtc *crtc,
+			    const struct drm_display_mode *mode)
+{
+	struct drm_device *ddev = crtc->dev;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+	const struct lsdc_chip_desc *desc = ldev->desc;
+
+	if (mode->hdisplay > desc->max_width)
+		return MODE_BAD_HVALUE;
+	if (mode->vdisplay > desc->max_height)
+		return MODE_BAD_VVALUE;
+
+	if (mode->clock > desc->max_pixel_clk) {
+		drm_dbg(ddev, "mode %dx%d, pixel clock=%d is too high\n",
+			mode->hdisplay, mode->vdisplay, mode->clock);
+		return MODE_CLOCK_HIGH;
+	}
+
+	/* The CRTC hardware dma take 256 bytes once a time,
+	 * it is a limitation of the CRTC.
+	 * TODO: check RGB565 support
+	 */
+	if (!ldev->relax_alignment) {
+		if ((mode->hdisplay * 4) % desc->stride_alignment) {
+			drm_dbg(ddev, "stride is not %u bytes aligned\n",
+				desc->stride_alignment);
+			return MODE_BAD;
+		}
+	}
+
+	return MODE_OK;
+}
+
+static int lsdc_pixpll_atomic_check(struct drm_crtc *crtc,
+				    struct drm_crtc_state *state)
+{
+	struct lsdc_display_pipe *dispipe = container_of(crtc, struct lsdc_display_pipe, crtc);
+	struct lsdc_pll * const pixpll = &dispipe->pixpll;
+	const struct lsdc_pixpll_funcs * const pfuncs = pixpll->funcs;
+	struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(state);
+	bool ret;
+
+	ret = pfuncs->compute(pixpll, state->mode.clock, &priv_state->pparams);
+	if (ret)
+		return 0;
+
+	drm_warn(crtc->dev, "failed find PLL parameters for %u\n", state->mode.clock);
+
+	return -EINVAL;
+}
+
+static int lsdc_crtc_helper_atomic_check(struct drm_crtc *crtc,
+					 struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+
+	if (!crtc_state->enable)
+		return 0; /* no mode checks if CRTC is being disabled */
+
+	return lsdc_pixpll_atomic_check(crtc, crtc_state);
+}
+
+static void lsdc_update_pixclk(struct drm_crtc *crtc)
+{
+	struct lsdc_display_pipe *dispipe = container_of(crtc, struct lsdc_display_pipe, crtc);
+	struct lsdc_pll * const pixpll = &dispipe->pixpll;
+	const struct lsdc_pixpll_funcs * const clkfun = pixpll->funcs;
+	struct lsdc_crtc_state *priv_state = to_lsdc_crtc_state(crtc->state);
+
+	clkfun->update(pixpll, &priv_state->pparams);
+}
+
+static void lsdc_crtc_helper_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct drm_device *ddev = crtc->dev;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	unsigned int index = drm_crtc_index(crtc);
+	u32 h_sync, v_sync, h_val, v_val;
+
+	/* 26:16 total pixels, 10:0 visiable pixels, in horizontal */
+	h_val = (mode->crtc_htotal << 16) | mode->crtc_hdisplay;
+	/* Hack to support non 256 bytes aligned stride, for example:
+	 * 800x480 DPI panel. In this case userspace do the work to
+	 * guarantee the horizontal pixel size is aligned by padding it.
+	 * In actual, We allocate 832x480x4 bytes in size.
+	 */
+	if (ldev->relax_alignment)
+		h_val = (h_val + 63) & ~63;
+
+	/* 26:16 total pixels, 10:0 visiable pixels, in vertical */
+	v_val = (mode->crtc_vtotal << 16) | mode->crtc_vdisplay;
+	/* 26:16 hsync end, 10:0 hsync start, bit 30 is hsync enable */
+	h_sync = (mode->crtc_hsync_end << 16) | mode->crtc_hsync_start | EN_HSYNC_BIT;
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+		h_sync |= INV_HSYNC_BIT;
+
+	/* 26:16 vsync end, 10:0 vsync start, bit 30 is vsync enable */
+	v_sync = (mode->crtc_vsync_end << 16) | mode->crtc_vsync_start | EN_VSYNC_BIT;
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+		v_sync |= INV_VSYNC_BIT;
+
+	if (index == 0) {
+		lsdc_reg_write32(ldev, LSDC_CRTC0_FB_ORIGIN_REG, 0);
+		lsdc_reg_write32(ldev, LSDC_CRTC0_HDISPLAY_REG, h_val);
+		lsdc_reg_write32(ldev, LSDC_CRTC0_VDISPLAY_REG, v_val);
+		lsdc_reg_write32(ldev, LSDC_CRTC0_HSYNC_REG, h_sync);
+		lsdc_reg_write32(ldev, LSDC_CRTC0_VSYNC_REG, v_sync);
+	} else if (index == 1) {
+		lsdc_reg_write32(ldev, LSDC_CRTC1_FB_ORIGIN_REG, 0);
+		lsdc_reg_write32(ldev, LSDC_CRTC1_HDISPLAY_REG, h_val);
+		lsdc_reg_write32(ldev, LSDC_CRTC1_VDISPLAY_REG, v_val);
+		lsdc_reg_write32(ldev, LSDC_CRTC1_HSYNC_REG, h_sync);
+		lsdc_reg_write32(ldev, LSDC_CRTC1_VSYNC_REG, v_sync);
+	}
+
+	drm_dbg(ddev, "%s modeset: %ux%u\n", crtc->name, mode->hdisplay, mode->vdisplay);
+
+	lsdc_update_pixclk(crtc);
+}
+
+static void lsdc_enable_display(struct lsdc_device *ldev, unsigned int index)
+{
+	u32 val;
+
+	if (index == 0) {
+		val = lsdc_reg_read32(ldev, LSDC_CRTC0_CFG_REG);
+		val |= CFG_OUTPUT_EN_BIT;
+		lsdc_reg_write32(ldev, LSDC_CRTC0_CFG_REG, val);
+	} else if (index == 1) {
+		val = lsdc_reg_read32(ldev, LSDC_CRTC1_CFG_REG);
+		val |= CFG_OUTPUT_EN_BIT;
+		lsdc_reg_write32(ldev, LSDC_CRTC1_CFG_REG, val);
+	}
+}
+
+static void lsdc_disable_display(struct lsdc_device *ldev, unsigned int index)
+{
+	u32 val;
+
+	if (index == 0) {
+		val = lsdc_reg_read32(ldev, LSDC_CRTC0_CFG_REG);
+		val &= ~CFG_OUTPUT_EN_BIT;
+		lsdc_reg_write32(ldev, LSDC_CRTC0_CFG_REG, val);
+	} else if (index == 1) {
+		val = lsdc_reg_read32(ldev, LSDC_CRTC1_CFG_REG);
+		val &= ~CFG_OUTPUT_EN_BIT;
+		lsdc_reg_write32(ldev, LSDC_CRTC1_CFG_REG, val);
+	}
+}
+
+static void lsdc_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+					   struct drm_atomic_state *state)
+{
+	struct drm_device *ddev = crtc->dev;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+
+	drm_crtc_vblank_on(crtc);
+
+	lsdc_enable_display(ldev, drm_crtc_index(crtc));
+
+	drm_dbg(ddev, "%s: enabled\n", crtc->name);
+}
+
+static void lsdc_crtc_helper_atomic_disable(struct drm_crtc *crtc,
+					    struct drm_atomic_state *state)
+{
+	struct drm_device *ddev = crtc->dev;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+
+	drm_crtc_vblank_off(crtc);
+
+	lsdc_disable_display(ldev, drm_crtc_index(crtc));
+
+	drm_dbg(ddev, "%s: disabled\n", crtc->name);
+}
+
+static void lsdc_crtc_update_clut(struct drm_crtc *crtc)
+{
+	struct lsdc_device *ldev = to_lsdc(crtc->dev);
+	unsigned int index = drm_crtc_index(crtc);
+	struct drm_color_lut *lut;
+	unsigned int i;
+
+	if (!ldev->enable_gamma)
+		return;
+
+	if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut)
+		return;
+
+	lut = (struct drm_color_lut *)crtc->state->gamma_lut->data;
+
+	lsdc_reg_write32(ldev, LSDC_CRTC0_GAMMA_INDEX_REG, 0);
+
+	for (i = 0; i < 256; i++) {
+		u32 val = ((lut->red << 8) & 0xff0000) |
+			  (lut->green & 0xff00) |
+			  (lut->blue >> 8);
+
+		if (index == 0)
+			lsdc_reg_write32(ldev, LSDC_CRTC0_GAMMA_DATA_REG, val);
+		else if (index == 1)
+			lsdc_reg_write32(ldev, LSDC_CRTC1_GAMMA_DATA_REG, val);
+
+		lut++;
+	}
+}
+
+static void lsdc_crtc_atomic_flush(struct drm_crtc *crtc,
+				   struct drm_atomic_state *state)
+{
+	struct drm_pending_vblank_event *event = crtc->state->event;
+
+	lsdc_crtc_update_clut(crtc);
+
+	if (event) {
+		crtc->state->event = NULL;
+
+		spin_lock_irq(&crtc->dev->event_lock);
+		if (drm_crtc_vblank_get(crtc) == 0)
+			drm_crtc_arm_vblank_event(crtc, event);
+		else
+			drm_crtc_send_vblank_event(crtc, event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+	}
+}
+
+static const struct drm_crtc_helper_funcs lsdc_crtc_helper_funcs = {
+	.mode_valid = lsdc_crtc_helper_mode_valid,
+	.mode_set_nofb = lsdc_crtc_helper_mode_set_nofb,
+	.atomic_enable = lsdc_crtc_helper_atomic_enable,
+	.atomic_disable = lsdc_crtc_helper_atomic_disable,
+	.atomic_check = lsdc_crtc_helper_atomic_check,
+	.atomic_flush = lsdc_crtc_atomic_flush,
+};
+
+int lsdc_crtc_init(struct drm_device *ddev,
+		   struct drm_crtc *crtc,
+		   unsigned int index,
+		   struct drm_plane *primary,
+		   struct drm_plane *cursor)
+{
+	int ret;
+
+	ret = drm_crtc_init_with_planes(ddev, crtc, primary, cursor,
+					&lsdc_crtc_funcs, "crtc%d", index);
+
+	if (ret) {
+		drm_err(ddev, "crtc init with planes failed: %d\n", ret);
+		return ret;
+	}
+
+	drm_crtc_helper_add(crtc, &lsdc_crtc_helper_funcs);
+
+	ret = drm_mode_crtc_set_gamma_size(crtc, 256);
+	if (ret)
+		drm_warn(ddev, "set the gamma table size failed\n");
+
+	drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/lsdc/lsdc_drv.c b/drivers/gpu/drm/lsdc/lsdc_drv.c
new file mode 100644
index 000000000000..a26105d01d1d
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_drv.c
@@ -0,0 +1,547 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#include <linux/pci.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_aperture.h>
+#include <drm/drm_vblank.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
+
+#include "lsdc_drv.h"
+#include "lsdc_irq.h"
+#include "lsdc_regs.h"
+#include "lsdc_output.h"
+#include "lsdc_pll.h"
+#include "lsdc_i2c.h"
+
+#define DRIVER_AUTHOR		"Sui Jingfeng <suijingfeng@loongson.cn>"
+#define DRIVER_NAME		"lsdc"
+#define DRIVER_DESC		"drm driver for loongson's display controller"
+#define DRIVER_DATE		"20200701"
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	0
+
+static const struct lsdc_chip_desc dc_in_ls2k1000 = {
+	.chip = LSDC_CHIP_2K1000,
+	.num_of_crtc = LSDC_NUM_CRTC,
+	/* ls2k1000 user manual say the max pixel clock can be about 200MHz */
+	.max_pixel_clk = 200000,
+	.max_width = 2560,
+	.max_height = 2048,
+	.num_of_hw_cursor = 1,
+	.hw_cursor_w = 32,
+	.hw_cursor_h = 32,
+	.stride_alignment = 256,
+	.have_builtin_i2c = false,
+	.has_vram = false,
+};
+
+static const struct lsdc_chip_desc dc_in_ls2k0500 = {
+	.chip = LSDC_CHIP_2K0500,
+	.num_of_crtc = LSDC_NUM_CRTC,
+	.max_pixel_clk = 200000,
+	.max_width = 2048,
+	.max_height = 2048,
+	.num_of_hw_cursor = 1,
+	.hw_cursor_w = 32,
+	.hw_cursor_h = 32,
+	.stride_alignment = 256,
+	.have_builtin_i2c = false,
+	.has_vram = false,
+};
+
+static const struct lsdc_chip_desc dc_in_ls7a1000 = {
+	.chip = LSDC_CHIP_7A1000,
+	.num_of_crtc = LSDC_NUM_CRTC,
+	.max_pixel_clk = 200000,
+	.max_width = 2048,
+	.max_height = 2048,
+	.num_of_hw_cursor = 1,
+	.hw_cursor_w = 32,
+	.hw_cursor_h = 32,
+	.stride_alignment = 256,
+	.have_builtin_i2c = true,
+	.has_vram = true,
+};
+
+static enum drm_mode_status
+lsdc_device_mode_valid(struct drm_device *ddev, const struct drm_display_mode *mode)
+{
+	struct lsdc_device *ldev = to_lsdc(ddev);
+
+	if (ldev->use_vram_helper)
+		return drm_vram_helper_mode_valid(ddev, mode);
+
+	return MODE_OK;
+}
+
+static const struct drm_mode_config_funcs lsdc_mode_config_funcs = {
+	.fb_create = drm_gem_fb_create,
+	.output_poll_changed = drm_fb_helper_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+	.mode_valid = lsdc_device_mode_valid,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static int lsdc_show_clock(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *)m->private;
+	struct drm_device *ddev = node->minor->dev;
+	struct drm_crtc *crtc;
+
+	drm_for_each_crtc(crtc, ddev) {
+		struct lsdc_display_pipe *pipe;
+		struct lsdc_pll *pixpll;
+		const struct lsdc_pixpll_funcs *funcs;
+		struct lsdc_pll_core_values params;
+		unsigned int out_khz;
+		struct drm_display_mode *adj;
+
+		pipe = container_of(crtc, struct lsdc_display_pipe, crtc);
+		if (!pipe->available)
+			continue;
+
+		adj = &crtc->state->adjusted_mode;
+
+		pixpll = &pipe->pixpll;
+		funcs = pixpll->funcs;
+		out_khz = funcs->get_clock_rate(pixpll, &params);
+
+		seq_printf(m, "Display pipe %u: %dx%d\n",
+			   pipe->index, adj->hdisplay, adj->vdisplay);
+
+		seq_printf(m, "Frequency actually output: %u kHz\n", out_khz);
+		seq_printf(m, "Pixel clock required: %d kHz\n", adj->clock);
+		seq_printf(m, "diff: %d kHz\n", adj->clock);
+
+		seq_printf(m, "div_ref=%u, loopc=%u, div_out=%u\n",
+			   params.div_ref, params.loopc, params.div_out);
+
+		seq_printf(m, "hsync_start=%d, hsync_end=%d, htotal=%d\n",
+			   adj->hsync_start, adj->hsync_end, adj->htotal);
+		seq_printf(m, "vsync_start=%d, vsync_end=%d, vtotal=%d\n\n",
+			   adj->vsync_start, adj->vsync_end, adj->vtotal);
+	}
+
+	return 0;
+}
+
+static int lsdc_show_mm(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *)m->private;
+	struct drm_device *ddev = node->minor->dev;
+	struct drm_printer p = drm_seq_file_printer(m);
+
+	drm_mm_print(&ddev->vma_offset_manager->vm_addr_space_mm, &p);
+
+	return 0;
+}
+
+#define REGDEF(reg) { __stringify_1(LSDC_##reg##_REG), LSDC_##reg##_REG }
+static const struct {
+	const char *name;
+	u32 reg_offset;
+} lsdc_regs_array[] = {
+	REGDEF(INT),
+	REGDEF(CURSOR_CFG),
+	REGDEF(CURSOR_ADDR),
+	REGDEF(CURSOR_POSITION),
+	REGDEF(CURSOR_BG_COLOR),
+	REGDEF(CURSOR_FG_COLOR),
+	REGDEF(CRTC0_CFG),
+	REGDEF(CRTC0_FB_ADDR0),
+	REGDEF(CRTC0_FB_ADDR1),
+	REGDEF(CRTC0_FB_HI_ADDR),
+	REGDEF(CRTC0_STRIDE),
+	REGDEF(CRTC0_FB_ORIGIN),
+	REGDEF(CRTC0_HDISPLAY),
+	REGDEF(CRTC0_HSYNC),
+	REGDEF(CRTC0_VDISPLAY),
+	REGDEF(CRTC0_VSYNC),
+	REGDEF(CRTC0_GAMMA_INDEX),
+	REGDEF(CRTC0_GAMMA_DATA),
+	REGDEF(CRTC1_CFG),
+	REGDEF(CRTC1_FB_ADDR0),
+	REGDEF(CRTC1_FB_ADDR1),
+	REGDEF(CRTC1_FB_HI_ADDR),
+	REGDEF(CRTC1_STRIDE),
+	REGDEF(CRTC1_FB_ORIGIN),
+	REGDEF(CRTC1_HDISPLAY),
+	REGDEF(CRTC1_HSYNC),
+	REGDEF(CRTC1_VDISPLAY),
+	REGDEF(CRTC1_VSYNC),
+	REGDEF(CRTC1_GAMMA_INDEX),
+	REGDEF(CRTC1_GAMMA_DATA),
+};
+
+static int lsdc_show_regs(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *)m->private;
+	struct drm_device *ddev = node->minor->dev;
+	struct lsdc_device *ldev = ddev->dev_private;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lsdc_regs_array); i++) {
+		u32 offset = lsdc_regs_array[i].reg_offset;
+		const char *name = lsdc_regs_array[i].name;
+
+		seq_printf(m, "%s (0x%04x): 0x%08x\n",
+			   name, offset,
+			   readl(ldev->reg_base + offset));
+	}
+
+	return 0;
+}
+
+static struct drm_info_list lsdc_debugfs_list[] = {
+	{ "clocks", lsdc_show_clock, 0 },
+	{ "mm",     lsdc_show_mm,   0, NULL },
+	{ "regs",   lsdc_show_regs, 0 },
+};
+
+static void lsdc_debugfs_init(struct drm_minor *minor)
+{
+	drm_debugfs_create_files(lsdc_debugfs_list,
+				 ARRAY_SIZE(lsdc_debugfs_list),
+				 minor->debugfs_root,
+				 minor);
+}
+#endif
+
+static struct drm_gem_object *
+lsdc_drm_gem_create_object(struct drm_device *ddev, size_t size)
+{
+	struct drm_gem_cma_object *obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+
+	if (!obj)
+		return ERR_PTR(-ENOMEM);
+
+	obj->map_noncoherent = true;
+
+	return &obj->base;
+}
+
+static int lsdc_gem_cma_dumb_create(struct drm_file *file,
+				    struct drm_device *ddev,
+				    struct drm_mode_create_dumb *args)
+{
+	struct lsdc_device *ldev = to_lsdc(ddev);
+	const struct lsdc_chip_desc *desc = ldev->desc;
+	unsigned int bytes_per_pixel = (args->bpp + 7) / 8;
+	unsigned int pitch = bytes_per_pixel * args->width;
+
+	/*
+	 * The dc in ls7a1000/ls2k1000/ls2k0500 require the stride be a
+	 * multiple of 256 bytes which is for sake of optimize dma data
+	 * transfer.
+	 */
+	args->pitch = roundup(pitch, desc->stride_alignment);
+
+	return drm_gem_cma_dumb_create_internal(file, ddev, args);
+}
+
+DEFINE_DRM_GEM_CMA_FOPS(lsdc_drv_fops);
+
+static const struct drm_driver lsdc_drm_driver_cma_stub = {
+	.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+	.lastclose = drm_fb_helper_lastclose,
+	.fops = &lsdc_drv_fops,
+	.gem_create_object = lsdc_drm_gem_create_object,
+
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+	.date = DRIVER_DATE,
+	.major = DRIVER_MAJOR,
+	.minor = DRIVER_MINOR,
+	.patchlevel = DRIVER_PATCHLEVEL,
+
+	DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(lsdc_gem_cma_dumb_create),
+
+#ifdef CONFIG_DEBUG_FS
+	.debugfs_init = lsdc_debugfs_init,
+#endif
+};
+
+DEFINE_DRM_GEM_FOPS(lsdc_gem_fops);
+
+static const struct drm_driver lsdc_vram_driver_stub = {
+	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
+	.fops = &lsdc_gem_fops,
+
+	.name = "loongson",
+	.desc = DRIVER_DESC,
+	.date = DRIVER_DATE,
+	.major = DRIVER_MAJOR,
+	.minor = DRIVER_MINOR,
+	.patchlevel = DRIVER_PATCHLEVEL,
+
+	DRM_GEM_VRAM_DRIVER,
+};
+
+static int lsdc_modeset_init(struct lsdc_device *ldev, uint32_t num_crtc)
+{
+	struct drm_device *ddev = ldev->ddev;
+	struct device_node *ports;
+	unsigned int i;
+	int ret;
+
+	ports = of_get_child_by_name(ldev->dev->of_node, "ports");
+
+	if (ports) {
+		drm_dbg(ddev, "Has ports node in DT\n");
+		ret = lsdc_attach_output(ldev, ports, num_crtc);
+		if (ret) {
+			of_node_put(ports);
+			return ret;
+		}
+	} else {
+		drm_dbg(ddev, "No ports node in DT\n");
+		for (i = 0; i < num_crtc; i++) {
+			ret = lsdc_create_output(ldev, i, num_crtc);
+			if (ret)
+				return ret;
+		}
+	}
+
+	for (i = 0; i < num_crtc; i++) {
+		struct lsdc_display_pipe * const dispipe = &ldev->disp_pipe[i];
+		struct drm_plane * const primary = &dispipe->primary;
+		struct drm_plane * const cursor = &dispipe->cursor;
+		struct drm_crtc * const crtc = &dispipe->crtc;
+		struct lsdc_pll * const pixpll = &dispipe->pixpll;
+
+		dispipe->index = i;
+
+		ret = lsdc_pixpll_init(pixpll, ddev, i);
+		if (ret)
+			return ret;
+
+		ret = lsdc_plane_init(ldev, primary, DRM_PLANE_TYPE_PRIMARY, i);
+		if (ret)
+			return ret;
+
+		ret = lsdc_plane_init(ldev, cursor, DRM_PLANE_TYPE_CURSOR, i);
+		if (ret)
+			return ret;
+
+		/*
+		 * Initial all of the CRTC available, in this way the crtc
+		 * index is equal to the hardware crtc index. That is:
+		 * display pipe 0 => crtc0 + dvo0 + encoder0
+		 * display pipe 1 => crtc1 + dvo1 + encoder1
+		 */
+		ret = lsdc_crtc_init(ddev, crtc, i, primary, cursor);
+		if (ret)
+			return ret;
+
+		drm_info(ddev, "display pipe %u initialized\n", i);
+	}
+
+	return 0;
+}
+
+static int lsdc_mode_config_init(struct lsdc_device *ldev)
+{
+	const struct lsdc_chip_desc * const descp = ldev->desc;
+	struct drm_device *ddev = ldev->ddev;
+	int ret;
+
+	ret = drmm_mode_config_init(ddev);
+	if (ret)
+		return ret;
+
+	ddev->mode_config.funcs = &lsdc_mode_config_funcs;
+	ddev->mode_config.min_width = 1;
+	ddev->mode_config.min_height = 1;
+	ddev->mode_config.max_width = 4096;
+	ddev->mode_config.max_height = 4096;
+	ddev->mode_config.preferred_depth = 24;
+	ddev->mode_config.prefer_shadow = ldev->use_vram_helper;
+
+	ddev->mode_config.cursor_width = descp->hw_cursor_h;
+	ddev->mode_config.cursor_height = descp->hw_cursor_h;
+
+	if (ldev->vram_base)
+		ddev->mode_config.fb_base = ldev->vram_base;
+
+	return lsdc_modeset_init(ldev, descp->num_of_crtc);
+}
+
+static void lsdc_mode_config_fini(struct drm_device *ddev)
+{
+	drm_atomic_helper_shutdown(ddev);
+
+	drm_mode_config_cleanup(ddev);
+}
+
+/*
+ * lsdc_detect_chip - a function to tell different chips apart.
+ */
+const struct lsdc_chip_desc *
+lsdc_detect_chip(struct pci_dev *pdev, const struct pci_device_id * const ent)
+{
+	static const struct lsdc_match {
+		char name[128];
+		const void *data;
+	} compat[] = {
+		{ .name = "loongson,ls7a1000-dc", .data = &dc_in_ls7a1000 },
+		{ .name = "loongson,ls2k1000-dc", .data = &dc_in_ls2k1000 },
+		{ .name = "loongson,ls2k0500-dc", .data = &dc_in_ls2k0500 },
+		{ .name = "loongson,loongson64c-4core-ls7a", .data = &dc_in_ls7a1000 },
+		{ .name = "loongson,loongson64g-4core-ls7a", .data = &dc_in_ls7a1000 },
+		{ .name = "loongson,loongson64-2core-2k1000", .data = &dc_in_ls2k1000 },
+		{ .name = "loongson,loongson2k1000", .data = &dc_in_ls2k1000 },
+		{ /* sentinel */ },
+	};
+
+	struct device_node *np;
+	unsigned int i;
+
+	/* Deduce DC variant information from the DC device node */
+	for (i = 0; i < ARRAY_SIZE(compat); ++i) {
+		np = of_find_compatible_node(NULL, NULL, compat[i].name);
+		if (!np)
+			continue;
+
+		of_node_put(np);
+
+		return compat[i].data;
+	}
+
+	dev_info(&pdev->dev, "No Compatible Device Node Found\n");
+
+	if (pci_get_device(PCI_VENDOR_ID_LOONGSON, 0x7A15, NULL))
+		return &dc_in_ls7a1000;
+	else if (pci_get_device(PCI_VENDOR_ID_LOONGSON, 0x7A05, NULL))
+		return &dc_in_ls2k1000;
+
+	return NULL;
+}
+
+static int lsdc_remove_conflicting_framebuffers(const struct drm_driver *drv)
+{
+	/* lsdc is a pci device, but it don't have a dedicate vram bar because
+	 * of historic reason. The display controller is ported from Loongson
+	 * 2H series SoC which date back to 2012.
+	 * And simplefb node may have been located anywhere in memory.
+	 */
+	return drm_aperture_remove_conflicting_framebuffers(0, ~0, false, drv);
+}
+
+static int lsdc_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct lsdc_device *ldev = dev_get_drvdata(dev->parent);
+	const struct drm_driver *driver;
+	struct drm_device *ddev;
+	int ret;
+
+	if (ldev->use_vram_helper)
+		driver = &lsdc_vram_driver_stub;
+	else
+		driver = &lsdc_drm_driver_cma_stub;
+
+	lsdc_remove_conflicting_framebuffers(driver);
+
+	ddev = drm_dev_alloc(driver, dev);
+	if (IS_ERR(ddev))
+		return PTR_ERR(ddev);
+
+	platform_set_drvdata(pdev, ddev);
+
+	ddev->dev_private = ldev;
+	ldev->ddev = ddev;
+
+	if (ldev->use_vram_helper) {
+		drmm_vram_helper_init(ddev, ldev->vram_base, ldev->vram_size);
+		if (ret) {
+			drm_err(ddev, "vram helper init failed: %d\n", ret);
+				goto err_kms;
+		}
+	};
+
+	ret = lsdc_mode_config_init(ldev);
+	if (ret) {
+		drm_dbg(ddev, "%s: %d\n", __func__, ret);
+		goto err_kms;
+	}
+
+	ret = devm_request_threaded_irq(dev, ldev->irq,
+					lsdc_irq_handler_cb,
+					lsdc_irq_thread_cb,
+					IRQF_ONESHOT, dev_name(dev), ddev);
+	if (ret) {
+		dev_err(dev, "Failed to register lsdc interrupt\n");
+		return ret;
+	}
+
+	ret = drm_vblank_init(ddev, ldev->desc->num_of_crtc);
+	if (ret)
+		goto err_kms;
+
+	drm_mode_config_reset(ddev);
+
+	drm_kms_helper_poll_init(ddev);
+
+	ret = drm_dev_register(ddev, 0);
+	if (ret)
+		goto err_poll_fini;
+
+	drm_fbdev_generic_setup(ddev, 32);
+
+	return 0;
+
+err_poll_fini:
+	drm_kms_helper_poll_fini(ddev);
+err_kms:
+	drm_dev_put(ddev);
+
+	return ret;
+}
+
+static int lsdc_platform_remove(struct platform_device *pdev)
+{
+	struct drm_device *ddev = platform_get_drvdata(pdev);
+	struct lsdc_device *ldev = to_lsdc(ddev);
+
+	drm_dev_unregister(ddev);
+
+	drm_kms_helper_poll_fini(ddev);
+
+	devm_free_irq(ddev->dev, ldev->irq, ddev);
+
+	lsdc_mode_config_fini(ddev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	drm_dev_put(ddev);
+
+	return 0;
+}
+
+struct platform_driver lsdc_platform_driver = {
+	.probe = lsdc_platform_probe,
+	.remove = lsdc_platform_remove,
+	.driver = {
+		.name = "lsdc",
+	},
+};
diff --git a/drivers/gpu/drm/lsdc/lsdc_drv.h b/drivers/gpu/drm/lsdc/lsdc_drv.h
new file mode 100644
index 000000000000..d03ef6ee649e
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_drv.h
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#ifndef __LSDC_DRV_H__
+#define __LSDC_DRV_H__
+
+#include <drm/drm_print.h>
+#include <drm/drm_device.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_atomic.h>
+
+#include "lsdc_regs.h"
+#include "lsdc_pll.h"
+
+#define LSDC_NUM_CRTC           2
+
+/* There is only a 1:1 mapping of encoders and connectors for lsdc,
+ * Each CRTC have two FB address registers.
+ *
+ * The display controller in LS2K1000/LS2K0500.
+ *       ___________________                                     _________
+ *      |            -------|                                   |         |
+ *      |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
+ *      |  _   _     -------|        ^              ^           |_________|
+ *      | | | | |           |        |              |
+ *      | |_| |_|           |     +------+          |
+ *      |                   <---->| i2c0 |<---------+
+ *      |          LSDC     |     +------+
+ *      |  _   _            |     +------+
+ *      | | | | |           <---->| i2c1 |----------+
+ *      | |_| |_|           |     +------+          |            _________
+ *      |            -------|        |              |           |         |
+ *      |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
+ *      |            -------|                                   |_________|
+ *      |___________________|
+ *
+ *
+ * The display controller in LS7A1000.
+ *       ___________________                                     _________
+ *      |            -------|                                   |         |
+ *      |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
+ *      |  _   _     -------|        ^             ^            |_________|
+ *      | | | | |    -------|        |             |
+ *      | |_| |_|    | i2c0 <--------+-------------+
+ *      |            -------|
+ *      |  _   _     -------|
+ *      | | | | |    | i2c1 <--------+-------------+
+ *      | |_| |_|    -------|        |             |             _________
+ *      |            -------|        |             |            |         |
+ *      |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
+ *      |            -------|                                   |_________|
+ *      |___________________|
+ */
+
+enum loongson_dc_family {
+	LSDC_CHIP_UNKNOWN = 0,
+	LSDC_CHIP_2K1000 = 1,  /* 2-Core Mips64r2 SoC, 64-bit */
+	LSDC_CHIP_7A1000 = 2,  /* North bridge of LS3A3000/LS3A4000/LS3A5000 */
+	LSDC_CHIP_2K0500 = 3,  /* Reduced version of LS2K1000, single core */
+	LSDC_CHIP_LAST,
+};
+
+struct lsdc_chip_desc {
+	enum loongson_dc_family chip;
+	u32 num_of_crtc;
+	u32 max_pixel_clk;
+	u32 max_width;
+	u32 max_height;
+	u32 num_of_hw_cursor;
+	u32 hw_cursor_w;
+	u32 hw_cursor_h;
+	/* DMA alignment constraint (must be a power of 256) */
+	u32 stride_alignment;
+	bool have_builtin_i2c;
+	bool has_vram;
+};
+
+struct lsdc_output {
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+};
+
+/*
+ * struct lsdc_display_pipe - Abstraction of hardware display pipeline.
+ * @crtc: CRTC control structure
+ * @plane: Plane control structure
+ * @encoder: Encoder control structure
+ * @pixpll: Pll control structure
+ * @connector: point to connector control structure this display pipe bind
+ * @index: the index corresponding to the hardware display pipe
+ * @available: is this display pipe is available on the motherboard, The
+ *  downstream mother board manufacturer may use only one of them.
+ *  For example, LEMOTE LX-6901 board just has only one VGA output.
+ *
+ * Display pipeline with plane, crtc, encoder, PLL collapsed into one entity.
+ */
+struct lsdc_display_pipe {
+	struct drm_crtc crtc;
+	struct drm_plane primary;
+	struct drm_plane cursor;
+	struct lsdc_pll pixpll;
+	struct lsdc_output *output;
+	int index;
+	bool available;
+};
+
+struct lsdc_crtc_state {
+	struct drm_crtc_state base;
+	struct lsdc_pll_core_values pparams;
+};
+
+struct lsdc_device {
+	struct device *dev;
+	struct drm_device *ddev;
+	struct lsdc_i2c *li2c[LSDC_NUM_CRTC];
+	/* dc core */
+	struct platform_device *dc;
+
+	/* LS7A1000 has a dediacted video RAM, typically 64 MB or more */
+	void __iomem *reg_base;
+	void __iomem *vram;
+	resource_size_t vram_base;
+	resource_size_t vram_size;
+
+	struct lsdc_display_pipe disp_pipe[LSDC_NUM_CRTC];
+
+	/*
+	 * @num_output: count the number of active display pipe.
+	 */
+	unsigned int num_output;
+
+	/* @desc: device dependent data and feature descriptions */
+	const struct lsdc_chip_desc *desc;
+
+	int irq;
+	u32 irq_status;
+
+	/*
+	 * @use_vram_helper: using vram helper base solution instead of
+	 * CMA helper based solution. The DC scanout from the VRAM is
+	 * proved to be more reliable, but graphic application is may
+	 * become slow when using this driver mode.
+	 */
+	bool use_vram_helper;
+	bool enable_gamma;
+	bool relax_alignment;
+};
+
+static inline struct lsdc_device *to_lsdc(struct drm_device *ddev)
+{
+	return ddev->dev_private;
+}
+
+static inline struct lsdc_crtc_state *
+to_lsdc_crtc_state(struct drm_crtc_state *base)
+{
+	return container_of(base, struct lsdc_crtc_state, base);
+}
+
+static inline u32 lsdc_reg_read32(struct lsdc_device * const ldev, u32 offset)
+{
+	return readl(ldev->reg_base + offset);
+}
+
+static inline void
+lsdc_reg_write32(struct lsdc_device * const ldev, u32 offset, u32 val)
+{
+	return writel(val, ldev->reg_base + offset);
+}
+
+int lsdc_crtc_init(struct drm_device *ddev,
+		   struct drm_crtc *crtc,
+		   unsigned int index,
+		   struct drm_plane *primary,
+		   struct drm_plane *cursor);
+
+int lsdc_plane_init(struct lsdc_device *ldev, struct drm_plane *plane,
+		    enum drm_plane_type type, unsigned int index);
+
+const struct lsdc_chip_desc *
+lsdc_detect_chip(struct pci_dev *pdev, const struct pci_device_id * const ent);
+
+extern struct platform_driver lsdc_platform_driver;
+
+#endif
diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.c b/drivers/gpu/drm/lsdc/lsdc_i2c.c
new file mode 100644
index 000000000000..55beed9266fa
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_i2c.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#include <linux/i2c.h>
+#include <linux/pci.h>
+
+#include "lsdc_drv.h"
+#include "lsdc_regs.h"
+#include "lsdc_i2c.h"
+
+/*
+ * ls7a_gpio_i2c_set - set the state of a gpio pin indicated by mask
+ * @mask: gpio pin mask
+ */
+static void ls7a_gpio_i2c_set(struct lsdc_i2c * const li2c, int mask, int state)
+{
+	unsigned long flags;
+	u8 val;
+
+	spin_lock_irqsave(&li2c->reglock, flags);
+
+	if (state) {
+		val = readb(li2c->dir_reg);
+		val |= mask;
+		writeb(val, li2c->dir_reg);
+	} else {
+		val = readb(li2c->dir_reg);
+		val &= ~mask;
+		writeb(val, li2c->dir_reg);
+
+		val = readb(li2c->dat_reg);
+		if (state)
+			val |= mask;
+		else
+			val &= ~mask;
+		writeb(val, li2c->dat_reg);
+	}
+
+	spin_unlock_irqrestore(&li2c->reglock, flags);
+}
+
+/*
+ * ls7a_gpio_i2c_get - read value back from gpio pin
+ * @mask: gpio pin mask
+ */
+static int ls7a_gpio_i2c_get(struct lsdc_i2c * const li2c, int mask)
+{
+	unsigned long flags;
+	u8 val;
+
+	spin_lock_irqsave(&li2c->reglock, flags);
+
+	/* first set this pin as input */
+	val = readb(li2c->dir_reg);
+	val |= mask;
+	writeb(val, li2c->dir_reg);
+
+	/* then get level state from this pin */
+	val = readb(li2c->dat_reg);
+
+	spin_unlock_irqrestore(&li2c->reglock, flags);
+
+	return (val & mask) ? 1 : 0;
+}
+
+/* set the state on the i2c->sda pin */
+static void ls7a_i2c_set_sda(void *i2c, int state)
+{
+	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
+
+	return ls7a_gpio_i2c_set(li2c, li2c->sda, state);
+}
+
+/* set the state on the i2c->scl pin */
+static void ls7a_i2c_set_scl(void *i2c, int state)
+{
+	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
+
+	return ls7a_gpio_i2c_set(li2c, li2c->scl, state);
+}
+
+/* read the value from the i2c->sda pin */
+static int ls7a_i2c_get_sda(void *i2c)
+{
+	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
+
+	return ls7a_gpio_i2c_get(li2c, li2c->sda);
+}
+
+/* read the value from the i2c->scl pin */
+static int ls7a_i2c_get_scl(void *i2c)
+{
+	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
+
+	return ls7a_gpio_i2c_get(li2c, li2c->scl);
+}
+
+/*
+ * mainly for dc in ls7a1000 which have builtin gpio emulated i2c
+ *
+ * @index : output channel index, 0 for DVO0, 1 for DVO1
+ */
+struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev, void *base, unsigned int index)
+{
+	char compat[32] = {0};
+	unsigned int udelay = 5;
+	unsigned int timeout = 2200;
+	int nr = -1;
+	struct i2c_adapter *adapter;
+	struct lsdc_i2c *li2c;
+	struct device_node *i2c_np;
+	int ret;
+
+	li2c = devm_kzalloc(dev, sizeof(*li2c), GFP_KERNEL);
+	if (!li2c)
+		return ERR_PTR(-ENOMEM);
+
+	li2c->index = index;
+	li2c->dev = dev;
+
+	if (index == 0) {
+		li2c->sda = 0x01;
+		li2c->scl = 0x02;
+	} else if (index == 1) {
+		li2c->sda = 0x04;
+		li2c->scl = 0x08;
+	}
+
+	spin_lock_init(&li2c->reglock);
+
+	snprintf(compat, sizeof(compat), "lsdc,i2c-gpio-%d", index);
+	i2c_np = of_find_compatible_node(dev->of_node, NULL, compat);
+	if (i2c_np) {
+		u32 sda, scl;
+
+		dev_dbg(dev, "Has %s property in the DT", compat);
+
+		/*  */
+		ret = of_property_read_u32(i2c_np, "sda", &sda);
+		if (ret == 0)
+			li2c->sda = 1 << sda;
+
+		ret = of_property_read_u32(i2c_np, "scl", &scl);
+		if (ret == 0)
+			li2c->scl = 1 << scl;
+
+		/* Optional properties which made the driver more flexible */
+		of_property_read_u32(i2c_np, "udelay", &udelay);
+		of_property_read_u32(i2c_np, "timeout", &timeout);
+		of_property_read_u32(i2c_np, "reg", &nr);
+	}
+
+	dev_dbg(dev, "%s: sda=%u, scl=%u, nr=%d, udelay=%u, timeout=%u\n",
+		compat, li2c->sda, li2c->scl, nr, udelay, timeout);
+
+	li2c->reg_base = base;
+
+	li2c->dir_reg = li2c->reg_base + LS7A_DC_GPIO_DIR_REG;
+	li2c->dat_reg = li2c->reg_base + LS7A_DC_GPIO_DAT_REG;
+
+	li2c->bit.setsda = ls7a_i2c_set_sda;
+	li2c->bit.setscl = ls7a_i2c_set_scl;
+	li2c->bit.getsda = ls7a_i2c_get_sda;
+	li2c->bit.getscl = ls7a_i2c_get_scl;
+	li2c->bit.udelay = udelay;
+	li2c->bit.timeout = usecs_to_jiffies(timeout);
+	li2c->bit.data = li2c;
+
+	adapter = &li2c->adapter;
+	adapter->algo_data = &li2c->bit;
+	adapter->owner = THIS_MODULE;
+	adapter->class = I2C_CLASS_DDC;
+	adapter->dev.parent = dev;
+	adapter->nr = nr;
+	if (i2c_np) {
+		adapter->dev.of_node = i2c_np;
+		of_node_put(i2c_np);
+	}
+
+	strscpy(adapter->name, &compat[5], sizeof(adapter->name));
+
+	i2c_set_adapdata(adapter, li2c);
+
+	ret = i2c_bit_add_numbered_bus(adapter);
+	if (ret) {
+		if (i2c_np)
+			of_node_put(i2c_np);
+
+		devm_kfree(dev, li2c);
+		return ERR_PTR(ret);
+	}
+
+	return li2c;
+}
+
+void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c)
+{
+	struct i2c_adapter *adapter;
+
+	if (li2c) {
+		adapter = &li2c->adapter;
+
+		if (adapter && adapter->dev.of_node)
+			of_node_put(adapter->dev.of_node);
+
+		devm_kfree(ddev->dev, li2c);
+	}
+}
+
+struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
+					 unsigned int index)
+{
+	const struct lsdc_chip_desc * const descp = ldev->desc;
+	struct lsdc_i2c *li2c;
+
+	if (index >= descp->num_of_crtc) {
+		drm_err(ldev->ddev, "I2c adapter is no more than %u, %u\n",
+			descp->num_of_crtc, index);
+		return NULL;
+	}
+
+	li2c = ldev->li2c[index];
+	if (li2c)
+		return &li2c->adapter;
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.h b/drivers/gpu/drm/lsdc/lsdc_i2c.h
new file mode 100644
index 000000000000..4ab825143eb4
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_i2c.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#ifndef __LSDC_I2C__
+#define __LSDC_I2C__
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/pci.h>
+
+struct lsdc_i2c {
+	struct device *dev;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data bit;
+	/* @reglock: protects concurrent register access */
+	spinlock_t reglock;
+	void __iomem *reg_base;
+	void __iomem *dir_reg;
+	void __iomem *dat_reg;
+	int index;
+	/* pin bit mask */
+	u8 sda;
+	u8 scl;
+};
+
+void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c);
+
+struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev,
+				      void *base,
+				      unsigned int index);
+
+struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
+					 unsigned int index);
+#endif
diff --git a/drivers/gpu/drm/lsdc/lsdc_irq.c b/drivers/gpu/drm/lsdc/lsdc_irq.c
new file mode 100644
index 000000000000..82fb877f3608
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_irq.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#include <drm/drm_vblank.h>
+
+#include "lsdc_drv.h"
+#include "lsdc_regs.h"
+#include "lsdc_irq.h"
+
+/* Function to be called in a threaded interrupt context. */
+irqreturn_t lsdc_irq_thread_cb(int irq, void *arg)
+{
+	struct drm_device *ddev = arg;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+	struct drm_crtc *crtc;
+
+	/* trigger the vblank event */
+	if (ldev->irq_status & INT_CRTC0_VS) {
+		crtc = drm_crtc_from_index(ddev, 0);
+		drm_crtc_handle_vblank(crtc);
+	}
+
+	if (ldev->irq_status & INT_CRTC1_VS) {
+		crtc = drm_crtc_from_index(ddev, 1);
+		drm_crtc_handle_vblank(crtc);
+	}
+
+	lsdc_reg_write32(ldev, LSDC_INT_REG, INT_CRTC0_VS_EN | INT_CRTC1_VS_EN);
+
+	return IRQ_HANDLED;
+}
+
+/* Function to be called when the IRQ occurs */
+irqreturn_t lsdc_irq_handler_cb(int irq, void *arg)
+{
+	struct drm_device *ddev = arg;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+
+	/* Read & Clear the interrupt status */
+	ldev->irq_status = lsdc_reg_read32(ldev, LSDC_INT_REG);
+	if ((ldev->irq_status & INT_STATUS_MASK) == 0) {
+		drm_warn(ddev, "no interrupt occurs\n");
+		return IRQ_NONE;
+	}
+
+	/* clear all interrupt */
+	lsdc_reg_write32(ldev, LSDC_INT_REG, ldev->irq_status);
+
+	return IRQ_WAKE_THREAD;
+}
diff --git a/drivers/gpu/drm/lsdc/lsdc_irq.h b/drivers/gpu/drm/lsdc/lsdc_irq.h
new file mode 100644
index 000000000000..40058515fe42
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_irq.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#ifndef __LSDC_IRQ_H__
+#define __LSDC_IRQ_H__
+
+irqreturn_t lsdc_irq_thread_cb(int irq, void *arg);
+irqreturn_t lsdc_irq_handler_cb(int irq, void *arg);
+
+#endif
diff --git a/drivers/gpu/drm/lsdc/lsdc_output.c b/drivers/gpu/drm/lsdc/lsdc_output.c
new file mode 100644
index 000000000000..3ff9abf6ffd7
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_output.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#include <drm/drm_of.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_bridge_connector.h>
+
+#include "lsdc_drv.h"
+#include "lsdc_i2c.h"
+#include "lsdc_output.h"
+
+static int lsdc_get_modes(struct drm_connector *connector)
+{
+	unsigned int num = 0;
+	struct edid *edid;
+
+	if (!IS_ERR_OR_NULL(connector->ddc)) {
+		edid = drm_get_edid(connector, connector->ddc);
+		if (edid) {
+			drm_connector_update_edid_property(connector, edid);
+			num = drm_add_edid_modes(connector, edid);
+			kfree(edid);
+		}
+
+		return num;
+	}
+	/*
+	 * In case we cannot retrieve the EDIDs (broken or missing i2c
+	 * bus), fallback on the XGA standards.
+	 */
+	num = drm_add_modes_noedid(connector, 1920, 1200);
+
+	/* And prefer a mode pretty much anyone can handle */
+	drm_set_preferred_mode(connector, 1024, 768);
+
+	return num;
+}
+
+static enum drm_connector_status
+lsdc_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct i2c_adapter *ddc = connector->ddc;
+
+	if (ddc && drm_probe_ddc(ddc))
+		return connector_status_connected;
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
+		return connector_status_connected;
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_DPI)
+		return connector_status_connected;
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_DVIA ||
+	    connector->connector_type == DRM_MODE_CONNECTOR_DVID ||
+	    connector->connector_type == DRM_MODE_CONNECTOR_DVII)
+		return connector_status_disconnected;
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+	    connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)
+		return connector_status_disconnected;
+
+	return connector_status_unknown;
+}
+
+static void lsdc_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_helper_funcs lsdc_connector_helpers = {
+	.get_modes = lsdc_get_modes,
+};
+
+static const struct drm_connector_funcs lsdc_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = lsdc_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = lsdc_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int lsdc_attach_bridges(struct lsdc_device *ldev,
+			       struct device_node *ports,
+			       unsigned int i)
+{
+	struct lsdc_display_pipe * const dispipe = &ldev->disp_pipe[i];
+	struct drm_device *ddev = ldev->ddev;
+	struct drm_bridge *bridge;
+	struct drm_panel *panel;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct lsdc_output *output;
+	int ret;
+
+	ret = drm_of_find_panel_or_bridge(ports, i, 0, &panel, &bridge);
+
+	if (panel) {
+		bridge = devm_drm_panel_bridge_add_typed(ddev->dev, panel, DRM_MODE_CONNECTOR_DPI);
+		drm_info(ddev, "output-%u is a dpi panel\n", i);
+	}
+
+	if (!bridge)
+		return ret;
+
+	output = drmm_encoder_alloc(ddev, struct lsdc_output, encoder,
+				    NULL, DRM_MODE_ENCODER_DPI,
+				    "encoder-%u", i);
+	if (IS_ERR(output)) {
+		ret = PTR_ERR(output);
+		drm_err(ddev, "Failed to init encoder: %d\n", ret);
+		return ret;
+	}
+
+	encoder = &output->encoder;
+	encoder->possible_crtcs = BIT(i);
+
+	ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+	if (ret) {
+		drm_err(ddev,
+			"failed to attach bridge %pOF for output %u (%d)\n",
+			bridge->of_node, i, ret);
+		return ret;
+	}
+
+	connector = drm_bridge_connector_init(ddev, encoder);
+	if (IS_ERR(connector)) {
+		drm_err(ddev, "Unable to init connector\n");
+		return PTR_ERR(connector);
+	}
+
+	drm_connector_attach_encoder(connector, encoder);
+
+	drm_info(ddev, "bridge-%u attached to %s\n", i, encoder->name);
+
+	dispipe->output = output;
+
+	return 0;
+}
+
+int lsdc_attach_output(struct lsdc_device *ldev,
+		       struct device_node *ports,
+		       uint32_t num_crtc)
+{
+	struct drm_device *ddev = ldev->ddev;
+	struct lsdc_display_pipe *disp;
+	struct drm_bridge *b;
+	struct drm_panel *p;
+	unsigned int i;
+	int ret;
+
+	ldev->num_output = 0;
+
+	if (!ports)
+		drm_err(ddev, "valid ports node is required\n");
+
+	for (i = 0; i < num_crtc; i++) {
+		disp = &ldev->disp_pipe[i];
+		disp->available = false;
+
+		ret = drm_of_find_panel_or_bridge(ports, i, 0, &p, &b);
+		if (ret) {
+			if (ret == -ENODEV) {
+				drm_dbg(ddev, "No active panel or bridge for port%u\n", i);
+				disp->available = false;
+				continue;
+			}
+
+			if (ret == -EPROBE_DEFER)
+				drm_dbg(ddev, "Bridge for port%d is defer probed\n", i);
+
+			return ret;
+		}
+
+		disp->available = true;
+		ldev->num_output++;
+	}
+
+	drm_info(ddev, "number of outputs: %u\n", ldev->num_output);
+
+	if (ldev->num_output == 0) {
+		drm_err(ddev, "No valid output, abort\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < num_crtc; i++) {
+		disp = &ldev->disp_pipe[i];
+		if (disp->available) {
+			ret = lsdc_attach_bridges(ldev, ports, i);
+			if (ret)
+				return ret;
+		} else {
+			drm_info(ddev, "output-%u is not available\n", i);
+		}
+	}
+
+	return 0;
+}
+
+/* No DT support, provide a minimal support */
+int lsdc_create_output(struct lsdc_device *ldev, unsigned int index, unsigned int num_crtc)
+{
+	const struct lsdc_chip_desc * const descp = ldev->desc;
+	struct lsdc_display_pipe * const dispipe = &ldev->disp_pipe[index];
+	struct drm_device *ddev = ldev->ddev;
+	struct i2c_adapter *ddc = NULL;
+	struct lsdc_output *output;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	int ret;
+
+	output = drmm_encoder_alloc(ddev, struct lsdc_output, encoder,
+				    NULL, DRM_MODE_ENCODER_DPI,
+				    "encoder-%u", index);
+	if (IS_ERR(output)) {
+		ret = PTR_ERR(output);
+		drm_err(ddev, "Failed to init encoder: %d\n", ret);
+		return ret;
+	}
+
+	encoder = &output->encoder;
+	encoder->possible_crtcs = BIT(index);
+
+	if (descp->have_builtin_i2c)
+		ddc = lsdc_get_i2c_adapter(ldev, index);
+
+	connector = &output->connector;
+	connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+
+	ret = drm_connector_init_with_ddc(ddev,
+					  connector,
+					  &lsdc_connector_funcs,
+					  DRM_MODE_CONNECTOR_DPI,
+					  ddc);
+	if (ret) {
+		drm_err(ddev, "Init connector%d failed\n", index);
+		return ret;
+	}
+
+	drm_connector_helper_add(connector, &lsdc_connector_helpers);
+
+	drm_connector_attach_encoder(connector, encoder);
+
+	dispipe->available = true;
+	dispipe->output = output;
+	ldev->num_output++;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/lsdc/lsdc_output.h b/drivers/gpu/drm/lsdc/lsdc_output.h
new file mode 100644
index 000000000000..4ca34c0ccba5
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_output.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#ifndef __LSDC_OUTPUT_H__
+#define __LSDC_OUTPUT_H__
+
+#include <drm/drm_device.h>
+#include <drm/drm_connector.h>
+
+int lsdc_create_output(struct lsdc_device *ldev, unsigned int i, unsigned int num_crtc);
+
+int lsdc_attach_output(struct lsdc_device *ldev,
+		       struct device_node *ports,
+		       uint32_t num_crtc);
+
+#endif
diff --git a/drivers/gpu/drm/lsdc/lsdc_pci_drv.c b/drivers/gpu/drm/lsdc/lsdc_pci_drv.c
new file mode 100644
index 000000000000..b3c746e9791b
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_pci_drv.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_modeset_helper.h>
+
+#include "lsdc_drv.h"
+#include "lsdc_i2c.h"
+
+static int lsdc_use_vram_helper = -1;
+MODULE_PARM_DESC(use_vram_helper, "Using vram helper based driver(0 = disabled)");
+module_param_named(use_vram_helper, lsdc_use_vram_helper, int, 0644);
+
+static int lsdc_gamma = -1;
+MODULE_PARM_DESC(gamma, "enable gamma (-1 = disabled (default), >0 = enabled)");
+module_param_named(gamma, lsdc_gamma, int, 0644);
+
+static int lsdc_relax_alignment = -1;
+MODULE_PARM_DESC(relax_alignment,
+		 "relax crtc stride alignment (-1 = disabled (default), >0 = enabled)");
+module_param_named(relax_alignment, lsdc_relax_alignment, int, 0644);
+
+#define DRIVER_AUTHOR		"Sui Jingfeng <suijingfeng@loongson.cn>"
+#define DRIVER_NAME		"lsdc"
+#define DRIVER_DESC		"drm driver for loongson's display controller"
+#define DRIVER_DATE		"20200701"
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	0
+
+static struct platform_device *
+lsdc_create_platform_device(const char *name,
+			    struct device *parent,
+			    const struct lsdc_chip_desc *descp,
+			    struct resource *res)
+{
+	struct device *dev;
+	struct platform_device *pdev;
+	int ret;
+
+	pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
+	if (!pdev) {
+		dev_err(parent, "can not create platform device\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dev_info(parent, "platform device %s created\n", name);
+
+	dev = &pdev->dev;
+	dev->parent = parent;
+
+	if (descp) {
+		ret = platform_device_add_data(pdev, descp, sizeof(*descp));
+		if (ret) {
+			dev_err(parent, "add platform data failed: %d\n", ret);
+			goto ERROR_RET;
+		}
+	}
+
+	if (res) {
+		ret = platform_device_add_resources(pdev, res, 1);
+		if (ret) {
+			dev_err(parent, "add platform resources failed: %d\n", ret);
+			goto ERROR_RET;
+		}
+	}
+
+	ret = platform_device_add(pdev);
+	if (ret) {
+		dev_err(parent, "add platform device failed: %d\n", ret);
+		goto ERROR_RET;
+	}
+
+	return pdev;
+
+ERROR_RET:
+	platform_device_put(pdev);
+	return ERR_PTR(ret);
+}
+
+static int lsdc_vram_init(struct lsdc_device *ldev)
+{
+	struct pci_dev *gpu;
+	resource_size_t base, size;
+
+	/* BAR 2 of LS7A1000's GPU(GC1000) contain VRAM */
+	gpu = pci_get_device(PCI_VENDOR_ID_LOONGSON, 0x7A15, NULL);
+
+	if (IS_ERR_OR_NULL(gpu))
+		return -ENOENT;
+
+	base = pci_resource_start(gpu, 2);
+	size =  pci_resource_len(gpu, 2);
+
+	ldev->vram_base = base;
+	ldev->vram_size = size;
+
+	dev_info(ldev->dev, "vram start: 0x%llx, size: %uMB\n",
+		 (u64)base, (u32)(size >> 20));
+
+	return 0;
+}
+
+static int lsdc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct device *dev = &pdev->dev;
+	const struct lsdc_chip_desc *descp;
+	struct lsdc_device *ldev;
+	int ret;
+
+	descp = lsdc_detect_chip(pdev, ent);
+	if (!descp) {
+		dev_info(dev, "unknown dc ip core, abort\n");
+		return -ENOENT;
+	}
+
+	ldev = devm_kzalloc(dev, sizeof(*ldev), GFP_KERNEL);
+	if (IS_ERR(ldev))
+		return PTR_ERR(ldev);
+
+	ldev->desc = descp;
+	ldev->dev = dev;
+
+	if (lsdc_use_vram_helper > 0)
+		ldev->use_vram_helper = true;
+	else if ((lsdc_use_vram_helper < 0) && descp->has_vram)
+		ldev->use_vram_helper = true;
+	else
+		ldev->use_vram_helper = false;
+
+	ldev->enable_gamma = lsdc_gamma > 0 ? true : false;
+	ldev->relax_alignment = lsdc_relax_alignment > 0 ? true : false;
+
+	ret = pcim_enable_device(pdev);
+	if (ret)
+		return ret;
+
+	pci_set_master(pdev);
+
+	/* BAR 0 contains registers */
+	ldev->reg_base = devm_ioremap_resource(dev, &pdev->resource[0]);
+	if (IS_ERR(ldev->reg_base))
+		return PTR_ERR(ldev->reg_base);
+
+	/* Create gpio emulated i2c driver as early as possible */
+	if (descp->have_builtin_i2c) {
+		struct lsdc_i2c *li2c;
+		unsigned int i;
+
+		for (i = 0; i < descp->num_of_crtc; i++) {
+			li2c = lsdc_create_i2c_chan(dev, ldev->reg_base, i);
+			if (IS_ERR(li2c))
+				return PTR_ERR(li2c);
+
+			ldev->li2c[i] = li2c;
+		}
+	}
+
+	/* Get the optional framebuffer memory resource */
+	ret = of_reserved_mem_device_init(dev);
+	if (ret && (ret != -ENODEV))
+		return ret;
+
+	if (descp->has_vram && ldev->use_vram_helper) {
+		ret = lsdc_vram_init(ldev);
+		if (ret) {
+			dev_err(dev, "VRAM is unavailable\n");
+			ldev->use_vram_helper = false;
+		}
+	}
+
+	ldev->irq = pdev->irq;
+
+	dev_set_drvdata(dev, ldev);
+
+	if (descp->has_vram && ldev->use_vram_helper) {
+		struct resource res;
+
+		memset(&res, 0, sizeof(res));
+		res.flags = IORESOURCE_MEM;
+		res.name = "LS7A_VRAM";
+		res.start = ldev->vram_base;
+		res.end = ldev->vram_size;
+	}
+
+	ldev->dc = lsdc_create_platform_device("lsdc", dev, descp, NULL);
+	if (IS_ERR(ldev->dc))
+		return PTR_ERR(ldev->dc);
+
+	return platform_driver_register(&lsdc_platform_driver);
+}
+
+static void lsdc_pci_remove(struct pci_dev *pdev)
+{
+	struct lsdc_device *ldev = pci_get_drvdata(pdev);
+
+	platform_device_unregister(ldev->dc);
+
+	pci_set_drvdata(pdev, NULL);
+
+	pci_clear_master(pdev);
+
+	pci_release_regions(pdev);
+}
+
+static int lsdc_drm_suspend(struct device *dev)
+{
+	struct lsdc_device *ldev = dev_get_drvdata(dev);
+
+	return drm_mode_config_helper_suspend(ldev->ddev);
+}
+
+static int lsdc_drm_resume(struct device *dev)
+{
+	struct lsdc_device *ldev = dev_get_drvdata(dev);
+
+	return drm_mode_config_helper_resume(ldev->ddev);
+}
+
+static int lsdc_pm_freeze(struct device *dev)
+{
+	return lsdc_drm_suspend(dev);
+}
+
+static int lsdc_pm_thaw(struct device *dev)
+{
+	return lsdc_drm_resume(dev);
+}
+
+static int lsdc_pm_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	int error;
+
+	error = lsdc_pm_freeze(dev);
+	if (error)
+		return error;
+
+	pci_save_state(pdev);
+	/* Shut down the device */
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int lsdc_pm_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	if (pcim_enable_device(pdev))
+		return -EIO;
+
+	pci_set_power_state(pdev, PCI_D0);
+
+	pci_restore_state(pdev);
+
+	return lsdc_pm_thaw(dev);
+}
+
+static const struct dev_pm_ops lsdc_pm_ops = {
+	.suspend = lsdc_pm_suspend,
+	.resume = lsdc_pm_resume,
+	.freeze = lsdc_pm_freeze,
+	.thaw = lsdc_pm_thaw,
+	.poweroff = lsdc_pm_freeze,
+	.restore = lsdc_pm_resume,
+};
+
+static const struct pci_device_id lsdc_pciid_list[] = {
+	{PCI_VENDOR_ID_LOONGSON, 0x7a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+static struct pci_driver lsdc_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = lsdc_pciid_list,
+	.probe = lsdc_pci_probe,
+	.remove = lsdc_pci_remove,
+	.driver.pm = &lsdc_pm_ops,
+};
+
+static int __init lsdc_drm_init(void)
+{
+	struct pci_dev *pdev = NULL;
+
+	if (drm_firmware_drivers_only())
+		return -EINVAL;
+
+	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev))) {
+		/*
+		 * Multiple video card workaround
+		 *
+		 * This integrated video card will always be selected as
+		 * default boot device by vgaarb subsystem.
+		 */
+		if (pdev->vendor != PCI_VENDOR_ID_LOONGSON) {
+			pr_info("Discrete graphic card detected, abort\n");
+			return 0;
+		}
+	}
+
+	return pci_register_driver(&lsdc_pci_driver);
+}
+module_init(lsdc_drm_init);
+
+static void __exit lsdc_drm_exit(void)
+{
+	pci_unregister_driver(&lsdc_pci_driver);
+}
+module_exit(lsdc_drm_exit);
+
+MODULE_DEVICE_TABLE(pci, lsdc_pciid_list);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/lsdc/lsdc_plane.c b/drivers/gpu/drm/lsdc/lsdc_plane.c
new file mode 100644
index 000000000000..9ff4b0726313
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_plane.c
@@ -0,0 +1,470 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_vblank.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_damage_helper.h>
+
+#include "lsdc_drv.h"
+#include "lsdc_regs.h"
+#include "lsdc_pll.h"
+
+static const u32 lsdc_primary_formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+};
+
+static const u32 lsdc_cursor_formats[] = {
+	DRM_FORMAT_ARGB8888,
+};
+
+static const u64 lsdc_fb_format_modifiers[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static void lsdc_update_fb_format(struct lsdc_device *ldev,
+				  struct drm_crtc *crtc,
+				  const struct drm_format_info *fmt_info)
+{
+	unsigned int index = drm_crtc_index(crtc);
+	u32 val = 0;
+	u32 fmt;
+
+	switch (fmt_info->format) {
+	case DRM_FORMAT_RGB565:
+		fmt = LSDC_PF_RGB565;
+		break;
+	case DRM_FORMAT_XRGB8888:
+		fmt = LSDC_PF_XRGB8888;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		fmt = LSDC_PF_XRGB8888;
+		break;
+	default:
+		fmt = LSDC_PF_XRGB8888;
+		break;
+	}
+
+	if (index == 0) {
+		val = lsdc_reg_read32(ldev, LSDC_CRTC0_CFG_REG);
+		val = (val & ~CFG_PIX_FMT_MASK) | fmt;
+		lsdc_reg_write32(ldev, LSDC_CRTC0_CFG_REG, val);
+	} else if (index == 1) {
+		val = lsdc_reg_read32(ldev, LSDC_CRTC1_CFG_REG);
+		val = (val & ~CFG_PIX_FMT_MASK) | fmt;
+		lsdc_reg_write32(ldev, LSDC_CRTC1_CFG_REG, val);
+	}
+}
+
+static void lsdc_update_fb_start_addr(struct lsdc_device *ldev,
+				      struct drm_crtc *crtc,
+				      u64 paddr)
+{
+	unsigned int index = drm_crtc_index(crtc);
+	u32 addr_reg;
+	u32 hi_addr_reg;
+	u32 cfg_reg;
+	u32 val;
+
+	/*
+	 * Find which framebuffer address register should update.
+	 * if FB_ADDR0_REG is in using, we write the addr to FB_ADDR1_REG,
+	 * if FB_ADDR1_REG is in using, we write the addr to FB_ADDR0_REG
+	 */
+	if (index == 0) {
+		/* CRTC0 */
+		val = lsdc_reg_read32(ldev, LSDC_CRTC0_CFG_REG);
+
+		cfg_reg = LSDC_CRTC0_CFG_REG;
+		hi_addr_reg = LSDC_CRTC0_FB_HI_ADDR_REG;
+
+		if (val & CFG_FB_IDX_BIT) {
+			addr_reg = LSDC_CRTC0_FB_ADDR0_REG;
+			drm_dbg(ldev->ddev, "CRTC0 FB0 will be use\n");
+		} else {
+			addr_reg = LSDC_CRTC0_FB_ADDR1_REG;
+			drm_dbg(ldev->ddev, "CRTC0 FB1 will be use\n");
+		}
+	} else if (index == 1) {
+		/* CRTC1 */
+		val = lsdc_reg_read32(ldev, LSDC_CRTC1_CFG_REG);
+
+		cfg_reg = LSDC_CRTC1_CFG_REG;
+		hi_addr_reg = LSDC_CRTC1_FB_HI_ADDR_REG;
+
+		if (val & CFG_FB_IDX_BIT) {
+			addr_reg = LSDC_CRTC1_FB_ADDR0_REG;
+			drm_dbg(ldev->ddev, "CRTC1 FB0 will be use\n");
+		} else {
+			addr_reg = LSDC_CRTC1_FB_ADDR1_REG;
+			drm_dbg(ldev->ddev, "CRTC1 FB1 will be use\n");
+		}
+	}
+
+	lsdc_reg_write32(ldev, addr_reg, paddr);
+	lsdc_reg_write32(ldev, hi_addr_reg, paddr >> 32);
+	/*
+	 * Then, we triger the fb switch, the switch of the framebuffer
+	 * to be scanout will complete at the next vblank.
+	 */
+	lsdc_reg_write32(ldev, cfg_reg, val | CFG_PAGE_FLIP_BIT);
+
+	drm_dbg(ldev->ddev, "crtc%u scantout from 0x%llx\n", index, paddr);
+}
+
+static unsigned int lsdc_get_fb_offset(struct drm_framebuffer *fb,
+				       struct drm_plane_state *state,
+				       unsigned int plane)
+{
+	unsigned int offset = fb->offsets[plane];
+
+	offset += fb->format->cpp[plane] * (state->src_x >> 16);
+	offset += fb->pitches[plane] * (state->src_y >> 16);
+
+	return offset;
+}
+
+static s64 lsdc_get_vram_bo_offset(struct drm_framebuffer *fb)
+{
+	struct drm_gem_vram_object *gbo;
+	s64 gpu_addr;
+
+	gbo = drm_gem_vram_of_gem(fb->obj[0]);
+	gpu_addr = drm_gem_vram_offset(gbo);
+
+	return gpu_addr;
+}
+
+static int lsdc_primary_plane_atomic_check(struct drm_plane *plane,
+					   struct drm_atomic_state *state)
+{
+	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+	struct drm_crtc *crtc = plane_state->crtc;
+	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+
+	if (!crtc)
+		return 0;
+
+	return drm_atomic_helper_check_plane_state(plane_state,
+						   crtc_state,
+						   DRM_PLANE_HELPER_NO_SCALING,
+						   DRM_PLANE_HELPER_NO_SCALING,
+						   false, true);
+}
+
+static void lsdc_update_stride(struct lsdc_device *ldev,
+			       struct drm_crtc *crtc,
+			       unsigned int stride)
+{
+	unsigned int index = drm_crtc_index(crtc);
+
+	if (index == 0)
+		lsdc_reg_write32(ldev, LSDC_CRTC0_STRIDE_REG, stride);
+	else if (index == 1)
+		lsdc_reg_write32(ldev, LSDC_CRTC1_STRIDE_REG, stride);
+
+	drm_dbg(ldev->ddev, "update stride to %u\n", stride);
+}
+
+static void lsdc_primary_plane_atomic_update(struct drm_plane *plane,
+					     struct drm_atomic_state *state)
+{
+	struct lsdc_device *ldev = to_lsdc(plane->dev);
+	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+	struct drm_crtc *crtc = new_plane_state->crtc;
+	struct drm_framebuffer *fb = new_plane_state->fb;
+	u32 fb_offset = lsdc_get_fb_offset(fb, new_plane_state, 0);
+	dma_addr_t fb_addr;
+
+	if (ldev->use_vram_helper) {
+		s64 gpu_addr;
+
+		gpu_addr = lsdc_get_vram_bo_offset(fb);
+		if (gpu_addr < 0)
+			return;
+
+		fb_addr = ldev->vram_base + gpu_addr + fb_offset;
+	} else {
+		struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0);
+
+		fb_addr = obj->paddr + fb_offset;
+	}
+
+	lsdc_update_fb_start_addr(ldev, crtc, fb_addr);
+
+	lsdc_update_stride(ldev, crtc, fb->pitches[0]);
+
+	if (drm_atomic_crtc_needs_modeset(crtc->state))
+		lsdc_update_fb_format(ldev, crtc, fb->format);
+}
+
+static void lsdc_primary_plane_atomic_disable(struct drm_plane *plane,
+					      struct drm_atomic_state *state)
+{
+	drm_dbg(plane->dev, "%s disabled\n", plane->name);
+}
+
+static int lsdc_plane_prepare_fb(struct drm_plane *plane,
+				 struct drm_plane_state *new_state)
+{
+	struct lsdc_device *ldev = to_lsdc(plane->dev);
+
+	if (ldev->use_vram_helper)
+		return drm_gem_vram_plane_helper_prepare_fb(plane, new_state);
+
+	return drm_gem_plane_helper_prepare_fb(plane, new_state);
+}
+
+static void lsdc_plane_cleanup_fb(struct drm_plane *plane,
+				  struct drm_plane_state *old_state)
+{
+	struct drm_device *ddev = plane->dev;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+
+	if (ldev->use_vram_helper)
+		return drm_gem_vram_plane_helper_cleanup_fb(plane, old_state);
+}
+
+static const struct drm_plane_helper_funcs lsdc_primary_plane_helpers = {
+	.prepare_fb = lsdc_plane_prepare_fb,
+	.cleanup_fb = lsdc_plane_cleanup_fb,
+	.atomic_check = lsdc_primary_plane_atomic_check,
+	.atomic_update = lsdc_primary_plane_atomic_update,
+	.atomic_disable = lsdc_primary_plane_atomic_disable,
+};
+
+static int lsdc_cursor_atomic_check(struct drm_plane *plane,
+				    struct drm_atomic_state *state)
+{
+	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+	struct drm_framebuffer *fb = new_plane_state->fb;
+	struct drm_crtc *crtc = new_plane_state->crtc;
+	struct drm_crtc_state *crtc_state;
+	int ret;
+
+	/* no need for further checks if the plane is being disabled */
+	if (!crtc || !fb)
+		return 0;
+
+	if (!new_plane_state->visible)
+		return 0;
+
+	crtc_state = drm_atomic_get_new_crtc_state(state,
+						   new_plane_state->crtc);
+
+	ret = drm_atomic_helper_check_plane_state(new_plane_state,
+						  crtc_state,
+						  DRM_PLANE_HELPER_NO_SCALING,
+						  DRM_PLANE_HELPER_NO_SCALING,
+						  true,
+						  true);
+	if (ret)
+		return ret;
+
+	if (fb->width < LSDC_CURS_MIN_SIZE ||
+	    fb->height < LSDC_CURS_MIN_SIZE ||
+	    fb->width > LSDC_CURS_MAX_SIZE ||
+	    fb->height > LSDC_CURS_MAX_SIZE) {
+		drm_err(plane->dev, "Invalid cursor size: %dx%d\n",
+			fb->width, fb->height);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void lsdc_cursor_update_location(struct lsdc_device *ldev,
+					struct drm_crtc *crtc)
+{
+	u32 val;
+
+	val = lsdc_reg_read32(ldev, LSDC_CURSOR_CFG_REG);
+
+	if ((val & CURSOR_FORMAT_MASK) == 0)
+		val |= CURSOR_FORMAT_ARGB8888;
+
+	/* Update the location of the cursor
+	 * if bit 4 of LSDC_CURSOR_CFG_REG is 1, then the cursor will be
+	 * locate at CRTC1, if bit 4 of LSDC_CURSOR_CFG_REG is 0, then
+	 * the cursor will be locate at CRTC0.
+	 */
+	if (drm_crtc_index(crtc))
+		val |= CURSOR_LOCATION_BIT;
+
+	lsdc_reg_write32(ldev, LSDC_CURSOR_CFG_REG, val);
+}
+
+/* update the position of the cursor */
+static void lsdc_cursor_update_position(struct lsdc_device *ldev, int x, int y)
+{
+	if (x < 0)
+		x = 0;
+
+	if (y < 0)
+		y = 0;
+
+	lsdc_reg_write32(ldev, LSDC_CURSOR_POSITION_REG, (y << 16) | x);
+}
+
+static void lsdc_cursor_atomic_update(struct drm_plane *plane,
+				      struct drm_atomic_state *state)
+{
+	struct drm_device *ddev = plane->dev;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
+	struct drm_framebuffer *new_fb = new_plane_state->fb;
+	struct drm_framebuffer *old_fb = old_plane_state->fb;
+
+	if (new_fb != old_fb) {
+		u64 cursor_addr;
+
+		if (ldev->use_vram_helper) {
+			s64 offset;
+
+			offset = lsdc_get_vram_bo_offset(new_fb);
+			cursor_addr = ldev->vram_base + offset;
+
+			drm_dbg_kms(ddev, "%s offset: %llx\n", plane->name, offset);
+		} else {
+			struct drm_gem_cma_object *cursor_obj;
+
+			cursor_obj = drm_fb_cma_get_gem_obj(new_fb, 0);
+			if (!cursor_obj)
+				return;
+
+			cursor_addr = cursor_obj->paddr;
+		}
+
+		lsdc_reg_write32(ldev, LSDC_CURSOR_ADDR_REG, cursor_addr);
+	}
+
+	lsdc_cursor_update_position(ldev, new_plane_state->crtc_x, new_plane_state->crtc_y);
+
+	lsdc_cursor_update_location(ldev, new_plane_state->crtc);
+}
+
+static void lsdc_cursor_atomic_disable(struct drm_plane *plane,
+				       struct drm_atomic_state *state)
+{
+	struct drm_device *ddev = plane->dev;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+
+	lsdc_reg_write32(ldev, LSDC_CURSOR_CFG_REG, 0);
+
+	drm_dbg(ddev, "%s disabled\n", plane->name);
+}
+
+static const struct drm_plane_helper_funcs lsdc_cursor_plane_helpers = {
+	.prepare_fb = lsdc_plane_prepare_fb,
+	.cleanup_fb = lsdc_plane_cleanup_fb,
+	.atomic_check = lsdc_cursor_atomic_check,
+	.atomic_update = lsdc_cursor_atomic_update,
+	.atomic_disable = lsdc_cursor_atomic_disable,
+};
+
+static int lsdc_plane_get_default_zpos(enum drm_plane_type type)
+{
+	switch (type) {
+	case DRM_PLANE_TYPE_PRIMARY:
+		return 0;
+	case DRM_PLANE_TYPE_OVERLAY:
+		return 1;
+	case DRM_PLANE_TYPE_CURSOR:
+		return 7;
+	}
+	return 0;
+}
+
+static void lsdc_plane_reset(struct drm_plane *plane)
+{
+	drm_atomic_helper_plane_reset(plane);
+
+	plane->state->zpos = lsdc_plane_get_default_zpos(plane->type);
+
+	drm_dbg(plane->dev, "%s reset\n", plane->name);
+}
+
+static const struct drm_plane_funcs lsdc_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = drm_plane_cleanup,
+	.reset = lsdc_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+int lsdc_plane_init(struct lsdc_device *ldev,
+		    struct drm_plane *plane,
+		    enum drm_plane_type type,
+		    unsigned int index)
+{
+	struct drm_device *ddev = ldev->ddev;
+	int zpos = lsdc_plane_get_default_zpos(type);
+	unsigned int format_count;
+	const u32 *formats;
+	const char *name;
+	int ret;
+
+	switch (type) {
+	case DRM_PLANE_TYPE_PRIMARY:
+		formats = lsdc_primary_formats;
+		format_count = ARRAY_SIZE(lsdc_primary_formats);
+		name = "primary-%u";
+		break;
+	case DRM_PLANE_TYPE_CURSOR:
+		formats = lsdc_cursor_formats;
+		format_count = ARRAY_SIZE(lsdc_cursor_formats);
+		name = "cursor-%u";
+		break;
+	case DRM_PLANE_TYPE_OVERLAY:
+		drm_err(ddev, "overlay plane is not supported\n");
+		break;
+	}
+
+	ret = drm_universal_plane_init(ddev, plane, 1 << index,
+				       &lsdc_plane_funcs,
+				       formats, format_count,
+				       lsdc_fb_format_modifiers,
+				       type, name, index);
+	if (ret) {
+		drm_err(ddev, "%s failed: %d\n", __func__, ret);
+		return ret;
+	}
+
+	switch (type) {
+	case DRM_PLANE_TYPE_PRIMARY:
+		drm_plane_helper_add(plane, &lsdc_primary_plane_helpers);
+		drm_plane_create_zpos_property(plane, zpos, 0, 6);
+		break;
+	case DRM_PLANE_TYPE_CURSOR:
+		drm_plane_helper_add(plane, &lsdc_cursor_plane_helpers);
+		drm_plane_create_zpos_immutable_property(plane, zpos);
+		break;
+	case DRM_PLANE_TYPE_OVERLAY:
+		drm_err(ddev, "overlay plane is not supported\n");
+		break;
+	}
+
+	drm_plane_create_alpha_property(plane);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/lsdc/lsdc_pll.c b/drivers/gpu/drm/lsdc/lsdc_pll.c
new file mode 100644
index 000000000000..1d5d23a6b9f3
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_pll.c
@@ -0,0 +1,574 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#include "lsdc_drv.h"
+#include "lsdc_regs.h"
+#include "lsdc_pll.h"
+
+/*
+ * The structure of the pixel PLL register is evolved with times.
+ * All loongson's cpu is little endian.
+ */
+
+/* u64 */
+struct ls7a1000_pixpll_bitmap {
+	/* Byte 0 ~ Byte 3 */
+	unsigned div_out      : 7;   /*  0 : 6     output clock divider  */
+	unsigned reserved_1   : 14;  /*  7 : 20                          */
+	unsigned loopc        : 9;   /* 21 : 29                          */
+	unsigned reserved_2   : 2;   /* 30 : 31                          */
+
+	/* Byte 4 ~ Byte 7 */
+	unsigned div_ref      : 7;   /*  0 : 6     input clock divider   */
+	unsigned locked       : 1;   /*  7         PLL locked flag       */
+	unsigned sel_out      : 1;   /*  8         output clk selector   */
+	unsigned reserved_3   : 2;   /*  9 : 10    reserved              */
+	unsigned set_param    : 1;   /*  11        set pll param         */
+	unsigned bypass       : 1;   /*  12                              */
+	unsigned powerdown    : 1;   /*  13                              */
+	unsigned reserved_4   : 18;  /*  14 : 31                         */
+};
+
+/* u128 */
+struct ls2k1000_pixpll_bitmap {
+	/* Byte 0 ~ Byte 3 */
+	unsigned sel_out      :  1;  /*  0      select this PLL          */
+	unsigned reserved_1   :  1;  /*  1                               */
+	unsigned sw_adj_en    :  1;  /*  2      allow software adjust    */
+	unsigned bypass       :  1;  /*  3      bypass L1 PLL            */
+	unsigned reserved_2   :  3;  /*  4:6                             */
+	unsigned lock_en      :  1;  /*  7      enable lock L1 PLL       */
+	unsigned reserved_3   :  2;  /*  8:9                             */
+	unsigned lock_check   :  2;  /* 10:11   precision check          */
+	unsigned reserved_4   :  4;  /* 12:15                            */
+
+	unsigned locked       :  1;  /* 16      PLL locked flag bit      */
+	unsigned reserved_5   :  2;  /* 17:18                            */
+	unsigned powerdown    :  1;  /* 19      powerdown the pll if set */
+	unsigned reserved_6   :  6;  /* 20:25                            */
+	unsigned div_ref      :  6;  /* 26:31   L1 Prescaler             */
+
+	/* Byte 4 ~ Byte 7 */
+	unsigned loopc        : 10;  /* 32:41   Clock Multiplier         */
+	unsigned l1_div       :  6;  /* 42:47   not used                 */
+	unsigned reserved_7   : 16;  /* 48:63                            */
+
+	/* Byte 8 ~ Byte 15 */
+	unsigned div_out      :  6;  /* 0 : 5   output clock divider     */
+	unsigned reserved_8   : 26;  /* 6 : 31                           */
+	unsigned reserved_9   : 32;  /* 70: 127                          */
+};
+
+/* u32 */
+struct ls2k0500_pixpll_bitmap {
+	/* Byte 0 ~ Byte 1 */
+	unsigned sel_out      : 1;
+	unsigned reserved_1   : 2;
+	unsigned sw_adj_en    : 1;   /* allow software adjust              */
+	unsigned bypass       : 1;   /* bypass L1 PLL                      */
+	unsigned powerdown    : 1;   /* write 1 to powerdown the PLL       */
+	unsigned reserved_2   : 1;
+	unsigned locked       : 1;   /*  7     Is L1 PLL locked, read only */
+	unsigned div_ref      : 6;   /*  8:13  ref clock divider           */
+	unsigned reserved_3   : 2;   /* 14:15                              */
+	/* Byte 2 ~ Byte 3 */
+	unsigned loopc        : 8;   /* 16:23   Clock Multiplier           */
+	unsigned div_out      : 6;   /* 24:29   output clock divider       */
+	unsigned reserved_4   : 2;   /* 30:31                              */
+};
+
+union lsdc_pixpll_bitmap {
+	struct ls7a1000_pixpll_bitmap ls7a1000;
+	struct ls2k1000_pixpll_bitmap ls2k1000;
+	struct ls2k0500_pixpll_bitmap ls2k0500;
+
+	u32 dword[4];
+};
+
+struct pixclk_to_pll_parm {
+	/* kHz */
+	unsigned int clock;
+
+	/* unrelated information */
+	unsigned short width;
+	unsigned short height;
+	unsigned short vrefresh;
+
+	/* Stores parameters for programming the Hardware PLLs */
+	unsigned short div_out;
+	unsigned short loopc;
+	unsigned short div_ref;
+};
+
+/*
+ * Pixel clock to PLL parameters translation table.
+ * Small static cached value to speed up PLL parameters calculation.
+ */
+static const struct pixclk_to_pll_parm pll_param_table[] = {
+	{148500, 1920, 1080, 60, 11, 49,  3},   /* 1920x1080@60Hz */
+						/* 1920x1080@50Hz */
+	{174500, 1920, 1080, 75, 17, 89,  3},   /* 1920x1080@75Hz */
+	{181250, 2560, 1080, 75,  8, 58,  4},   /* 2560x1080@75Hz */
+	{146250, 1680, 1050, 60, 16, 117, 5},   /* 1680x1050@60Hz */
+	{135000, 1280, 1024, 75, 10, 54,  4},   /* 1280x1024@75Hz */
+
+	{108000, 1600, 900,  60, 15, 81,  5},   /* 1600x900@60Hz  */
+						/* 1280x1024@60Hz */
+						/* 1280x960@60Hz */
+						/* 1152x864@75Hz */
+
+	{106500, 1440, 900,  60, 19, 81,  4},   /* 1440x900@60Hz */
+	{88750,  1440, 900,  60, 16, 71,  5},   /* 1440x900@60Hz */
+	{83500,  1280, 800,  60, 17, 71,  5},   /* 1280x800@60Hz */
+	{71000,  1280, 800,  60, 20, 71,  5},   /* 1280x800@60Hz */
+
+	{74250,  1280, 720,  60, 22, 49,  3},   /* 1280x720@60Hz */
+						/* 1280x720@50Hz */
+
+	{78750,  1024, 768,  75, 16, 63,  5},   /* 1024x768@75Hz */
+	{75000,  1024, 768,  70, 29, 87,  4},   /* 1024x768@70Hz */
+	{65000,  1024, 768,  60, 20, 39,  3},   /* 1024x768@60Hz */
+
+	{51200,  1024, 600,  60, 25, 64,  5},   /* 1024x600@60Hz */
+
+	{57284,  832,  624,  75, 24, 55,  4},   /* 832x624@75Hz */
+	{49500,  800,  600,  75, 40, 99,  5},   /* 800x600@75Hz */
+	{50000,  800,  600,  72, 44, 88,  4},   /* 800x600@72Hz */
+	{40000,  800,  600,  60, 30, 36,  3},   /* 800x600@60Hz */
+	{36000,  800,  600,  56, 50, 72,  4},   /* 800x600@56Hz */
+	{31500,  640,  480,  75, 40, 63,  5},   /* 640x480@75Hz */
+						/* 640x480@73Hz */
+
+	{30240,  640,  480,  67, 62, 75,  4},   /* 640x480@67Hz */
+	{27000,  720,  576,  50, 50, 54,  4},   /* 720x576@60Hz */
+	{25175,  640,  480,  60, 85, 107, 5},   /* 640x480@60Hz */
+	{25200,  640,  480,  60, 50, 63,  5},   /* 640x480@60Hz */
+						/* 720x480@60Hz */
+};
+
+/**
+ * lsdc_pixpll_setup - ioremap the device dependent PLL registers
+ *
+ * @this: point to the object which this function is called from
+ */
+static int lsdc_pixpll_setup(struct lsdc_pll * const this)
+{
+	this->mmio = ioremap(this->reg_base, this->reg_size);
+
+	return 0;
+}
+
+/*
+ * Find a set of pll parameters (to generate pixel clock) from a static
+ * local table, which avoid to compute the pll parameter eachtime a
+ * modeset is triggered.
+ *
+ * @this: point to the object which this function is called from
+ * @clock: the desired output pixel clock, the unit is kHz
+ * @pout: point to where the parameters to store if found
+ *
+ *  Return true if hit, otherwise return false.
+ */
+static bool lsdc_pixpll_find(struct lsdc_pll * const this,
+			     unsigned int clock,
+			     struct lsdc_pll_core_values * const pout)
+{
+	unsigned int num = ARRAY_SIZE(pll_param_table);
+	unsigned int i;
+
+	for (i = 0; i < num; i++) {
+		if (clock != pll_param_table[i].clock)
+			continue;
+
+		pout->div_ref = pll_param_table[i].div_ref;
+		pout->loopc   = pll_param_table[i].loopc;
+		pout->div_out = pll_param_table[i].div_out;
+
+		return true;
+	}
+
+	drm_dbg(this->ddev, "pixel clock %u: miss\n", clock);
+
+	return false;
+}
+
+/*
+ * Find a set of pll parameters which have minimal difference with the desired
+ * pixel clock frequency. It does that by computing all of the possible
+ * combination. Compute the diff and find the combination with minimal diff.
+ *
+ *  clock_out = refclk / div_ref * loopc / div_out
+ *
+ *  refclk is fixed as 100MHz in ls7a1000, ls2k1000 and ls2k0500
+ *
+ * @this: point to the object from which this function is called
+ * @clk: the desired output pixel clock, the unit is kHz
+ * @pout: point to where the parameters to store if success
+ *
+ *  Return true if a parameter is found, otherwise return false
+ */
+static bool lsdc_pixpll_compute(struct lsdc_pll * const this,
+				unsigned int clk,
+				struct lsdc_pll_core_values *pout)
+{
+	unsigned int refclk = this->ref_clock;
+	const unsigned int tolerance = 1000;
+	unsigned int min = tolerance;
+	unsigned int div_out, loopc, div_ref;
+
+	if (lsdc_pixpll_find(this, clk, pout))
+		return true;
+
+	for (div_out = 6; div_out < 64; div_out++) {
+		for (div_ref = 3; div_ref < 6; div_ref++) {
+			for (loopc = 6; loopc < 161; loopc++) {
+				int diff;
+
+				if (loopc < 12 * div_ref)
+					continue;
+				if (loopc > 32 * div_ref)
+					continue;
+
+				diff = clk * div_out - refclk * loopc / div_ref;
+
+				if (diff < 0)
+					diff = -diff;
+
+				if (diff < min) {
+					min = diff;
+					pout->div_ref = div_ref;
+					pout->div_out = div_out;
+					pout->loopc = loopc;
+
+					if (diff == 0)
+						return true;
+				}
+			}
+		}
+	}
+
+	return min < tolerance;
+}
+
+/*
+ * Update the pll parameters to hardware, target to the pixpll in ls7a1000
+ *
+ * @this: point to the object from which this function is called
+ * @param: point to the core parameters passed in
+ *
+ * return 0 if successful.
+ */
+static int ls7a1000_pixpll_param_update(struct lsdc_pll * const this,
+					struct lsdc_pll_core_values const *param)
+{
+	void __iomem *reg = this->mmio;
+	unsigned int counter = 0;
+	bool locked;
+	u32 val;
+
+	/* Bypass the software configured PLL, using refclk directly */
+	val = readl(reg + 0x4);
+	val &= ~(1 << 8);
+	writel(val, reg + 0x4);
+
+	/* Powerdown the PLL */
+	val = readl(reg + 0x4);
+	val |= (1 << 13);
+	writel(val, reg + 0x4);
+
+	/* Clear the pll parameters */
+	val = readl(reg + 0x4);
+	val &= ~(1 << 11);
+	writel(val, reg + 0x4);
+
+	/* clear old value & config new value */
+	val = readl(reg + 0x04);
+	val &= ~0x7F;
+	val |= param->div_ref;        /* div_ref */
+	writel(val, reg + 0x4);
+
+	val = readl(reg);
+	val &= ~0x7f;
+	val |= param->div_out;        /* div_out */
+
+	val &= ~(0x1ff << 21);
+	val |= param->loopc << 21;    /* loopc */
+	writel(val, reg);
+
+	/* Set the pll the parameters */
+	val = readl(reg + 0x4);
+	val |= (1 << 11);
+	writel(val, reg + 0x4);
+
+	/* Powerup the PLL */
+	val = readl(reg + 0x4);
+	val &= ~(1 << 13);
+	writel(val, reg + 0x4);
+
+	/* Wait the PLL lock */
+	do {
+		val = readl(reg + 0x4);
+		locked = val & 0x80;
+		counter++;
+	} while (!locked && (counter < 10000));
+
+	drm_dbg(this->ddev, "%u loop waited\n", counter);
+
+	/* Switch to the software configured pll */
+	val = readl(reg + 0x4);
+	val |= (1UL << 8);
+	writel(val, reg + 0x4);
+
+	return 0;
+}
+
+/*
+ * Update the pll parameters to hardware, target to the pixpll in ls2k1000
+ *
+ * @this: point to the object from which this function is called
+ * @param: pointer to where the parameter is passed in
+ *
+ * return 0 if successful.
+ */
+static int ls2k1000_pixpll_param_update(struct lsdc_pll * const this,
+					struct lsdc_pll_core_values const *param)
+{
+	void __iomem *reg = this->mmio;
+	unsigned int counter = 0;
+	bool locked = false;
+	u32 val;
+
+	val = readl(reg);
+	/* Bypass the software configured PLL, using refclk directly */
+	val &= ~(1 << 0);
+	writel(val, reg);
+
+	/* Powerdown the PLL */
+	val |= (1 << 19);
+	writel(val, reg);
+
+	/* Allow the software configuration */
+	val &= ~(1 << 2);
+	writel(val, reg);
+
+	/* allow L1 PLL lock */
+	val = (1L << 7) | (3L << 10);
+	writel(val, reg);
+
+	/* clear div_ref bit field */
+	val &= ~(0x3f << 26);
+	/* set div_ref bit field */
+	val = val | (param->div_ref << 26);
+	writel(val, reg);
+
+	val = readl(reg + 4);
+	/* clear loopc bit field */
+	val &= ~0x0fff;
+	/* set loopc bit field */
+	val |= param->loopc;
+	writel(val, reg + 4);
+
+	/* set div_out */
+	writel(param->div_out, reg + 8);
+
+	val = readl(reg);
+	/* use the software configure param */
+	val |= (1 << 2);
+	/* powerup the PLL */
+	val &= ~(1 << 19);
+	writel(val, reg);
+
+	/* wait pll setup and locked */
+	do {
+		val = readl(reg);
+		locked = val & 0x10000;
+		counter++;
+	} while (!locked && (counter < 10000));
+
+	drm_dbg(this->ddev, "%u loop waited\n", counter);
+
+	/* Switch to the above software configured PLL instead of refclk */
+	val |= 1;
+	writel(val, reg);
+
+	return 0;
+}
+
+/*
+ * Update the pll parameters to hardware, target to the pixpll in ls2k0500
+ *
+ * @this: point to the object which calling this function
+ * @param: pointer to where the parameters passed in
+ *
+ * return 0 if successful.
+ */
+static int ls2k0500_pixpll_param_update(struct lsdc_pll * const this,
+					struct lsdc_pll_core_values const *param)
+{
+	void __iomem *reg = this->mmio;
+	unsigned int counter = 0;
+	bool locked = false;
+	u32 val;
+
+	/* Bypass the software configured PLL, using refclk directly */
+	val = readl(reg);
+	val &= ~(1 << 0);
+	writel(val, reg);
+
+	/* Powerdown the PLL */
+	val = readl(reg);
+	val |= (1 << 5);
+	writel(val, reg);
+
+	/* Allow the software configuration */
+	val |= (1 << 3);
+	writel(val, reg);
+
+	/* Update the pll params */
+	val = (param->div_out << 24) |
+	      (param->loopc << 16) |
+	      (param->div_ref << 8);
+
+	writel(val, reg);
+
+	/* Powerup the PLL */
+	val = readl(reg);
+	val &= ~(1 << 5);
+	writel(val, reg);
+
+	/* wait pll setup and locked */
+	do {
+		val = readl(reg);
+		locked = val & 0x80;
+		counter++;
+	} while (!locked && (counter < 10000));
+
+	drm_dbg(this->ddev, "%u loop waited\n", counter);
+
+	/* Switch to the above software configured PLL instead of refclk */
+	writel((val | 1), reg);
+
+	return 0;
+}
+
+static unsigned int lsdc_get_clock_rate(struct lsdc_pll * const this,
+					struct lsdc_pll_core_values *pout)
+{
+	struct drm_device *ddev = this->ddev;
+	struct lsdc_device *ldev = to_lsdc(ddev);
+	const struct lsdc_chip_desc * const desc = ldev->desc;
+	unsigned int out;
+	union lsdc_pixpll_bitmap parms;
+
+	if (desc->chip == LSDC_CHIP_7A1000) {
+		struct ls7a1000_pixpll_bitmap *obj = &parms.ls7a1000;
+
+		parms.dword[0] = readl(this->mmio);
+		parms.dword[1] = readl(this->mmio + 4);
+		out = this->ref_clock / obj->div_ref * obj->loopc / obj->div_out;
+		if (pout) {
+			pout->div_ref = obj->div_ref;
+			pout->loopc = obj->loopc;
+			pout->div_out = obj->div_out;
+		}
+	} else if (desc->chip == LSDC_CHIP_2K1000) {
+		struct ls2k1000_pixpll_bitmap *obj = &parms.ls2k1000;
+
+		parms.dword[0] = readl(this->mmio);
+		parms.dword[1] = readl(this->mmio + 4);
+		parms.dword[2] = readl(this->mmio + 8);
+		parms.dword[3] = readl(this->mmio + 12);
+		out = this->ref_clock / obj->div_ref * obj->loopc / obj->div_out;
+		if (pout) {
+			pout->div_ref = obj->div_ref;
+			pout->loopc = obj->loopc;
+			pout->div_out = obj->div_out;
+		}
+	} else if (desc->chip == LSDC_CHIP_2K0500) {
+		struct ls2k0500_pixpll_bitmap *obj = &parms.ls2k0500;
+
+		parms.dword[0] = readl(this->mmio);
+		out = this->ref_clock / obj->div_ref * obj->loopc / obj->div_out;
+		if (pout) {
+			pout->div_ref = obj->div_ref;
+			pout->loopc = obj->loopc;
+			pout->div_out = obj->div_out;
+		}
+	} else {
+		drm_err(ddev, "unknown chip, the driver need update\n");
+		return 0;
+	}
+
+	return out;
+}
+
+static const struct lsdc_pixpll_funcs ls7a1000_pixpll_funcs = {
+	.setup = lsdc_pixpll_setup,
+	.compute = lsdc_pixpll_compute,
+	.update = ls7a1000_pixpll_param_update,
+	.get_clock_rate = lsdc_get_clock_rate,
+};
+
+static const struct lsdc_pixpll_funcs ls2k1000_pixpll_funcs = {
+	.setup = lsdc_pixpll_setup,
+	.compute = lsdc_pixpll_compute,
+	.update = ls2k1000_pixpll_param_update,
+	.get_clock_rate = lsdc_get_clock_rate,
+};
+
+static const struct lsdc_pixpll_funcs ls2k0500_pixpll_funcs = {
+	.setup = lsdc_pixpll_setup,
+	.compute = lsdc_pixpll_compute,
+	.update = ls2k0500_pixpll_param_update,
+	.get_clock_rate = lsdc_get_clock_rate,
+};
+
+int lsdc_pixpll_init(struct lsdc_pll * const this,
+		     struct drm_device *ddev,
+		     unsigned int index)
+{
+	struct lsdc_device *ldev = to_lsdc(ddev);
+	const struct lsdc_chip_desc *ip = ldev->desc;
+
+	this->ddev = ddev;
+	this->index = index;
+	this->ref_clock = LSDC_PLL_REF_CLK;
+
+	if (ip->chip == LSDC_CHIP_7A1000) {
+		if (index == 0)
+			this->reg_base = LS7A1000_CFG_REG_BASE + LS7A1000_PIX_PLL0_REG;
+		else if (index == 1)
+			this->reg_base = LS7A1000_CFG_REG_BASE + LS7A1000_PIX_PLL1_REG;
+		this->reg_size = 8;
+		this->funcs = &ls7a1000_pixpll_funcs;
+	} else if (ip->chip == LSDC_CHIP_2K1000) {
+		if (index == 0)
+			this->reg_base = LS2K1000_CFG_REG_BASE + LS2K1000_PIX_PLL0_REG;
+		else if (index == 1)
+			this->reg_base = LS2K1000_CFG_REG_BASE + LS2K1000_PIX_PLL1_REG;
+
+		this->reg_size = 16;
+		this->funcs = &ls2k1000_pixpll_funcs;
+	} else if (ip->chip == LSDC_CHIP_2K0500) {
+		if (index == 0)
+			this->reg_base = LS2K0500_CFG_REG_BASE + LS2K0500_PIX_PLL0_REG;
+		else if (index == 1)
+			this->reg_base = LS2K0500_CFG_REG_BASE + LS2K0500_PIX_PLL1_REG;
+
+		this->reg_size = 4;
+		this->funcs = &ls2k0500_pixpll_funcs;
+	} else {
+		drm_err(this->ddev, "unknown chip, the driver need update\n");
+		return -ENOENT;
+	}
+
+	return this->funcs->setup(this);
+}
diff --git a/drivers/gpu/drm/lsdc/lsdc_pll.h b/drivers/gpu/drm/lsdc/lsdc_pll.h
new file mode 100644
index 000000000000..cad37a7a77d2
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_pll.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#ifndef __LSDC_PLL_H__
+#define __LSDC_PLL_H__
+
+#include <drm/drm_device.h>
+
+/*
+ * PIXEL PLL hardware structure
+ *
+ * refclk: reference frequency, 100 MHz from external oscillator
+ * outclk: output frequency desired.
+ *
+ *
+ *               L1       Fref                      Fvco     L2
+ * refclk   +-----------+      +------------------+      +---------+   outclk
+ * ---+---> | Prescaler | ---> | Clock Multiplier | ---> | divider | -------->
+ *    |     +-----------+      +------------------+      +---------+     ^
+ *    |           ^                      ^                    ^          |
+ *    |           |                      |                    |          |
+ *    |           |                      |                    |          |
+ *    |        div_ref                 loopc               div_out       |
+ *    |                                                                  |
+ *    +---- sel_out (bypass above software configurable clock if==1) ----+
+ *
+ *  sel_out: PLL clock output selector.
+ *
+ *  If sel_out == 1, it will take refclk as output directly,
+ *  the L1 Prescaler and the out divider is bypassed.
+ *
+ *  If sel_out == 0, then:
+ *  outclk = refclk / div_ref * loopc / div_out;
+ *
+ * PLL hardware working requirements:
+ *
+ *  1) 20 MHz <= refclk / div_ref <= 40Mhz
+ *  2) 1.2 GHz <= refclk /div_out * loopc <= 3.2 Ghz
+ *
+ */
+
+struct lsdc_pll_core_values {
+	unsigned int div_ref;
+	unsigned int loopc;
+	unsigned int div_out;
+};
+
+struct lsdc_pll;
+
+struct lsdc_pixpll_funcs {
+	int (*setup)(struct lsdc_pll * const this);
+	bool (*compute)(struct lsdc_pll * const this, unsigned int clock,
+			struct lsdc_pll_core_values *params_out);
+	int (*update)(struct lsdc_pll * const this,
+		      struct lsdc_pll_core_values const *params_in);
+	unsigned int (*get_clock_rate)(struct lsdc_pll * const this,
+				       struct lsdc_pll_core_values *pout);
+};
+
+struct lsdc_pll {
+	const struct lsdc_pixpll_funcs *funcs;
+	struct drm_device *ddev;
+	void __iomem *mmio;
+
+	/* PLL register offset */
+	u32 reg_base;
+	/* PLL register size in bytes */
+	u32 reg_size;
+
+	/* 100000kHz, fixed on all board found */
+	unsigned int ref_clock;
+
+	unsigned int index;
+};
+
+int lsdc_pixpll_init(struct lsdc_pll * const this,
+		     struct drm_device *ddev,
+		     unsigned int index);
+
+#endif
diff --git a/drivers/gpu/drm/lsdc/lsdc_regs.h b/drivers/gpu/drm/lsdc/lsdc_regs.h
new file mode 100644
index 000000000000..e925ab487d12
--- /dev/null
+++ b/drivers/gpu/drm/lsdc/lsdc_regs.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KMS driver for Loongson display controller
+ * Copyright (C) 2022 Loongson Corporation
+ */
+
+/*
+ * Authors:
+ *      Sui Jingfeng <suijingfeng@loongson.cn>
+ */
+
+#ifndef __LSDC_REGS_H__
+#define __LSDC_REGS_H__
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+/*
+ * PIXEL PLL
+ */
+#define LSDC_PLL_REF_CLK                100000           /* kHz */
+
+/*
+ * Those PLL registers are not located at DC reg bar space,
+ * there are relative to LSXXXXX_CFG_REG_BASE.
+ * XXXXX = 7A1000, 2K1000, 2K0500
+ */
+
+/* LS2K1000 */
+#define LS2K1000_PIX_PLL0_REG           0x04B0
+#define LS2K1000_PIX_PLL1_REG           0x04C0
+#define LS2K1000_CFG_REG_BASE           0x1fe10000
+
+/* LS7A1000 */
+#define LS7A1000_PIX_PLL0_REG           0x04B0
+#define LS7A1000_PIX_PLL1_REG           0x04C0
+#define LS7A1000_CFG_REG_BASE           0x10010000
+
+/* LS2K0500 */
+#define LS2K0500_PIX_PLL0_REG           0x0418
+#define LS2K0500_PIX_PLL1_REG           0x0420
+#define LS2K0500_CFG_REG_BASE           0x1fe10000
+
+/*
+ *  CRTC CFG REG
+ */
+#define CFG_PIX_FMT_MASK                GENMASK(2, 0)
+
+enum lsdc_pixel_format {
+	LSDC_PF_NONE = 0,
+	LSDC_PF_ARGB4444 = 1,  /* ARGB A:4 bits R/G/B: 4 bits each [16 bits] */
+	LSDC_PF_ARGB1555 = 2,  /* ARGB A:1 bit RGB:15 bits [16 bits] */
+	LSDC_PF_RGB565 = 3,    /* RGB [16 bits] */
+	LSDC_PF_XRGB8888 = 4,  /* XRGB [32 bits] */
+};
+
+/* Each CRTC has two FB address registers, CFG_FB_IDX_BIT specify
+ * which fb address register is currently in using by the CRTC.
+ * Setting CFG_PAGE_FLIP_BIT bit will triger the switch. The switch
+ * finished at the vblank and if you want switch back you can set
+ * CFG_PAGE_FLIP_BIT again.
+ */
+#define CFG_PAGE_FLIP_BIT               BIT(7)
+#define CFG_OUTPUT_EN_BIT               BIT(8)
+/* CRTC0 clone from CRTC1 or CRTC1 clone from CRTC0 using hardware logic */
+#define CFG_PANEL_SWITCH                BIT(9)
+/* Indicate witch fb addr reg is in using, currently */
+#define CFG_FB_IDX_BIT                  BIT(11)
+#define CFG_GAMMAR_EN_BIT               BIT(12)
+
+/* CRTC get soft reset if voltage level change from 1 -> 0 */
+#define CFG_RESET_BIT                   BIT(20)
+
+#define EN_HSYNC_BIT                    BIT(30)
+#define INV_HSYNC_BIT                   BIT(31)
+#define EN_VSYNC_BIT                    BIT(30)
+#define INV_VSYNC_BIT                   BIT(31)
+
+/******** CRTC0 & DVO0 ********/
+#define LSDC_CRTC0_CFG_REG              0x1240
+#define LSDC_CRTC0_FB_ADDR0_REG         0x1260
+#define LSDC_CRTC0_FB_ADDR1_REG         0x1580
+#define LSDC_CRTC0_FB_HI_ADDR_REG       0x15A0
+#define LSDC_CRTC0_STRIDE_REG           0x1280
+#define LSDC_CRTC0_FB_ORIGIN_REG        0x1300
+#define LSDC_CRTC0_HDISPLAY_REG         0x1400
+#define LSDC_CRTC0_HSYNC_REG            0x1420
+#define LSDC_CRTC0_VDISPLAY_REG         0x1480
+#define LSDC_CRTC0_VSYNC_REG            0x14A0
+#define LSDC_CRTC0_GAMMA_INDEX_REG      0x14E0
+#define LSDC_CRTC0_GAMMA_DATA_REG       0x1500
+
+/******** CTRC1 & DVO1 ********/
+#define LSDC_CRTC1_CFG_REG              0x1250
+#define LSDC_CRTC1_FB_ADDR0_REG         0x1270
+#define LSDC_CRTC1_FB_ADDR1_REG         0x1590
+#define LSDC_CRTC1_FB_HI_ADDR_REG       0x15C0
+#define LSDC_CRTC1_STRIDE_REG           0x1290
+#define LSDC_CRTC1_FB_ORIGIN_REG        0x1310
+#define LSDC_CRTC1_HDISPLAY_REG         0x1410
+#define LSDC_CRTC1_HSYNC_REG            0x1430
+#define LSDC_CRTC1_VDISPLAY_REG         0x1490
+#define LSDC_CRTC1_VSYNC_REG            0x14B0
+#define LSDC_CRTC1_GAMMA_INDEX_REG      0x14F0
+#define LSDC_CRTC1_GAMMA_DATA_REG       0x1510
+
+/*
+ * Hardware cursor
+ * There is only one hardware cursor shared by two CRTC in ls7a1000,
+ * ls2k1000 and ls2k0500.
+ */
+#define LSDC_CURSOR_CFG_REG             0x1520
+
+#define CURSOR_FORMAT_MASK              GENMASK(1, 0)
+#define CURSOR_FORMAT_DISABLE           0
+#define CURSOR_FORMAT_MONOCHROME        BIT(0)
+#define CURSOR_FORMAT_ARGB8888          BIT(1)
+#define CURSOR_LOCATION_BIT             BIT(4)
+
+#define LSDC_CURSOR_ADDR_REG            0x1530
+#define LSDC_CURSOR_POSITION_REG        0x1540
+#define LSDC_CURSOR_BG_COLOR_REG        0x1550  /* background color */
+#define LSDC_CURSOR_FG_COLOR_REG        0x1560  /* foreground color */
+
+#define CUR_WIDTH_SIZE                  32
+#define CUR_HEIGHT_SIZE                 32
+
+#define LSDC_CURS_MIN_SIZE              1
+#define LSDC_CURS_MAX_SIZE              64
+
+/*
+ * DC Interrupt Control Register, 32bit, Address Offset: 1570
+ *
+ * Bits  0:10 inidicate the interrupt type, read only
+ * Bits 16:26 control if the specific interrupt corresponding to bit 0~10
+ * is enabled or not. Write 1 to enable, write 0 to disable
+ *
+ * RF: Read Finished
+ * IDBU : Internal Data Buffer Underflow
+ * IDBFU : Internal Data Buffer Fatal Underflow
+ *
+ *
+ * +-------+-------------------------------+-------+--------+--------+-------+
+ * | 31:27 |            26:16              | 15:11 |   10   |   9    |   8   |
+ * +-------+-------------------------------+-------+--------+--------+-------+
+ * |  N/A  | Interrupt Enable Control Bits |  N/A  | IDBFU0 | IDBFU1 | IDBU0 |
+ * +-------+-------------------------------+-------+--------+--------+-------+
+ *
+ * Bit 4 is cursor buffer read finished, no use.
+ *
+ * +-------+-----+-----+-----+--------+--------+--------+--------+
+ * |   7   |  6  |  5  |  4  |   3    |   2    |   1    |   0    |
+ * +-------+-----+-----+-----+--------+--------+--------+--------+
+ * | IDBU1 | RF0 | RF1 |     | HSYNC0 | VSYNC0 | HSYNC1 | VSYNC1 |
+ * +-------+-----+-----+-----+--------+--------+--------+--------+
+ *
+ */
+
+#define LSDC_INT_REG                           0x1570
+
+#define INT_CRTC0_VS                           BIT(2)
+#define INT_CRTC0_HS                           BIT(3)
+#define INT_CRTC0_RF                           BIT(6)
+#define INT_CRTC0_IDBU                         BIT(8)
+#define INT_CRTC0_IDBFU                        BIT(10)
+
+#define INT_CURSOR_RF                          BIT(4)
+
+#define INT_CRTC1_VS                           BIT(0)
+#define INT_CRTC1_HS                           BIT(1)
+#define INT_CRTC1_RF                           BIT(5)
+#define INT_CRTC1_IDBU                         BIT(7)
+#define INT_CRTC1_IDBFU                        BIT(9)
+
+#define INT_CRTC0_VS_EN                        BIT(18)
+#define INT_CRTC0_HS_EN                        BIT(19)
+#define INT_CRTC0_RF_EN                        BIT(22)
+#define INT_CRTC0_IDBU_EN                      BIT(24)
+#define INT_CRTC0_IDBFU_EN                     BIT(26)
+
+#define INT_CURSOR_RF_EN                       BIT(20)
+
+#define INT_CRTC1_VS_EN                        BIT(16)
+#define INT_CRTC1_HS_EN                        BIT(17)
+#define INT_CRTC1_RF_EN                        BIT(21)
+#define INT_CRTC1_IDBU_EN                      BIT(23)
+#define INT_CRTC1_IDBFU_EN                     BIT(25)
+
+#define INT_STATUS_MASK                        GENMASK(10, 0)
+
+/*
+ * LS7A1000 have 4 gpios which is under control of the LS7A_DC_GPIO_DAT_REG
+ * and LS7A_DC_GPIO_DIR_REG register, it has no relationship whth the general
+ * GPIO hardware. Those registers are in the DC register space on LS7A1000.
+ *
+ * Those GPIOs are used to emulated I2C, for reading edid and monitor detection
+ *
+ * LS2k1000 and LS2K0500 don't have those registers, they use hardware i2c or
+ * generial GPIO emulated i2c from other module.
+ *
+ * GPIO data register
+ *  Address offset: 0x1650
+ *   +---------------+-----------+-----------+
+ *   | 7 | 6 | 5 | 4 |  3  |  2  |  1  |  0  |
+ *   +---------------+-----------+-----------+
+ *   |               |    DVO1   |    DVO0   |
+ *   +      N/A      +-----------+-----------+
+ *   |               | SCL | SDA | SCL | SDA |
+ *   +---------------+-----------+-----------+
+ */
+#define LS7A_DC_GPIO_DAT_REG                   0x1650
+
+/*
+ *  GPIO Input/Output direction control register
+ *  Address offset: 0x1660
+ *  write 1 for Input, 0 for Output.
+ */
+#define LS7A_DC_GPIO_DIR_REG                   0x1660
+
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-21 16:29 ` [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller Sui Jingfeng
@ 2022-03-21 23:20   ` Rob Herring
  2022-03-22  2:33     ` Sui Jingfeng
  0 siblings, 1 reply; 48+ messages in thread
From: Rob Herring @ 2022-03-21 23:20 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel

On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
> From: suijingfeng <suijingfeng@loongson.cn>
> 

Needs a commit message.

> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> Signed-off-by: Sui Jingfeng <15330273260@189.cn>

Same person? Don't need both emails.

> ---
>  .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
>  1 file changed, 230 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> new file mode 100644
> index 000000000000..7be63346289e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> @@ -0,0 +1,230 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
> +
> +maintainers:
> +  - Sui Jingfeng <suijingfeng@loongson.cn>
> +
> +description: |+
> +
> +  Loongson display controllers are simple which require scanout buffers
> +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
> +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
> +  with a dedicated video RAM which is 64MB or more, precise size can be
> +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
> +  chip.
> +
> +  LSDC has two display pipes, each way has a DVO interface which provide
> +  RGB888 signals, vertical & horizontal synchronisations, data enable and
> +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
> +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
> +
> +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
> +  located at the DC register space. They are used to emulate two way i2c,
> +  One for DVO0, another for DVO1.
> +
> +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
> +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
> +
> +  LSDC's display pipeline have several components as below description,
> +
> +  The display controller in LS7A1000:
> +     ___________________                                     _________
> +    |            -------|                                   |         |
> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> +    |  _   _     -------|        ^             ^            |_________|
> +    | | | | |    -------|        |             |
> +    | |_| |_|    | i2c0 <--------+-------------+
> +    |            -------|
> +    |   DC IN LS7A1000  |
> +    |  _   _     -------|
> +    | | | | |    | i2c1 <--------+-------------+
> +    | |_| |_|    -------|        |             |             _________
> +    |            -------|        |             |            |         |
> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> +    |            -------|                                   |_________|
> +    |___________________|
> +
> +  Simple usage of LS7A1000 with LS3A4000 CPU:
> +
> +    +------+            +-----------------------------------+
> +    | DDR4 |            |  +-------------------+            |
> +    +------+            |  | PCIe Root complex |   LS7A1000 |
> +       || MC0           |  +--++---------++----+            |
> +  +----------+  HT 3.0  |     ||         ||                 |
> +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
> +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
> +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
> +       || MC1           +---------------|--|----------------+
> +    +------+                            |  |
> +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
> +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
> +                      +-------+                      +------+
> +
> +  The display controller in LS2K1000/LS2K0500:
> +     ___________________                                     _________
> +    |            -------|                                   |         |
> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> +    |  _   _     -------|        ^              ^           |_________|
> +    | | | | |           |        |              |
> +    | |_| |_|           |     +------+          |
> +    |                   <---->| i2c0 |<---------+
> +    |   DC IN LS2K1000  |     +------+
> +    |  _   _            |     +------+
> +    | | | | |           <---->| i2c1 |----------+
> +    | |_| |_|           |     +------+          |            _________
> +    |            -------|        |              |           |         |
> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> +    |            -------|                                   |_________|
> +    |___________________|
> +
> +properties:
> +  $nodename:
> +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
> +
> +  compatible:
> +    oneOf:
> +      - items:
> +          - enum:
> +              - loongson,ls7a1000-dc
> +              - loongson,ls2k1000-dc
> +              - loongson,ls2k0500-dc
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 0
> +
> +  i2c-gpio@0:
> +    description: |
> +      Built-in GPIO emulate i2c exported for external display bridge

If you have i2c-gpio, that belongs at the DT top-level, not here.

> +      configuration, onitor detection and edid read back etc, for ls7a1000
> +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be

No, there's a defined i2c-gpio compatible already.

> +      used to specify a I2c adapter bus number, if you don't specify one
> +      i2c driver core will dynamically assign a bus number. Please specify

Bus numbers are a linux detail not relevant to DT binding.

> +      it only when its bus number matters. Bus number greater than 6 is safe
> +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
> +
> +  i2c-gpio@1:
> +    description: |
> +      Built-in GPIO emulate i2c exported for external display bridge
> +      configuration, onitor detection and edid read back etc, for ls7a1000
> +      only. Its compatible must be lsdc,i2c-gpio-1.
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +
> +    properties:
> +      port@0:
> +        $ref: /schemas/graph.yaml#/properties/port
> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> +
> +      port@1:
> +        $ref: /schemas/graph.yaml#/properties/port
> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> +
> +    required:
> +      - port@0
> +      - port@1
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - ports
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    bus {
> +
> +        #address-cells = <3>;
> +        #size-cells = <2>;
> +        #interrupt-cells = <2>;
> +
> +        display-controller@6,1 {
> +            compatible = "loongson,ls7a1000-dc";
> +            reg = <0x3100 0x0 0x0 0x0 0x0>;
> +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
> +
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +
> +            i2c-gpio@0 {
> +                compatible = "lsdc,i2c-gpio-0";
> +                reg = <6>;
> +                sda = <0>;
> +                scl = <1>;
> +            };
> +
> +            i2c-gpio@1 {
> +                compatible = "lsdc,i2c-gpio-1";
> +                reg = <7>;
> +                sda = <2>;
> +                scl = <3>;
> +            };
> +
> +            ports {
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +                port@0 {
> +                    reg = <0>;
> +                    endpoint {
> +                            remote-endpoint = <&vga_encoder_in>;
> +                    };
> +                };
> +                port@1 {
> +                    reg = <1>;
> +                    endpoint {
> +                            remote-endpoint = <&dvi_encoder_in>;
> +                    };
> +                };
> +            };
> +        };
> +    };
> +
> +  - |
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    bus {
> +
> +        #address-cells = <3>;
> +        #size-cells = <2>;
> +        #interrupt-cells = <2>;
> +
> +        display-controller@6,0 {
> +            compatible = "loongson,ls2k1000-dc";
> +            reg = <0x3100 0x0 0x0 0x0 0x0>;
> +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
> +
> +            ports {
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +                port@0 {
> +                    reg = <0>;
> +                    endpoint {
> +                            remote-endpoint = <&panel_in>;
> +                    };
> +                };
> +                port@1 {
> +                    reg = <1>;
> +                    endpoint {
> +                            remote-endpoint = <&hdmi_encoder_in>;
> +                    };
> +                };
> +            };
> +        };
> +    };
> +...
> -- 
> 2.25.1
> 
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-21 23:20   ` Rob Herring
@ 2022-03-22  2:33     ` Sui Jingfeng
  2022-03-22 13:08       ` Jiaxun Yang
  2022-03-22 20:55       ` Rob Herring
  0 siblings, 2 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-22  2:33 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel


On 2022/3/22 07:20, Rob Herring wrote:
> On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
>> From: suijingfeng <suijingfeng@loongson.cn>
>>
> Needs a commit message.
>
>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
> Same person? Don't need both emails.

Yes,  suijingfeng@loongson.cn is my company's email. But it can not be 
used to send patches to dri-devel,

when send patches with this email, the patch will not be shown on patch 
works.

Emails  are either blocked or got  rejected  by loongson's mail server.  
It can only receive emails

from you and other people, but not dri-devel. so have to use my personal 
email(15330273260@189.cn) to send patches.

>> ---
>>   .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
>>   1 file changed, 230 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>> new file mode 100644
>> index 000000000000..7be63346289e
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>> @@ -0,0 +1,230 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
>> +
>> +maintainers:
>> +  - Sui Jingfeng <suijingfeng@loongson.cn>
>> +
>> +description: |+
>> +
>> +  Loongson display controllers are simple which require scanout buffers
>> +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
>> +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
>> +  with a dedicated video RAM which is 64MB or more, precise size can be
>> +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
>> +  chip.
>> +
>> +  LSDC has two display pipes, each way has a DVO interface which provide
>> +  RGB888 signals, vertical & horizontal synchronisations, data enable and
>> +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
>> +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
>> +
>> +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
>> +  located at the DC register space. They are used to emulate two way i2c,
>> +  One for DVO0, another for DVO1.
>> +
>> +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
>> +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
>> +
>> +  LSDC's display pipeline have several components as below description,
>> +
>> +  The display controller in LS7A1000:
>> +     ___________________                                     _________
>> +    |            -------|                                   |         |
>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>> +    |  _   _     -------|        ^             ^            |_________|
>> +    | | | | |    -------|        |             |
>> +    | |_| |_|    | i2c0 <--------+-------------+
>> +    |            -------|
>> +    |   DC IN LS7A1000  |
>> +    |  _   _     -------|
>> +    | | | | |    | i2c1 <--------+-------------+
>> +    | |_| |_|    -------|        |             |             _________
>> +    |            -------|        |             |            |         |
>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>> +    |            -------|                                   |_________|
>> +    |___________________|
>> +
>> +  Simple usage of LS7A1000 with LS3A4000 CPU:
>> +
>> +    +------+            +-----------------------------------+
>> +    | DDR4 |            |  +-------------------+            |
>> +    +------+            |  | PCIe Root complex |   LS7A1000 |
>> +       || MC0           |  +--++---------++----+            |
>> +  +----------+  HT 3.0  |     ||         ||                 |
>> +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>> +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>> +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
>> +       || MC1           +---------------|--|----------------+
>> +    +------+                            |  |
>> +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>> +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>> +                      +-------+                      +------+
>> +
>> +  The display controller in LS2K1000/LS2K0500:
>> +     ___________________                                     _________
>> +    |            -------|                                   |         |
>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>> +    |  _   _     -------|        ^              ^           |_________|
>> +    | | | | |           |        |              |
>> +    | |_| |_|           |     +------+          |
>> +    |                   <---->| i2c0 |<---------+
>> +    |   DC IN LS2K1000  |     +------+
>> +    |  _   _            |     +------+
>> +    | | | | |           <---->| i2c1 |----------+
>> +    | |_| |_|           |     +------+          |            _________
>> +    |            -------|        |              |           |         |
>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>> +    |            -------|                                   |_________|
>> +    |___________________|
>> +
>> +properties:
>> +  $nodename:
>> +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
>> +
>> +  compatible:
>> +    oneOf:
>> +      - items:
>> +          - enum:
>> +              - loongson,ls7a1000-dc
>> +              - loongson,ls2k1000-dc
>> +              - loongson,ls2k0500-dc
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  interrupts:
>> +    maxItems: 1
>> +
>> +  '#address-cells':
>> +    const: 1
>> +
>> +  '#size-cells':
>> +    const: 0
>> +
>> +  i2c-gpio@0:
>> +    description: |
>> +      Built-in GPIO emulate i2c exported for external display bridge
> If you have i2c-gpio, that belongs at the DT top-level, not here.
>
>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>> +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
> No, there's a defined i2c-gpio compatible already.

This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
LSDC register space, not general purpose GPIOs with separate control register resource.
So i think it is the child node of display-controller@6,1, it belongs to LSDC.
It seems that put it at the DT top-level break the hierarchy and relationship.

>> +      used to specify a I2c adapter bus number, if you don't specify one
>> +      i2c driver core will dynamically assign a bus number. Please specify
> Bus numbers are a linux detail not relevant to DT binding.
>
>> +      it only when its bus number matters. Bus number greater than 6 is safe
>> +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
>> +
>> +  i2c-gpio@1:
>> +    description: |
>> +      Built-in GPIO emulate i2c exported for external display bridge
>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>> +      only. Its compatible must be lsdc,i2c-gpio-1.
>> +
>> +  ports:
>> +    $ref: /schemas/graph.yaml#/properties/ports
>> +
>> +    properties:
>> +      port@0:
>> +        $ref: /schemas/graph.yaml#/properties/port
>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>> +
>> +      port@1:
>> +        $ref: /schemas/graph.yaml#/properties/port
>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>> +
>> +    required:
>> +      - port@0
>> +      - port@1
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - interrupts
>> +  - ports
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +    #include <dt-bindings/interrupt-controller/irq.h>
>> +    bus {
>> +
>> +        #address-cells = <3>;
>> +        #size-cells = <2>;
>> +        #interrupt-cells = <2>;
>> +
>> +        display-controller@6,1 {
>> +            compatible = "loongson,ls7a1000-dc";
>> +            reg = <0x3100 0x0 0x0 0x0 0x0>;
>> +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
>> +
>> +            #address-cells = <1>;
>> +            #size-cells = <0>;
>> +
>> +            i2c-gpio@0 {
>> +                compatible = "lsdc,i2c-gpio-0";
>> +                reg = <6>;
>> +                sda = <0>;
>> +                scl = <1>;
>> +            };
>> +
>> +            i2c-gpio@1 {
>> +                compatible = "lsdc,i2c-gpio-1";
>> +                reg = <7>;
>> +                sda = <2>;
>> +                scl = <3>;
>> +            };
>> +
>> +            ports {
>> +                #address-cells = <1>;
>> +                #size-cells = <0>;
>> +                port@0 {
>> +                    reg = <0>;
>> +                    endpoint {
>> +                            remote-endpoint = <&vga_encoder_in>;
>> +                    };
>> +                };
>> +                port@1 {
>> +                    reg = <1>;
>> +                    endpoint {
>> +                            remote-endpoint = <&dvi_encoder_in>;
>> +                    };
>> +                };
>> +            };
>> +        };
>> +    };
>> +
>> +  - |
>> +    #include <dt-bindings/interrupt-controller/irq.h>
>> +    bus {
>> +
>> +        #address-cells = <3>;
>> +        #size-cells = <2>;
>> +        #interrupt-cells = <2>;
>> +
>> +        display-controller@6,0 {
>> +            compatible = "loongson,ls2k1000-dc";
>> +            reg = <0x3100 0x0 0x0 0x0 0x0>;
>> +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
>> +
>> +            ports {
>> +                #address-cells = <1>;
>> +                #size-cells = <0>;
>> +                port@0 {
>> +                    reg = <0>;
>> +                    endpoint {
>> +                            remote-endpoint = <&panel_in>;
>> +                    };
>> +                };
>> +                port@1 {
>> +                    reg = <1>;
>> +                    endpoint {
>> +                            remote-endpoint = <&hdmi_encoder_in>;
>> +                    };
>> +                };
>> +            };
>> +        };
>> +    };
>> +...
>> -- 
>> 2.25.1
>>
>>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-21 16:29 ` [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board Sui Jingfeng
@ 2022-03-22 13:05   ` Jiaxun Yang
  2022-03-22 13:38     ` Sui Jingfeng
  0 siblings, 1 reply; 48+ messages in thread
From: Jiaxun Yang @ 2022-03-22 13:05 UTC (permalink / raw)
  To: Sui Jingfeng, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Rob Herring, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel



在 2022/3/21 16:29, Sui Jingfeng 写道:
> From: suijingfeng <suijingfeng@loongson.cn>
>
> The board name is LS3A4000_7A1000_EVB_BOARD_V1.4, it consist of 1.8Ghz
> mips64r5 4-core CPU and LS7A1000 bridge chip. It has PCIe GEN2 x8 slot,
> therefore can play with discrete graphics card.

Hi Jingfeng,

As we've discussed before if you are going to introduce new dts then you 
*MUST*
include it in makefile and wire it up in code.

A dts file doing nothing lying in the tree is just suspicious.

Thanks.
- Jiaxun

>
> While the integrated display copntroller is equipped with a VGA output
> and a DVI output, the VGA is connect to the DVO0 output port of the
> display controller, the DVI is connected to DVO1 output port of the
> display controller.
>
>      +------+            +-----------------------------------+
>      | DDR4 |            |  +-------------------+            |
>      +------+            |  | PCIe Root complex |   LS7A1000 |
>         || MC0           |  +--++---------++----+            |
>    +----------+  HT 3.0  |     ||         ||                 |
>    | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>    |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>    +----------+          | +--------+  +-+--+-+    +---------+   +------+
>         || MC1           +---------------|--|----------------+
>      +------+                            |  |
>      | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>      +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>                        +-------+                      +------+
>
> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
> ---
>   .../boot/dts/loongson/ls3a4000_7a1000_evb.dts | 136 ++++++++++++++++++
>   1 file changed, 136 insertions(+)
>   create mode 100644 arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts
>
> diff --git a/arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts b/arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts
> new file mode 100644
> index 000000000000..f467eddccdac
> --- /dev/null
> +++ b/arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts
> @@ -0,0 +1,136 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/dts-v1/;
> +
> +#include "loongson64g-package.dtsi"
> +#include "ls7a-pch.dtsi"
> +
> +/ {
> +	compatible = "loongson,loongson64g-4core-ls7a";
> +	model = "LS3A4000_7A1000_EVB_BOARD_V1.4";
> +
> +	vga-encoder {
> +		compatible = "adi,adv7123", "dumb-vga-dac";
> +
> +		ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			port@0 {
> +				reg = <0>;
> +				adv7123_in: endpoint {
> +					remote-endpoint = <&dc_out_rgb0>;
> +				};
> +			};
> +
> +			port@1 {
> +				reg = <1>;
> +				adv7123_out: endpoint {
> +					remote-endpoint = <&vga_connector_in>;
> +				};
> +			};
> +		};
> +	};
> +
> +	vga-connector {
> +		compatible = "vga-connector";
> +		label = "vga";
> +
> +		ddc-i2c-bus = <&i2c6>;
> +
> +		port {
> +			vga_connector_in: endpoint {
> +				remote-endpoint = <&adv7123_out>;
> +			};
> +		};
> +	};
> +
> +	tfp410: dvi-encoder {
> +		compatible = "ti,tfp410";
> +
> +		ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			port@0 {
> +				reg = <0>;
> +				tfp410_in: endpoint {
> +					pclk-sample = <1>;
> +					bus-width = <24>;
> +					remote-endpoint = <&dc_out_rgb1>;
> +				};
> +			};
> +
> +			port@1 {
> +				reg = <1>;
> +				tfp410_out: endpoint {
> +					remote-endpoint = <&dvi_connector_in>;
> +				};
> +			};
> +		};
> +	};
> +
> +	dvi-connector {
> +		compatible = "dvi-connector";
> +		label = "dvi";
> +		digital;
> +
> +		ddc-i2c-bus = <&i2c7>;
> +
> +		port {
> +			dvi_connector_in: endpoint {
> +				remote-endpoint = <&tfp410_out>;
> +			};
> +		};
> +	};
> +};
> +
> +&package0 {
> +	htvec: interrupt-controller@efdfb000080 {
> +		compatible = "loongson,htvec-1.0";
> +		reg = <0xefd 0xfb000080 0x40>;
> +		interrupt-controller;
> +		#interrupt-cells = <1>;
> +
> +		interrupt-parent = <&liointc>;
> +		interrupts = <24 IRQ_TYPE_LEVEL_HIGH>,
> +			     <25 IRQ_TYPE_LEVEL_HIGH>,
> +			     <26 IRQ_TYPE_LEVEL_HIGH>,
> +			     <27 IRQ_TYPE_LEVEL_HIGH>,
> +			     <28 IRQ_TYPE_LEVEL_HIGH>,
> +			     <29 IRQ_TYPE_LEVEL_HIGH>,
> +			     <30 IRQ_TYPE_LEVEL_HIGH>,
> +			     <31 IRQ_TYPE_LEVEL_HIGH>;
> +	};
> +};
> +
> +&pch {
> +	msi: msi-controller@2ff00000 {
> +		compatible = "loongson,pch-msi-1.0";
> +		reg = <0 0x2ff00000 0 0x8>;
> +		interrupt-controller;
> +		msi-controller;
> +		loongson,msi-base-vec = <64>;
> +		loongson,msi-num-vecs = <192>;
> +		interrupt-parent = <&htvec>;
> +	};
> +};
> +
> +&lsdc {
> +	ports {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		port@0 {
> +			endpoint {
> +				remote-endpoint = <&adv7123_in>;
> +			};
> +		};
> +
> +		port@1 {
> +			endpoint {
> +				remote-endpoint = <&tfp410_in>;
> +			};
> +		};
> +	};
> +};


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-22  2:33     ` Sui Jingfeng
@ 2022-03-22 13:08       ` Jiaxun Yang
  2022-03-22 13:54         ` Sui Jingfeng
  2022-03-22 20:55       ` Rob Herring
  1 sibling, 1 reply; 48+ messages in thread
From: Jiaxun Yang @ 2022-03-22 13:08 UTC (permalink / raw)
  To: Sui Jingfeng, Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Lucas Stach,
	Maarten Lankhorst, Ilia Mirkin, Qing Zhang, suijingfeng,
	linux-mips, linux-kernel, devicetree, dri-devel



在 2022/3/22 2:33, Sui Jingfeng 写道:
>
> On 2022/3/22 07:20, Rob Herring wrote:
>> On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>
>> Needs a commit message.
>>
>>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>> Same person? Don't need both emails.
>
> Yes,  suijingfeng@loongson.cn is my company's email. But it can not be 
> used to send patches to dri-devel,
>
> when send patches with this email, the patch will not be shown on 
> patch works.
>
> Emails  are either blocked or got  rejected  by loongson's mail 
> server.  It can only receive emails
>
> from you and other people, but not dri-devel. so have to use my 
> personal email(15330273260@189.cn) to send patches.
In this case you can just use your company's email to sign-off
code and sending with your personal email. It's common practice.

If you don't want to receiving kernel email in your company mailbox,
you can add a entry in .mailmap .

Thanks.
- Jiaxun

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-22 13:05   ` Jiaxun Yang
@ 2022-03-22 13:38     ` Sui Jingfeng
  2022-03-22 16:06       ` Jiaxun Yang
  0 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-22 13:38 UTC (permalink / raw)
  To: Jiaxun Yang, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Rob Herring, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel


On 2022/3/22 21:05, Jiaxun Yang wrote:
>
>
> 在 2022/3/21 16:29, Sui Jingfeng 写道:
>> From: suijingfeng <suijingfeng@loongson.cn>
>>
>> The board name is LS3A4000_7A1000_EVB_BOARD_V1.4, it consist of 1.8Ghz
>> mips64r5 4-core CPU and LS7A1000 bridge chip. It has PCIe GEN2 x8 slot,
>> therefore can play with discrete graphics card.
>
> Hi Jingfeng,
>
> As we've discussed before if you are going to introduce new dts then 
> you *MUST*
> include it in makefile and wire it up in code.
>
> A dts file doing nothing lying in the tree is just suspicious.
>
> Thanks.
> - Jiaxun
>
Hi, Jiaxun,

I know what you means, but it is the kernel side developer's job.
I am just a naive graphic driver developer,I can not care so much.
Below is my private patch which can be used to built specific dts
into the linux kernel, therefore make the verification easier.


diff --git a/arch/mips/boot/dts/loongson/Makefile b/arch/mips/boot/dts/loongson/Makefile
index 5c6433e441ee..99b66675c4a1 100644
--- a/arch/mips/boot/dts/loongson/Makefile
+++ b/arch/mips/boot/dts/loongson/Makefile
@@ -1,9 +1,22 @@
  # SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_MACH_LOONGSON64)	+= loongson64_2core_2k1000.dtb
-dtb-$(CONFIG_MACH_LOONGSON64)	+= loongson64c_4core_ls7a.dtb
-dtb-$(CONFIG_MACH_LOONGSON64)	+= loongson64c_4core_rs780e.dtb
-dtb-$(CONFIG_MACH_LOONGSON64)	+= loongson64c_8core_rs780e.dtb
-dtb-$(CONFIG_MACH_LOONGSON64)	+= loongson64g_4core_ls7a.dtb
-dtb-$(CONFIG_MACH_LOONGSON64)	+= loongson64v_4core_virtio.dtb
+
+dtb-$(CONFIG_LOONGSON64_LS2K1000_PAI_V1_5)	+= ls2k1000_pai.dtb
+dtb-$(CONFIG_LOONGSON64_LS2K1000_EVB_V1_2)	+= ls2k1000_evb.dtb
+dtb-$(CONFIG_LOONGSON64_LS2K1000_GENERIC)	+= loongson64_2core_2k1000.dtb
+
+dtb-$(CONFIG_LOONGSON64_LS3A3000_LS7A1000)	+= loongson64c_4core_ls7a.dtb
+dtb-$(CONFIG_LOONGSON64_LS3A3000_RS780E)	+= loongson64c_4core_rs780e.dtb
+dtb-$(CONFIG_LOONGSON64_LS3B3000_RS780E)	+= loongson64c_8core_rs780e.dtb
+
+dtb-$(CONFIG_LOONGSON64_LS3A4000_7A1000_LEMOTE_A1901) += lemote_a1901.dtb
+dtb-$(CONFIG_LOONGSON64_LS3A4000_7A1000_EVB_V1_4) += ls3a4000_7a1000_evb.dtb
+dtb-$(CONFIG_LOONGSON64_LS3A4000_7A1000_GENERIC)  += loongson64g_4core_ls7a.dtb
+
+dtb-$(CONFIG_LOONGSON64_BOARD_DEFAULT)	+= loongson64_2core_2k1000.dtb
+dtb-$(CONFIG_LOONGSON64_BOARD_DEFAULT)	+= loongson64c_4core_ls7a.dtb
+dtb-$(CONFIG_LOONGSON64_BOARD_DEFAULT)	+= loongson64c_4core_rs780e.dtb
+dtb-$(CONFIG_LOONGSON64_BOARD_DEFAULT)	+= loongson64c_8core_rs780e.dtb
+dtb-$(CONFIG_LOONGSON64_BOARD_DEFAULT)	+= loongson64g_4core_ls7a.dtb
+dtb-$(CONFIG_LOONGSON64_BOARD_DEFAULT)	+= loongson64v_4core_virtio.dtb
  
  obj-$(CONFIG_BUILTIN_DTB)	+= $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/include/asm/mach-loongson64/builtin_dtbs.h b/arch/mips/include/asm/mach-loongson64/builtin_dtbs.h
index 8be710557bdb..605bfa47b4b9 100644
--- a/arch/mips/include/asm/mach-loongson64/builtin_dtbs.h
+++ b/arch/mips/include/asm/mach-loongson64/builtin_dtbs.h
@@ -8,10 +8,10 @@
  #ifndef __ASM_MACH_LOONGSON64_BUILTIN_DTBS_H_
  #define __ASM_MACH_LOONGSON64_BUILTIN_DTBS_H_
  
-extern u32 __dtb_loongson64_2core_2k1000_begin[];
-extern u32 __dtb_loongson64c_4core_ls7a_begin[];
-extern u32 __dtb_loongson64c_4core_rs780e_begin[];
-extern u32 __dtb_loongson64c_8core_rs780e_begin[];
-extern u32 __dtb_loongson64g_4core_ls7a_begin[];
-extern u32 __dtb_loongson64v_4core_virtio_begin[];
+extern u32 __weak __dtb_loongson64_2core_2k1000_begin[];
+extern u32 __weak __dtb_loongson64c_4core_ls7a_begin[];
+extern u32 __weak __dtb_loongson64c_4core_rs780e_begin[];
+extern u32 __weak __dtb_loongson64c_8core_rs780e_begin[];
+extern u32 __weak __dtb_loongson64g_4core_ls7a_begin[];
+extern u32 __weak __dtb_loongson64v_4core_virtio_begin[];
  #endif
diff --git a/arch/mips/loongson64/Kconfig b/arch/mips/loongson64/Kconfig
index 517f1f8e81fb..7030185ed0c6 100644
--- a/arch/mips/loongson64/Kconfig
+++ b/arch/mips/loongson64/Kconfig
@@ -12,4 +12,43 @@ config RS780_HPET
  	  Note: This driver is doing some dangerous hack. Please only enable
  	  it on RS780E systems.
  
+choice
+	prompt "Board type"
+	depends on MACH_LOONGSON64
+	depends on BUILTIN_DTB
+	help
+	 pick a device tree that matches the target board.
+
+config LOONGSON64_BOARD_DEFAULT
+	bool "Default"
+
+config LOONGSON64_LS3A4000_7A1000_LEMOTE_A1901
+	bool "LEMOTE A1901 LS3A4000 board"
+
+config LOONGSON64_LS3A4000_7A1000_EVB_V1_4
+	bool "LS3A4000 LS7A1000 evaluation board v1.4"
+
+config LOONGSON64_LS3A4000_7A1000_GENERIC
+	bool "LS3A4000 LS7A1000 generic board"
+
+config LOONGSON64_LS3A3000_LS7A1000
+	bool "LS3A3000 LS7A1000 generic board"
+
+config LOONGSON64_LS3A3000_RS780E
+	bool "LS3A3000 RS780E generic board"
+
+config LOONGSON64_LS3B3000_RS780E
+	bool "LS3B3000 RS780E generic board"
+
+config LOONGSON64_LS2K1000_PAI_V1_5
+	bool "LS2K1000 PAI board V1.5"
+
+config LOONGSON64_LS2K1000_EVB_V1_2
+	bool "LS2K1000 evaluation board V1.2"
+
+config LOONGSON64_LS2K1000_GENERIC
+	bool "LS2K1000 generic"
+
+endchoice
+
  endif # MACH_LOONGSON64
diff --git a/arch/mips/loongson64/setup.c b/arch/mips/loongson64/setup.c
index cb10d14da433..f8859039a4e0 100644
--- a/arch/mips/loongson64/setup.c
+++ b/arch/mips/loongson64/setup.c
@@ -16,6 +16,13 @@ void *loongson_fdt_blob;
  
  void __init plat_mem_setup(void)
  {
+	void *fdt;
+
+	fdt = get_fdt();
+
+	if (fdt)
+		loongson_fdt_blob = fdt;
+
  	if (loongson_fdt_blob)
  		__dt_setup_arch(loongson_fdt_blob);
  }

>>
>> While the integrated display copntroller is equipped with a VGA output
>> and a DVI output, the VGA is connect to the DVO0 output port of the
>> display controller, the DVI is connected to DVO1 output port of the
>> display controller.
>>
>>      +------+            +-----------------------------------+
>>      | DDR4 |            |  +-------------------+            |
>>      +------+            |  | PCIe Root complex |   LS7A1000 |
>>         || MC0           |  +--++---------++----+            |
>>    +----------+  HT 3.0  |     ||         ||                 |
>>    | LS3A4000 |<-------->| +---++---+  +--++--+ +---------+   +------+
>>    |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| 
>> VRAM |
>>    +----------+          | +--------+  +-+--+-+    +---------+ +------+
>>         || MC1           +---------------|--|----------------+
>>      +------+                            |  |
>>      | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>>      +------+   VGA <--|ADV7125|<--------+ +-------->|TFP410|--> 
>> DVI/HDMI
>>                        +-------+                      +------+
>>
>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>> ---
>>   .../boot/dts/loongson/ls3a4000_7a1000_evb.dts | 136 ++++++++++++++++++
>>   1 file changed, 136 insertions(+)
>>   create mode 100644 arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts
>>
>> diff --git a/arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts 
>> b/arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts
>> new file mode 100644
>> index 000000000000..f467eddccdac
>> --- /dev/null
>> +++ b/arch/mips/boot/dts/loongson/ls3a4000_7a1000_evb.dts
>> @@ -0,0 +1,136 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +/dts-v1/;
>> +
>> +#include "loongson64g-package.dtsi"
>> +#include "ls7a-pch.dtsi"
>> +
>> +/ {
>> +    compatible = "loongson,loongson64g-4core-ls7a";
>> +    model = "LS3A4000_7A1000_EVB_BOARD_V1.4";
>> +
>> +    vga-encoder {
>> +        compatible = "adi,adv7123", "dumb-vga-dac";
>> +
>> +        ports {
>> +            #address-cells = <1>;
>> +            #size-cells = <0>;
>> +
>> +            port@0 {
>> +                reg = <0>;
>> +                adv7123_in: endpoint {
>> +                    remote-endpoint = <&dc_out_rgb0>;
>> +                };
>> +            };
>> +
>> +            port@1 {
>> +                reg = <1>;
>> +                adv7123_out: endpoint {
>> +                    remote-endpoint = <&vga_connector_in>;
>> +                };
>> +            };
>> +        };
>> +    };
>> +
>> +    vga-connector {
>> +        compatible = "vga-connector";
>> +        label = "vga";
>> +
>> +        ddc-i2c-bus = <&i2c6>;
>> +
>> +        port {
>> +            vga_connector_in: endpoint {
>> +                remote-endpoint = <&adv7123_out>;
>> +            };
>> +        };
>> +    };
>> +
>> +    tfp410: dvi-encoder {
>> +        compatible = "ti,tfp410";
>> +
>> +        ports {
>> +            #address-cells = <1>;
>> +            #size-cells = <0>;
>> +
>> +            port@0 {
>> +                reg = <0>;
>> +                tfp410_in: endpoint {
>> +                    pclk-sample = <1>;
>> +                    bus-width = <24>;
>> +                    remote-endpoint = <&dc_out_rgb1>;
>> +                };
>> +            };
>> +
>> +            port@1 {
>> +                reg = <1>;
>> +                tfp410_out: endpoint {
>> +                    remote-endpoint = <&dvi_connector_in>;
>> +                };
>> +            };
>> +        };
>> +    };
>> +
>> +    dvi-connector {
>> +        compatible = "dvi-connector";
>> +        label = "dvi";
>> +        digital;
>> +
>> +        ddc-i2c-bus = <&i2c7>;
>> +
>> +        port {
>> +            dvi_connector_in: endpoint {
>> +                remote-endpoint = <&tfp410_out>;
>> +            };
>> +        };
>> +    };
>> +};
>> +
>> +&package0 {
>> +    htvec: interrupt-controller@efdfb000080 {
>> +        compatible = "loongson,htvec-1.0";
>> +        reg = <0xefd 0xfb000080 0x40>;
>> +        interrupt-controller;
>> +        #interrupt-cells = <1>;
>> +
>> +        interrupt-parent = <&liointc>;
>> +        interrupts = <24 IRQ_TYPE_LEVEL_HIGH>,
>> +                 <25 IRQ_TYPE_LEVEL_HIGH>,
>> +                 <26 IRQ_TYPE_LEVEL_HIGH>,
>> +                 <27 IRQ_TYPE_LEVEL_HIGH>,
>> +                 <28 IRQ_TYPE_LEVEL_HIGH>,
>> +                 <29 IRQ_TYPE_LEVEL_HIGH>,
>> +                 <30 IRQ_TYPE_LEVEL_HIGH>,
>> +                 <31 IRQ_TYPE_LEVEL_HIGH>;
>> +    };
>> +};
>> +
>> +&pch {
>> +    msi: msi-controller@2ff00000 {
>> +        compatible = "loongson,pch-msi-1.0";
>> +        reg = <0 0x2ff00000 0 0x8>;
>> +        interrupt-controller;
>> +        msi-controller;
>> +        loongson,msi-base-vec = <64>;
>> +        loongson,msi-num-vecs = <192>;
>> +        interrupt-parent = <&htvec>;
>> +    };
>> +};
>> +
>> +&lsdc {
>> +    ports {
>> +        #address-cells = <1>;
>> +        #size-cells = <0>;
>> +
>> +        port@0 {
>> +            endpoint {
>> +                remote-endpoint = <&adv7123_in>;
>> +            };
>> +        };
>> +
>> +        port@1 {
>> +            endpoint {
>> +                remote-endpoint = <&tfp410_in>;
>> +            };
>> +        };
>> +    };
>> +};
>

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-22 13:08       ` Jiaxun Yang
@ 2022-03-22 13:54         ` Sui Jingfeng
  2022-03-22 16:08           ` Jiaxun Yang
  2022-03-22 20:03           ` Rob Herring
  0 siblings, 2 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-22 13:54 UTC (permalink / raw)
  To: Jiaxun Yang, Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Lucas Stach,
	Maarten Lankhorst, Ilia Mirkin, Qing Zhang, suijingfeng,
	linux-mips, linux-kernel, devicetree, dri-devel


On 2022/3/22 21:08, Jiaxun Yang wrote:
>
>
> 在 2022/3/22 2:33, Sui Jingfeng 写道:
>>
>> On 2022/3/22 07:20, Rob Herring wrote:
>>> On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
>>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>>
>>> Needs a commit message.
>>>
>>>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>>>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>>> Same person? Don't need both emails.
>>
>> Yes,  suijingfeng@loongson.cn is my company's email. But it can not 
>> be used to send patches to dri-devel,
>>
>> when send patches with this email, the patch will not be shown on 
>> patch works.
>>
>> Emails  are either blocked or got  rejected  by loongson's mail 
>> server.  It can only receive emails
>>
>> from you and other people, but not dri-devel. so have to use my 
>> personal email(15330273260@189.cn) to send patches.
> In this case you can just use your company's email to sign-off
> code and sending with your personal email. It's common practice.
>
> If you don't want to receiving kernel email in your company mailbox,
> you can add a entry in .mailmap .
>
|I'm using `git send-email -7 --cover-letter --annotate -v11` command to 
send patches, it will automatically sign off patches with the my private 
emails. |

> Thanks.
> - Jiaxun

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-22 13:38     ` Sui Jingfeng
@ 2022-03-22 16:06       ` Jiaxun Yang
  2022-03-23  1:53         ` Sui Jingfeng
  0 siblings, 1 reply; 48+ messages in thread
From: Jiaxun Yang @ 2022-03-22 16:06 UTC (permalink / raw)
  To: Sui Jingfeng, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Rob Herring, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel



在 2022/3/22 13:38, Sui Jingfeng 写道:
>
> On 2022/3/22 21:05, Jiaxun Yang wrote:
>>
>>
>> 在 2022/3/21 16:29, Sui Jingfeng 写道:
>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>
>>> The board name is LS3A4000_7A1000_EVB_BOARD_V1.4, it consist of 1.8Ghz
>>> mips64r5 4-core CPU and LS7A1000 bridge chip. It has PCIe GEN2 x8 slot,
>>> therefore can play with discrete graphics card.
>>
>> Hi Jingfeng,
>>
>> As we've discussed before if you are going to introduce new dts then 
>> you *MUST*
>> include it in makefile and wire it up in code.
>>
>> A dts file doing nothing lying in the tree is just suspicious.
>>
>> Thanks.
>> - Jiaxun
>>
> Hi, Jiaxun,
>
> I know what you means, but it is the kernel side developer's job.
> I am just a naive graphic driver developer,I can not care so much.
> Below is my private patch which can be used to built specific dts
> into the linux kernel, therefore make the verification easier.
Hi Jingfeng,

In kernel world we take care all the stuff we touched ourself :-)

If you are not confident with them please drop those DTS from the patchset
besides the generic one. I can do the rest for you after getting this 
set merged.

Thanks.
- Jiaxun


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-22 13:54         ` Sui Jingfeng
@ 2022-03-22 16:08           ` Jiaxun Yang
  2022-03-22 20:03           ` Rob Herring
  1 sibling, 0 replies; 48+ messages in thread
From: Jiaxun Yang @ 2022-03-22 16:08 UTC (permalink / raw)
  To: Sui Jingfeng, Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Lucas Stach,
	Maarten Lankhorst, Ilia Mirkin, Qing Zhang, suijingfeng,
	linux-mips, linux-kernel, devicetree, dri-devel



在 2022/3/22 13:54, Sui Jingfeng 写道:
>
> On 2022/3/22 21:08, Jiaxun Yang wrote:
>>
>>
>> 在 2022/3/22 2:33, Sui Jingfeng 写道:
>>>
>>> On 2022/3/22 07:20, Rob Herring wrote:
>>>> On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
>>>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>>>
>>>> Needs a commit message.
>>>>
>>>>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>>>>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>>>> Same person? Don't need both emails.
>>>
>>> Yes,  suijingfeng@loongson.cn is my company's email. But it can not 
>>> be used to send patches to dri-devel,
>>>
>>> when send patches with this email, the patch will not be shown on 
>>> patch works.
>>>
>>> Emails  are either blocked or got  rejected  by loongson's mail 
>>> server.  It can only receive emails
>>>
>>> from you and other people, but not dri-devel. so have to use my 
>>> personal email(15330273260@189.cn) to send patches.
>> In this case you can just use your company's email to sign-off
>> code and sending with your personal email. It's common practice.
>>
>> If you don't want to receiving kernel email in your company mailbox,
>> you can add a entry in .mailmap .
>>
> |I'm using `git send-email -7 --cover-letter --annotate -v11` command 
> to send patches, it will automatically sign off patches with the my 
> private emails. |
The alternative solution is:

git format-patch -7 -v11 --cover-letter
git send-email ./*.patch

Thanks.
- Jiaxun

>
>> Thanks.
>> - Jiaxun


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-22 13:54         ` Sui Jingfeng
  2022-03-22 16:08           ` Jiaxun Yang
@ 2022-03-22 20:03           ` Rob Herring
  1 sibling, 0 replies; 48+ messages in thread
From: Rob Herring @ 2022-03-22 20:03 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Jiaxun Yang, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng, linux-mips, linux-kernel, devicetree,
	dri-devel

On Tue, Mar 22, 2022 at 09:54:08PM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/22 21:08, Jiaxun Yang wrote:
> > 
> > 
> > 在 2022/3/22 2:33, Sui Jingfeng 写道:
> > > 
> > > On 2022/3/22 07:20, Rob Herring wrote:
> > > > On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
> > > > > From: suijingfeng <suijingfeng@loongson.cn>
> > > > > 
> > > > Needs a commit message.
> > > > 
> > > > > Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> > > > > Signed-off-by: Sui Jingfeng <15330273260@189.cn>
> > > > Same person? Don't need both emails.
> > > 
> > > Yes,  suijingfeng@loongson.cn is my company's email. But it can not
> > > be used to send patches to dri-devel,
> > > 
> > > when send patches with this email, the patch will not be shown on
> > > patch works.
> > > 
> > > Emails  are either blocked or got  rejected  by loongson's mail
> > > server.  It can only receive emails
> > > 
> > > from you and other people, but not dri-devel. so have to use my
> > > personal email(15330273260@189.cn) to send patches.
> > In this case you can just use your company's email to sign-off
> > code and sending with your personal email. It's common practice.
> > 
> > If you don't want to receiving kernel email in your company mailbox,
> > you can add a entry in .mailmap .
> > 
> |I'm using `git send-email -7 --cover-letter --annotate -v11` command to
> send patches, it will automatically sign off patches with the my private
> emails. |

I think that is only if you set your git config author to your private 
email. Pretty much anything git might automatically do can be turned 
off.

Rob


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-21 16:29 ` [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
@ 2022-03-22 20:49   ` Rob Herring
  2022-03-23  4:12     ` Sui Jingfeng
                       ` (7 more replies)
  0 siblings, 8 replies; 48+ messages in thread
From: Rob Herring @ 2022-03-22 20:49 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot

On Tue, Mar 22, 2022 at 12:29:16AM +0800, Sui Jingfeng wrote:
> From: suijingfeng <suijingfeng@loongson.cn>
> 
> There is a display controller in loongson's LS2K1000 SoC and LS7A1000
> bridge chip, the display controller is a PCI device in those chips. It
> has two display pipes but with only one hardware cursor. Each way has
> a DVO interface which provide RGB888 signals, vertical & horizontal
> synchronisations, data enable and the pixel clock. Each CRTC is able to
> scanout from 1920x1080 resolution at 60Hz, the maxmium resolution is
> 2048x2048 according to the hardware spec. Loongson display controllers
> are simple which require scanout buffers to be physically contiguous.
> 
> For LS7A1000 bridge chip, the DC is equipped with a dedicated video RAM
> which is typically 64MB or more. In this case, VRAM helper based driver
> is intend to be used. While LS2K1000 is a SoC, only system memory is
> available. Therefore CMA helper based driver is intend to be used. It is
> possible to use VRAM helper based solution by carving out part of system
> memory as VRAM though.
> 
> For LS7A1000, there are 4 dedicated GPIOs whose control register is
> located at the DC register space, They are used to emulate two way i2c.
> One for DVO0, another for DVO1. LS2K1000 and LS2K0500 SoC don't have such
> GPIO hardwared, they grab i2c adapter from other module, either general
> purpose GPIO emulated i2c or hardware i2c adapter.
> 
>     +------+            +-----------------------------------+
>     | DDR4 |            |  +-------------------+            |
>     +------+            |  | PCIe Root complex |   LS7A1000 |
>        || MC0           |  +--++---------++----+            |
>   +----------+  HT 3.0  |     ||         ||                 |
>   | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>   |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>   +----------+          | +--------+  +-+--+-+    +---------+   +------+
>        || MC1           +---------------|--|----------------+
>     +------+                            |  |
>     | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>     +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>                       +-------+                      +------+
> 
> The above picture give a simple usage of LS7A1000, note that the encoder
> is not necessary adv7125 or tfp410, other candicates can be ch7034b,
> sil9022, ite66121 and lt8618 etc.
> 
> v2: Fixup warnings reported by kernel test robot
> 
> v3: Fix more grammar mistakes in Kconfig reported by Randy Dunlap and give
>     more details about lsdc.
> 
> v4:
>    1) Add dts required and explain why device tree is required.
>    2) Give more description about lsdc and VRAM helper based driver.
>    3) Fix warnings reported by kernel test robot.
>    4) Introduce stride_alignment member into struct lsdc_chip_desc, the
>       stride alignment is 256 bytes for ls7a1000, ls2k1000 and ls2k0500.
> 
> v5:
>    1) Using writel and readl replace writeq and readq, to fix kernel test
>       robot report build error on other archtecture.
>    2) Set default fb format to XRGB8888 at crtc reset time.
> 
> v6:
>    1) Explain why we are not switch to drm dridge subsystem on ls2k1000.
>    2) Explain why tiny drm driver is not suitable for us.
>    3) Give a short description of the trival dirty uppdate implement based
>       on CMA helper.
> 
> v7:
>    1) Remove select I2C_GPIO and I2C_LS2X in Kconfig, it is not ready now
>    2) Licensing issues are fixed suggested by Krzysztof Kozlowski.
>    3) Remove lsdc_pixpll_print(), part of it move to debugfs.
>    4) Set prefer_shadow to true if vram based driver is in using.
>    5) Replace double blank lines with single line in all files.
>    6) Verbose cmd line parameter is replaced with drm_dbg()
>    7) All warnnings reported by ./scripts/checkpatch.pl --strict are fixed
>    8) Get edid from dtb support is removed as suggested by Maxime Ripard
>    9) Fix typos and various improvement
> 
> v8:
>    1) Drop damage update implement and its command line.
>    2) Drop DRM_LSDC_VRAM_DRIVER config option as suggested by Maxime.
>    3) Deduce DC's identification from its compatible property.
>    4) Drop the board specific dts patch.
>    5) Add documention about the display controller device node.
> 
> v9:
>    1) Fix the warnings reported by checkpatch script and fix typos
> 
> v10:
>    1) Pass `make dt_binding_check` validation
>    2) Fix warnings reported by kernel test robot
> 
> v11:
>    1) Convert the driver to use drm bridge and of graph framework.
>    2) Dump register value support through debugfs.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> ---
>  drivers/gpu/drm/Kconfig             |   2 +
>  drivers/gpu/drm/Makefile            |   1 +
>  drivers/gpu/drm/lsdc/Kconfig        |  23 ++
>  drivers/gpu/drm/lsdc/Makefile       |  13 +
>  drivers/gpu/drm/lsdc/lsdc_crtc.c    | 396 +++++++++++++++++++
>  drivers/gpu/drm/lsdc/lsdc_drv.c     | 547 ++++++++++++++++++++++++++
>  drivers/gpu/drm/lsdc/lsdc_drv.h     | 197 ++++++++++
>  drivers/gpu/drm/lsdc/lsdc_i2c.c     | 235 ++++++++++++
>  drivers/gpu/drm/lsdc/lsdc_i2c.h     |  42 ++
>  drivers/gpu/drm/lsdc/lsdc_irq.c     |  58 +++
>  drivers/gpu/drm/lsdc/lsdc_irq.h     |  18 +
>  drivers/gpu/drm/lsdc/lsdc_output.c  | 262 +++++++++++++
>  drivers/gpu/drm/lsdc/lsdc_output.h  |  24 ++
>  drivers/gpu/drm/lsdc/lsdc_pci_drv.c | 328 ++++++++++++++++
>  drivers/gpu/drm/lsdc/lsdc_plane.c   | 470 +++++++++++++++++++++++
>  drivers/gpu/drm/lsdc/lsdc_pll.c     | 574 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/lsdc/lsdc_pll.h     |  88 +++++
>  drivers/gpu/drm/lsdc/lsdc_regs.h    | 220 +++++++++++
>  18 files changed, 3498 insertions(+)
>  create mode 100644 drivers/gpu/drm/lsdc/Kconfig
>  create mode 100644 drivers/gpu/drm/lsdc/Makefile
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_crtc.c
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.c
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.h
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.c
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.h
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.c
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.h
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.c
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.h
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_pci_drv.c
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_plane.c
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.c
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.h
>  create mode 100644 drivers/gpu/drm/lsdc/lsdc_regs.h

[...]

> diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.c b/drivers/gpu/drm/lsdc/lsdc_i2c.c
> new file mode 100644
> index 000000000000..55beed9266fa
> --- /dev/null
> +++ b/drivers/gpu/drm/lsdc/lsdc_i2c.c
> @@ -0,0 +1,235 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * KMS driver for Loongson display controller

Not really a useful comment since every file has the same one.

> + * Copyright (C) 2022 Loongson Corporation
> + */
> +
> +/*
> + * Authors:
> + *      Sui Jingfeng <suijingfeng@loongson.cn>
> + */
> +
> +#include <linux/i2c.h>
> +#include <linux/pci.h>
> +
> +#include "lsdc_drv.h"
> +#include "lsdc_regs.h"
> +#include "lsdc_i2c.h"
> +
> +/*
> + * ls7a_gpio_i2c_set - set the state of a gpio pin indicated by mask
> + * @mask: gpio pin mask
> + */
> +static void ls7a_gpio_i2c_set(struct lsdc_i2c * const li2c, int mask, int state)
> +{
> +	unsigned long flags;
> +	u8 val;
> +
> +	spin_lock_irqsave(&li2c->reglock, flags);

What are you protecting? Doesn't the caller serialize calls to these 
functions?

> +
> +	if (state) {
> +		val = readb(li2c->dir_reg);
> +		val |= mask;
> +		writeb(val, li2c->dir_reg);
> +	} else {
> +		val = readb(li2c->dir_reg);
> +		val &= ~mask;
> +		writeb(val, li2c->dir_reg);
> +
> +		val = readb(li2c->dat_reg);
> +		if (state)

This condition is never true. We're in the 'else' because !state.

> +			val |= mask;
> +		else
> +			val &= ~mask;
> +		writeb(val, li2c->dat_reg);

Shouldn't you set the data register low first and then change the 
direction? Otherwise, you may be driving high for a moment. However, if 
high is always done by setting the direction as input, why write the 
data register each time? I'm assuming whatever is written to the dat_reg 
is maintained regardless of pin state.

> +	}
> +
> +	spin_unlock_irqrestore(&li2c->reglock, flags);
> +}
> +
> +/*
> + * ls7a_gpio_i2c_get - read value back from gpio pin
> + * @mask: gpio pin mask
> + */
> +static int ls7a_gpio_i2c_get(struct lsdc_i2c * const li2c, int mask)
> +{
> +	unsigned long flags;
> +	u8 val;
> +
> +	spin_lock_irqsave(&li2c->reglock, flags);
> +
> +	/* first set this pin as input */
> +	val = readb(li2c->dir_reg);
> +	val |= mask;
> +	writeb(val, li2c->dir_reg);
> +
> +	/* then get level state from this pin */
> +	val = readb(li2c->dat_reg);
> +
> +	spin_unlock_irqrestore(&li2c->reglock, flags);
> +
> +	return (val & mask) ? 1 : 0;
> +}
> +
> +/* set the state on the i2c->sda pin */
> +static void ls7a_i2c_set_sda(void *i2c, int state)
> +{
> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
> +
> +	return ls7a_gpio_i2c_set(li2c, li2c->sda, state);
> +}
> +
> +/* set the state on the i2c->scl pin */
> +static void ls7a_i2c_set_scl(void *i2c, int state)
> +{
> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
> +
> +	return ls7a_gpio_i2c_set(li2c, li2c->scl, state);
> +}
> +
> +/* read the value from the i2c->sda pin */
> +static int ls7a_i2c_get_sda(void *i2c)
> +{
> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
> +
> +	return ls7a_gpio_i2c_get(li2c, li2c->sda);
> +}
> +
> +/* read the value from the i2c->scl pin */
> +static int ls7a_i2c_get_scl(void *i2c)
> +{
> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
> +
> +	return ls7a_gpio_i2c_get(li2c, li2c->scl);
> +}
> +
> +/*
> + * mainly for dc in ls7a1000 which have builtin gpio emulated i2c
> + *
> + * @index : output channel index, 0 for DVO0, 1 for DVO1
> + */
> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev, void *base, unsigned int index)
> +{
> +	char compat[32] = {0};
> +	unsigned int udelay = 5;
> +	unsigned int timeout = 2200;
> +	int nr = -1;
> +	struct i2c_adapter *adapter;
> +	struct lsdc_i2c *li2c;
> +	struct device_node *i2c_np;
> +	int ret;
> +
> +	li2c = devm_kzalloc(dev, sizeof(*li2c), GFP_KERNEL);
> +	if (!li2c)
> +		return ERR_PTR(-ENOMEM);
> +
> +	li2c->index = index;
> +	li2c->dev = dev;
> +
> +	if (index == 0) {
> +		li2c->sda = 0x01;
> +		li2c->scl = 0x02;
> +	} else if (index == 1) {
> +		li2c->sda = 0x04;
> +		li2c->scl = 0x08;

Just require this to be in DT rather than having some default.

> +	}
> +
> +	spin_lock_init(&li2c->reglock);
> +
> +	snprintf(compat, sizeof(compat), "lsdc,i2c-gpio-%d", index);

compatible values shouldn't have an index and you shouldn't need a 
index in DT. You need to iterate over child nodes with matching 
compatible.

> +	i2c_np = of_find_compatible_node(dev->of_node, NULL, compat);
> +	if (i2c_np) {
> +		u32 sda, scl;
> +
> +		dev_dbg(dev, "Has %s property in the DT", compat);
> +
> +		/*  */
> +		ret = of_property_read_u32(i2c_np, "sda", &sda);

Custom properties need a vendor prefix.

> +		if (ret == 0)
> +			li2c->sda = 1 << sda;
> +
> +		ret = of_property_read_u32(i2c_np, "scl", &scl);
> +		if (ret == 0)
> +			li2c->scl = 1 << scl;
> +
> +		/* Optional properties which made the driver more flexible */
> +		of_property_read_u32(i2c_np, "udelay", &udelay);
> +		of_property_read_u32(i2c_np, "timeout", &timeout);

These aren't documented. Do you really need them in DT?

> +		of_property_read_u32(i2c_np, "reg", &nr);
> +	}
> +
> +	dev_dbg(dev, "%s: sda=%u, scl=%u, nr=%d, udelay=%u, timeout=%u\n",
> +		compat, li2c->sda, li2c->scl, nr, udelay, timeout);
> +
> +	li2c->reg_base = base;
> +
> +	li2c->dir_reg = li2c->reg_base + LS7A_DC_GPIO_DIR_REG;
> +	li2c->dat_reg = li2c->reg_base + LS7A_DC_GPIO_DAT_REG;
> +
> +	li2c->bit.setsda = ls7a_i2c_set_sda;
> +	li2c->bit.setscl = ls7a_i2c_set_scl;
> +	li2c->bit.getsda = ls7a_i2c_get_sda;
> +	li2c->bit.getscl = ls7a_i2c_get_scl;
> +	li2c->bit.udelay = udelay;
> +	li2c->bit.timeout = usecs_to_jiffies(timeout);
> +	li2c->bit.data = li2c;
> +
> +	adapter = &li2c->adapter;
> +	adapter->algo_data = &li2c->bit;
> +	adapter->owner = THIS_MODULE;
> +	adapter->class = I2C_CLASS_DDC;
> +	adapter->dev.parent = dev;
> +	adapter->nr = nr;
> +	if (i2c_np) {
> +		adapter->dev.of_node = i2c_np;
> +		of_node_put(i2c_np);
> +	}
> +
> +	strscpy(adapter->name, &compat[5], sizeof(adapter->name));
> +
> +	i2c_set_adapdata(adapter, li2c);
> +
> +	ret = i2c_bit_add_numbered_bus(adapter);

Why do you care what the bus number is? You shouldn't need to.

> +	if (ret) {
> +		if (i2c_np)
> +			of_node_put(i2c_np);
> +
> +		devm_kfree(dev, li2c);
> +		return ERR_PTR(ret);
> +	}
> +
> +	return li2c;
> +}
> +
> +void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c)
> +{
> +	struct i2c_adapter *adapter;
> +
> +	if (li2c) {
> +		adapter = &li2c->adapter;
> +
> +		if (adapter && adapter->dev.of_node)
> +			of_node_put(adapter->dev.of_node);
> +
> +		devm_kfree(ddev->dev, li2c);
> +	}
> +}
> +
> +struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
> +					 unsigned int index)
> +{
> +	const struct lsdc_chip_desc * const descp = ldev->desc;
> +	struct lsdc_i2c *li2c;
> +
> +	if (index >= descp->num_of_crtc) {
> +		drm_err(ldev->ddev, "I2c adapter is no more than %u, %u\n",
> +			descp->num_of_crtc, index);
> +		return NULL;
> +	}
> +
> +	li2c = ldev->li2c[index];
> +	if (li2c)
> +		return &li2c->adapter;
> +
> +	return NULL;
> +}
> diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.h b/drivers/gpu/drm/lsdc/lsdc_i2c.h
> new file mode 100644
> index 000000000000..4ab825143eb4
> --- /dev/null
> +++ b/drivers/gpu/drm/lsdc/lsdc_i2c.h
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * KMS driver for Loongson display controller
> + * Copyright (C) 2022 Loongson Corporation
> + */
> +
> +/*
> + * Authors:
> + *      Sui Jingfeng <suijingfeng@loongson.cn>
> + */
> +
> +#ifndef __LSDC_I2C__
> +#define __LSDC_I2C__
> +
> +#include <linux/i2c.h>
> +#include <linux/i2c-algo-bit.h>
> +#include <linux/pci.h>
> +
> +struct lsdc_i2c {
> +	struct device *dev;
> +	struct i2c_adapter adapter;
> +	struct i2c_algo_bit_data bit;
> +	/* @reglock: protects concurrent register access */
> +	spinlock_t reglock;
> +	void __iomem *reg_base;
> +	void __iomem *dir_reg;
> +	void __iomem *dat_reg;
> +	int index;
> +	/* pin bit mask */
> +	u8 sda;
> +	u8 scl;
> +};
> +
> +void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c);
> +
> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev,
> +				      void *base,
> +				      unsigned int index);
> +
> +struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
> +					 unsigned int index);
> +#endif

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-22  2:33     ` Sui Jingfeng
  2022-03-22 13:08       ` Jiaxun Yang
@ 2022-03-22 20:55       ` Rob Herring
  2022-03-23  3:38         ` Sui Jingfeng
  1 sibling, 1 reply; 48+ messages in thread
From: Rob Herring @ 2022-03-22 20:55 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel

On Tue, Mar 22, 2022 at 10:33:45AM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/22 07:20, Rob Herring wrote:
> > On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
> > > From: suijingfeng <suijingfeng@loongson.cn>
> > > 
> > Needs a commit message.
> > 
> > > Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> > > Signed-off-by: Sui Jingfeng <15330273260@189.cn>
> > Same person? Don't need both emails.
> 
> Yes,  suijingfeng@loongson.cn is my company's email. But it can not be used
> to send patches to dri-devel,
> 
> when send patches with this email, the patch will not be shown on patch
> works.
> 
> Emails  are either blocked or got  rejected  by loongson's mail server.  It
> can only receive emails
> 
> from you and other people, but not dri-devel. so have to use my personal
> email(15330273260@189.cn) to send patches.
> 
> > > ---
> > >   .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
> > >   1 file changed, 230 insertions(+)
> > >   create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > 
> > > diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > new file mode 100644
> > > index 000000000000..7be63346289e
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > @@ -0,0 +1,230 @@
> > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > +%YAML 1.2
> > > +---
> > > +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
> > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > +
> > > +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
> > > +
> > > +maintainers:
> > > +  - Sui Jingfeng <suijingfeng@loongson.cn>
> > > +
> > > +description: |+
> > > +
> > > +  Loongson display controllers are simple which require scanout buffers
> > > +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
> > > +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
> > > +  with a dedicated video RAM which is 64MB or more, precise size can be
> > > +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
> > > +  chip.
> > > +
> > > +  LSDC has two display pipes, each way has a DVO interface which provide
> > > +  RGB888 signals, vertical & horizontal synchronisations, data enable and
> > > +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
> > > +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
> > > +
> > > +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
> > > +  located at the DC register space. They are used to emulate two way i2c,
> > > +  One for DVO0, another for DVO1.
> > > +
> > > +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
> > > +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
> > > +
> > > +  LSDC's display pipeline have several components as below description,
> > > +
> > > +  The display controller in LS7A1000:
> > > +     ___________________                                     _________
> > > +    |            -------|                                   |         |
> > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > +    |  _   _     -------|        ^             ^            |_________|
> > > +    | | | | |    -------|        |             |
> > > +    | |_| |_|    | i2c0 <--------+-------------+
> > > +    |            -------|
> > > +    |   DC IN LS7A1000  |
> > > +    |  _   _     -------|
> > > +    | | | | |    | i2c1 <--------+-------------+
> > > +    | |_| |_|    -------|        |             |             _________
> > > +    |            -------|        |             |            |         |
> > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > +    |            -------|                                   |_________|
> > > +    |___________________|
> > > +
> > > +  Simple usage of LS7A1000 with LS3A4000 CPU:
> > > +
> > > +    +------+            +-----------------------------------+
> > > +    | DDR4 |            |  +-------------------+            |
> > > +    +------+            |  | PCIe Root complex |   LS7A1000 |
> > > +       || MC0           |  +--++---------++----+            |
> > > +  +----------+  HT 3.0  |     ||         ||                 |
> > > +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
> > > +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
> > > +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
> > > +       || MC1           +---------------|--|----------------+
> > > +    +------+                            |  |
> > > +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
> > > +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
> > > +                      +-------+                      +------+
> > > +
> > > +  The display controller in LS2K1000/LS2K0500:
> > > +     ___________________                                     _________
> > > +    |            -------|                                   |         |
> > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > +    |  _   _     -------|        ^              ^           |_________|
> > > +    | | | | |           |        |              |
> > > +    | |_| |_|           |     +------+          |
> > > +    |                   <---->| i2c0 |<---------+
> > > +    |   DC IN LS2K1000  |     +------+
> > > +    |  _   _            |     +------+
> > > +    | | | | |           <---->| i2c1 |----------+
> > > +    | |_| |_|           |     +------+          |            _________
> > > +    |            -------|        |              |           |         |
> > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > +    |            -------|                                   |_________|
> > > +    |___________________|
> > > +
> > > +properties:
> > > +  $nodename:
> > > +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
> > > +
> > > +  compatible:
> > > +    oneOf:
> > > +      - items:
> > > +          - enum:
> > > +              - loongson,ls7a1000-dc
> > > +              - loongson,ls2k1000-dc
> > > +              - loongson,ls2k0500-dc
> > > +
> > > +  reg:
> > > +    maxItems: 1
> > > +
> > > +  interrupts:
> > > +    maxItems: 1
> > > +
> > > +  '#address-cells':
> > > +    const: 1
> > > +
> > > +  '#size-cells':
> > > +    const: 0
> > > +
> > > +  i2c-gpio@0:
> > > +    description: |
> > > +      Built-in GPIO emulate i2c exported for external display bridge
> > If you have i2c-gpio, that belongs at the DT top-level, not here.
> > 
> > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
> > No, there's a defined i2c-gpio compatible already.
> 
> This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
> By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
> adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
> LSDC register space, not general purpose GPIOs with separate control register resource.
> So i think it is the child node of display-controller@6,1, it belongs to LSDC.
> It seems that put it at the DT top-level break the hierarchy and relationship.

Okay, I see. Then just 'i2c' for the node names. You need a reference to 
i2c-controller.yaml for these nodes too.

The compatible should not have an index in it.


> 
> > > +      used to specify a I2c adapter bus number, if you don't specify one
> > > +      i2c driver core will dynamically assign a bus number. Please specify
> > Bus numbers are a linux detail not relevant to DT binding.
> > 
> > > +      it only when its bus number matters. Bus number greater than 6 is safe
> > > +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
> > > +
> > > +  i2c-gpio@1:
> > > +    description: |
> > > +      Built-in GPIO emulate i2c exported for external display bridge
> > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > +      only. Its compatible must be lsdc,i2c-gpio-1.
> > > +
> > > +  ports:
> > > +    $ref: /schemas/graph.yaml#/properties/ports
> > > +
> > > +    properties:
> > > +      port@0:
> > > +        $ref: /schemas/graph.yaml#/properties/port
> > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > +
> > > +      port@1:
> > > +        $ref: /schemas/graph.yaml#/properties/port
> > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > +
> > > +    required:
> > > +      - port@0
> > > +      - port@1
> > > +
> > > +required:
> > > +  - compatible
> > > +  - reg
> > > +  - interrupts
> > > +  - ports
> > > +
> > > +additionalProperties: false
> > > +
> > > +examples:
> > > +  - |
> > > +    #include <dt-bindings/interrupt-controller/irq.h>
> > > +    bus {
> > > +
> > > +        #address-cells = <3>;
> > > +        #size-cells = <2>;
> > > +        #interrupt-cells = <2>;
> > > +
> > > +        display-controller@6,1 {
> > > +            compatible = "loongson,ls7a1000-dc";
> > > +            reg = <0x3100 0x0 0x0 0x0 0x0>;
> > > +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
> > > +
> > > +            #address-cells = <1>;
> > > +            #size-cells = <0>;
> > > +
> > > +            i2c-gpio@0 {
> > > +                compatible = "lsdc,i2c-gpio-0";
> > > +                reg = <6>;

'reg' needs to be documented with some description of what 6 and 7 
represent. If they are the control register offset, then make the 
address translatable (use 'ranges' and define the size).

> > > +                sda = <0>;
> > > +                scl = <1>;

These need a vendor prefix.

> > > +            };
> > > +
> > > +            i2c-gpio@1 {
> > > +                compatible = "lsdc,i2c-gpio-1";
> > > +                reg = <7>;
> > > +                sda = <2>;
> > > +                scl = <3>;
> > > +            };
> > > +
> > > +            ports {
> > > +                #address-cells = <1>;
> > > +                #size-cells = <0>;
> > > +                port@0 {
> > > +                    reg = <0>;
> > > +                    endpoint {
> > > +                            remote-endpoint = <&vga_encoder_in>;
> > > +                    };
> > > +                };
> > > +                port@1 {
> > > +                    reg = <1>;
> > > +                    endpoint {
> > > +                            remote-endpoint = <&dvi_encoder_in>;
> > > +                    };
> > > +                };
> > > +            };
> > > +        };
> > > +    };
> > > +
> > > +  - |
> > > +    #include <dt-bindings/interrupt-controller/irq.h>
> > > +    bus {
> > > +
> > > +        #address-cells = <3>;
> > > +        #size-cells = <2>;
> > > +        #interrupt-cells = <2>;
> > > +
> > > +        display-controller@6,0 {
> > > +            compatible = "loongson,ls2k1000-dc";
> > > +            reg = <0x3100 0x0 0x0 0x0 0x0>;
> > > +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
> > > +
> > > +            ports {
> > > +                #address-cells = <1>;
> > > +                #size-cells = <0>;
> > > +                port@0 {
> > > +                    reg = <0>;
> > > +                    endpoint {
> > > +                            remote-endpoint = <&panel_in>;
> > > +                    };
> > > +                };
> > > +                port@1 {
> > > +                    reg = <1>;
> > > +                    endpoint {
> > > +                            remote-endpoint = <&hdmi_encoder_in>;
> > > +                    };
> > > +                };
> > > +            };
> > > +        };
> > > +    };
> > > +...
> > > -- 
> > > 2.25.1
> > > 
> > > 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-22 16:06       ` Jiaxun Yang
@ 2022-03-23  1:53         ` Sui Jingfeng
  2022-03-23  2:29           ` Jiaxun Yang
  2022-03-23 12:53           ` Rob Herring
  0 siblings, 2 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-23  1:53 UTC (permalink / raw)
  To: Jiaxun Yang, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Rob Herring, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel


On 2022/3/23 00:06, Jiaxun Yang wrote:
>
>
> 在 2022/3/22 13:38, Sui Jingfeng 写道:
>>
>> On 2022/3/22 21:05, Jiaxun Yang wrote:
>>>
>>>
>>> 在 2022/3/21 16:29, Sui Jingfeng 写道:
>>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>>
>>>> The board name is LS3A4000_7A1000_EVB_BOARD_V1.4, it consist of 1.8Ghz
>>>> mips64r5 4-core CPU and LS7A1000 bridge chip. It has PCIe GEN2 x8 
>>>> slot,
>>>> therefore can play with discrete graphics card.
>>>
>>> Hi Jingfeng,
>>>
>>> As we've discussed before if you are going to introduce new dts then 
>>> you *MUST*
>>> include it in makefile and wire it up in code.
>>>
>>> A dts file doing nothing lying in the tree is just suspicious.
>>>
>>> Thanks.
>>> - Jiaxun
>>>
>> Hi, Jiaxun,
>>
>> I know what you means, but it is the kernel side developer's job.
>> I am just a naive graphic driver developer,I can not care so much.
>> Below is my private patch which can be used to built specific dts
>> into the linux kernel, therefore make the verification easier.
> Hi Jingfeng,
>
> In kernel world we take care all the stuff we touched ourself :-)
>
> If you are not confident with them please drop those DTS from the 
> patchset
> besides the generic one. I can do the rest for you after getting this 
> set merged.
>
> Thanks.
> - Jiaxun
>
Hi, Jiaxun

Build all dts into vmlinuz will make the vmlinuz bigger and bigger.
How does the kernel get the dtb is another big issue, either from built-in
dtb or pass from the firmware(pmon and uefi etc). This should be
solved with another patch carefully. Providing board specific dts
helps to code review, it helps reviewers understand that there are
variant boards and have to be express with different OF graph.

Now, there are about 6 dts under arch/mips/boot/dts/loongson/,
Suppose loongson have 1000+ different board, do you want built all
of them into vmlinuz?

Besides, ls7a1000 and ls2k1000 lack a i2c driver, gpio driver,
pwm driver, clk driver, can you pay more attention to salve those
problems, please ?


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-23  1:53         ` Sui Jingfeng
@ 2022-03-23  2:29           ` Jiaxun Yang
  2022-03-23  3:07             ` Sui Jingfeng
  2022-03-23  7:07             ` Sui Jingfeng
  2022-03-23 12:53           ` Rob Herring
  1 sibling, 2 replies; 48+ messages in thread
From: Jiaxun Yang @ 2022-03-23  2:29 UTC (permalink / raw)
  To: Sui Jingfeng, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Rob Herring, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel, chenhuacai,
	Tiezhu Yang, liyi



在 2022/3/23 1:53, Sui Jingfeng 写道:
> Hi, Jiaxun
>
> Build all dts into vmlinuz will make the vmlinuz bigger and bigger.
> How does the kernel get the dtb is another big issue, either from 
> built-in
> dtb or pass from the firmware(pmon and uefi etc). This should be
> solved with another patch carefully. Providing board specific dts
> helps to code review, it helps reviewers understand that there are
> variant boards and have to be express with different OF graph.
Hi,

I insist my taste on those code. If the only intention is to demonstrate
the usage of the driver then please just leave them in dt document
or commit message.

>
> Now, there are about 6 dts under arch/mips/boot/dts/loongson/,
> Suppose loongson have 1000+ different board, do you want built all
> of them into vmlinuz?
Note that we are supporting all those boards on "platform" bias. Which
means if they share similar design then they will use the same DTS.
If we have a new design then unfortunately our kernel binary must grow.

For those who intended to build a size-optimized kernel they will be
able to disable unused DTS in Kconfig.

If you want to blame somebody for the problem then please don't
blame us. We tried very hard to fit all those stuff into kernel's model
of devices. You should blame those who did the initial design of
Loongson's boot interface that failed to introduce a proper way
to describe the platform.

>
> Besides, ls7a1000 and ls2k1000 lack a i2c driver, gpio driver,
> pwm driver, clk driver, can you pay more attention to salve those
> problems, please ?
Are you trying to make a TODO list for your colleague :-)

We , community developers, don't owe you anything. So please
don't expect anything from us. I lost access to most Loongson
devices since I'm currently study abroad, but I'm determined to
keep platform code in a good shape. That's my duty as a maintainer.

Thanks.
- Jiaxun

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-23  2:29           ` Jiaxun Yang
@ 2022-03-23  3:07             ` Sui Jingfeng
  2022-03-23  3:14               ` Jiaxun Yang
  2022-03-23  7:07             ` Sui Jingfeng
  1 sibling, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-23  3:07 UTC (permalink / raw)
  To: Jiaxun Yang, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Rob Herring, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel, chenhuacai,
	Tiezhu Yang, liyi


On 2022/3/23 10:29, Jiaxun Yang wrote:
>
>
> 在 2022/3/23 1:53, Sui Jingfeng 写道:
>> Hi, Jiaxun
>>
>> Build all dts into vmlinuz will make the vmlinuz bigger and bigger.
>> How does the kernel get the dtb is another big issue, either from 
>> built-in
>> dtb or pass from the firmware(pmon and uefi etc). This should be
>> solved with another patch carefully. Providing board specific dts
>> helps to code review, it helps reviewers understand that there are
>> variant boards and have to be express with different OF graph.
> Hi,
>
> I insist my taste on those code. If the only intention is to demonstrate
> the usage of the driver then please just leave them in dt document
> or commit message.
>
>>
>> Now, there are about 6 dts under arch/mips/boot/dts/loongson/,
>> Suppose loongson have 1000+ different board, do you want built all
>> of them into vmlinuz?
> Note that we are supporting all those boards on "platform" bias. Which
> means if they share similar design then they will use the same DTS.
> If we have a new design then unfortunately our kernel binary must grow.
>
> For those who intended to build a size-optimized kernel they will be
> able to disable unused DTS in Kconfig.
>
> If you want to blame somebody for the problem then please don't
> blame us. We tried very hard to fit all those stuff into kernel's model
> of devices. You should blame those who did the initial design of
> Loongson's boot interface that failed to introduce a proper way
> to describe the platform.
>
>>
>> Besides, ls7a1000 and ls2k1000 lack a i2c driver, gpio driver,
>> pwm driver, clk driver, can you pay more attention to salve those
>> problems, please ?
> Are you trying to make a TODO list for your colleague :-)
>
> We , community developers, don't owe you anything. So please
> don't expect anything from us. I lost access to most Loongson
> devices since I'm currently study abroad, but I'm determined to
> keep platform code in a good shape. That's my duty as a maintainer.
>
> Thanks.
> - Jiaxun

Providing a few board specific dts doesn't hurt anybody.

Can we leave the problem(passing correct dts to the kernel) untouched and

solve it in the feature with a another patch, ok?


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-23  3:07             ` Sui Jingfeng
@ 2022-03-23  3:14               ` Jiaxun Yang
  0 siblings, 0 replies; 48+ messages in thread
From: Jiaxun Yang @ 2022-03-23  3:14 UTC (permalink / raw)
  To: Sui Jingfeng, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Rob Herring, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel, Huacai Chen,
	Tiezhu Yang, liyi



在2022年3月23日三月 上午3:07,Sui Jingfeng写道:
> On 2022/3/23 10:29, Jiaxun Yang wrote:
>>
>>
>> 在 2022/3/23 1:53, Sui Jingfeng 写道:
>>> Hi, Jiaxun
>>>
>>> Build all dts into vmlinuz will make the vmlinuz bigger and bigger.
>>> How does the kernel get the dtb is another big issue, either from 
>>> built-in
>>> dtb or pass from the firmware(pmon and uefi etc). This should be
>>> solved with another patch carefully. Providing board specific dts
>>> helps to code review, it helps reviewers understand that there are
>>> variant boards and have to be express with different OF graph.
>> Hi,
>>
>> I insist my taste on those code. If the only intention is to demonstrate
>> the usage of the driver then please just leave them in dt document
>> or commit message.
>>
>>>
>>> Now, there are about 6 dts under arch/mips/boot/dts/loongson/,
>>> Suppose loongson have 1000+ different board, do you want built all
>>> of them into vmlinuz?
>> Note that we are supporting all those boards on "platform" bias. Which
>> means if they share similar design then they will use the same DTS.
>> If we have a new design then unfortunately our kernel binary must grow.
>>
>> For those who intended to build a size-optimized kernel they will be
>> able to disable unused DTS in Kconfig.
>>
>> If you want to blame somebody for the problem then please don't
>> blame us. We tried very hard to fit all those stuff into kernel's model
>> of devices. You should blame those who did the initial design of
>> Loongson's boot interface that failed to introduce a proper way
>> to describe the platform.
>>
>>>
>>> Besides, ls7a1000 and ls2k1000 lack a i2c driver, gpio driver,
>>> pwm driver, clk driver, can you pay more attention to salve those
>>> problems, please ?
>> Are you trying to make a TODO list for your colleague :-)
>>
>> We , community developers, don't owe you anything. So please
>> don't expect anything from us. I lost access to most Loongson
>> devices since I'm currently study abroad, but I'm determined to
>> keep platform code in a good shape. That's my duty as a maintainer.
>>
>> Thanks.
>> - Jiaxun
>
> Providing a few board specific dts doesn't hurt anybody.

There are a lot of things that don't hurt anybody but we shouldn't do.

The standard of reviewing the code is not "doesn't hurt anybody". It's "do the right thing".

Please reference:
https://www.kernel.org/doc/html/latest/process/6.Followthrough.html

>
> Can we leave the problem(passing correct dts to the kernel) untouched and
>
> solve it in the feature with a another patch, ok?

Then please drop platform DTS part.

I must NAK this part, sorry.

Thanks
-- 
- Jiaxun

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-22 20:55       ` Rob Herring
@ 2022-03-23  3:38         ` Sui Jingfeng
  2022-03-23 13:03           ` Rob Herring
  0 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-23  3:38 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel


On 2022/3/23 04:55, Rob Herring wrote:
> On Tue, Mar 22, 2022 at 10:33:45AM +0800, Sui Jingfeng wrote:
>> On 2022/3/22 07:20, Rob Herring wrote:
>>> On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
>>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>>
>>> Needs a commit message.
>>>
>>>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>>>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>>> Same person? Don't need both emails.
>> Yes,  suijingfeng@loongson.cn is my company's email. But it can not be used
>> to send patches to dri-devel,
>>
>> when send patches with this email, the patch will not be shown on patch
>> works.
>>
>> Emails  are either blocked or got  rejected  by loongson's mail server.  It
>> can only receive emails
>>
>> from you and other people, but not dri-devel. so have to use my personal
>> email(15330273260@189.cn) to send patches.
>>
>>>> ---
>>>>    .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
>>>>    1 file changed, 230 insertions(+)
>>>>    create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>> new file mode 100644
>>>> index 000000000000..7be63346289e
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>> @@ -0,0 +1,230 @@
>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>>> +%YAML 1.2
>>>> +---
>>>> +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>> +
>>>> +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
>>>> +
>>>> +maintainers:
>>>> +  - Sui Jingfeng <suijingfeng@loongson.cn>
>>>> +
>>>> +description: |+
>>>> +
>>>> +  Loongson display controllers are simple which require scanout buffers
>>>> +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
>>>> +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
>>>> +  with a dedicated video RAM which is 64MB or more, precise size can be
>>>> +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
>>>> +  chip.
>>>> +
>>>> +  LSDC has two display pipes, each way has a DVO interface which provide
>>>> +  RGB888 signals, vertical & horizontal synchronisations, data enable and
>>>> +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
>>>> +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
>>>> +
>>>> +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
>>>> +  located at the DC register space. They are used to emulate two way i2c,
>>>> +  One for DVO0, another for DVO1.
>>>> +
>>>> +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
>>>> +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
>>>> +
>>>> +  LSDC's display pipeline have several components as below description,
>>>> +
>>>> +  The display controller in LS7A1000:
>>>> +     ___________________                                     _________
>>>> +    |            -------|                                   |         |
>>>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>>>> +    |  _   _     -------|        ^             ^            |_________|
>>>> +    | | | | |    -------|        |             |
>>>> +    | |_| |_|    | i2c0 <--------+-------------+
>>>> +    |            -------|
>>>> +    |   DC IN LS7A1000  |
>>>> +    |  _   _     -------|
>>>> +    | | | | |    | i2c1 <--------+-------------+
>>>> +    | |_| |_|    -------|        |             |             _________
>>>> +    |            -------|        |             |            |         |
>>>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>>>> +    |            -------|                                   |_________|
>>>> +    |___________________|
>>>> +
>>>> +  Simple usage of LS7A1000 with LS3A4000 CPU:
>>>> +
>>>> +    +------+            +-----------------------------------+
>>>> +    | DDR4 |            |  +-------------------+            |
>>>> +    +------+            |  | PCIe Root complex |   LS7A1000 |
>>>> +       || MC0           |  +--++---------++----+            |
>>>> +  +----------+  HT 3.0  |     ||         ||                 |
>>>> +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>>>> +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>>>> +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
>>>> +       || MC1           +---------------|--|----------------+
>>>> +    +------+                            |  |
>>>> +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>>>> +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>>>> +                      +-------+                      +------+
>>>> +
>>>> +  The display controller in LS2K1000/LS2K0500:
>>>> +     ___________________                                     _________
>>>> +    |            -------|                                   |         |
>>>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>>>> +    |  _   _     -------|        ^              ^           |_________|
>>>> +    | | | | |           |        |              |
>>>> +    | |_| |_|           |     +------+          |
>>>> +    |                   <---->| i2c0 |<---------+
>>>> +    |   DC IN LS2K1000  |     +------+
>>>> +    |  _   _            |     +------+
>>>> +    | | | | |           <---->| i2c1 |----------+
>>>> +    | |_| |_|           |     +------+          |            _________
>>>> +    |            -------|        |              |           |         |
>>>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>>>> +    |            -------|                                   |_________|
>>>> +    |___________________|
>>>> +
>>>> +properties:
>>>> +  $nodename:
>>>> +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
>>>> +
>>>> +  compatible:
>>>> +    oneOf:
>>>> +      - items:
>>>> +          - enum:
>>>> +              - loongson,ls7a1000-dc
>>>> +              - loongson,ls2k1000-dc
>>>> +              - loongson,ls2k0500-dc
>>>> +
>>>> +  reg:
>>>> +    maxItems: 1
>>>> +
>>>> +  interrupts:
>>>> +    maxItems: 1
>>>> +
>>>> +  '#address-cells':
>>>> +    const: 1
>>>> +
>>>> +  '#size-cells':
>>>> +    const: 0
>>>> +
>>>> +  i2c-gpio@0:
>>>> +    description: |
>>>> +      Built-in GPIO emulate i2c exported for external display bridge
>>> If you have i2c-gpio, that belongs at the DT top-level, not here.
>>>
>>>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>>>> +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
>>> No, there's a defined i2c-gpio compatible already.
>> This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
>> By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
>> adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
>> LSDC register space, not general purpose GPIOs with separate control register resource.
>> So i think it is the child node of display-controller@6,1, it belongs to LSDC.
>> It seems that put it at the DT top-level break the hierarchy and relationship.
> Okay, I see. Then just 'i2c' for the node names. You need a reference to
> i2c-controller.yaml for these nodes too.
>
> The compatible should not have an index in it.
OK, i will fix this at the next version. thanks.
>>>> +      used to specify a I2c adapter bus number, if you don't specify one
>>>> +      i2c driver core will dynamically assign a bus number. Please specify
>>> Bus numbers are a linux detail not relevant to DT binding.
>>>
>>>> +      it only when its bus number matters. Bus number greater than 6 is safe
>>>> +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
>>>> +
>>>> +  i2c-gpio@1:
>>>> +    description: |
>>>> +      Built-in GPIO emulate i2c exported for external display bridge
>>>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>>>> +      only. Its compatible must be lsdc,i2c-gpio-1.
>>>> +
>>>> +  ports:
>>>> +    $ref: /schemas/graph.yaml#/properties/ports
>>>> +
>>>> +    properties:
>>>> +      port@0:
>>>> +        $ref: /schemas/graph.yaml#/properties/port
>>>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>>>> +
>>>> +      port@1:
>>>> +        $ref: /schemas/graph.yaml#/properties/port
>>>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>>>> +
>>>> +    required:
>>>> +      - port@0
>>>> +      - port@1
>>>> +
>>>> +required:
>>>> +  - compatible
>>>> +  - reg
>>>> +  - interrupts
>>>> +  - ports
>>>> +
>>>> +additionalProperties: false
>>>> +
>>>> +examples:
>>>> +  - |
>>>> +    #include <dt-bindings/interrupt-controller/irq.h>
>>>> +    bus {
>>>> +
>>>> +        #address-cells = <3>;
>>>> +        #size-cells = <2>;
>>>> +        #interrupt-cells = <2>;
>>>> +
>>>> +        display-controller@6,1 {
>>>> +            compatible = "loongson,ls7a1000-dc";
>>>> +            reg = <0x3100 0x0 0x0 0x0 0x0>;
>>>> +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
>>>> +
>>>> +            #address-cells = <1>;
>>>> +            #size-cells = <0>;
>>>> +
>>>> +            i2c-gpio@0 {
>>>> +                compatible = "lsdc,i2c-gpio-0";
>>>> +                reg = <6>;
> 'reg' needs to be documented with some description of what 6 and 7
> represent. If they are the control register offset, then make the
> address translatable (use 'ranges' and define the size).

By design, the reg property is used to specify a I2c adapter bus number,
if we don't specify one, i2c driver core will dynamically assign a bus number.
then the nr of the i2c adapter will started from 0. I want is start from 6
to avoid potential conflict feature hardware I2C driver.

Because LS7A1000 bridge chip have 6 hardware I2C controller integrated,
but its driver is not up-streamed yet. By default these hardware I2C controller's
nr is started from 0.

Even through i2c driver core can dynamically generate a number, i still want it
to be fixed and keep consistent and explicit. That is, i2c6 is for display pipe 0,
i2c7 is for display pipe 1. This follow the convention and flexible enough.

>>>> +                sda = <0>;
>>>> +                scl = <1>;
> These need a vendor prefix.
OK, i will fix this at the next version, thanks
>>>> +            };
>>>> +
>>>> +            i2c-gpio@1 {
>>>> +                compatible = "lsdc,i2c-gpio-1";
>>>> +                reg = <7>;
>>>> +                sda = <2>;
>>>> +                scl = <3>;
>>>> +            };
>>>> +
>>>> +            ports {
>>>> +                #address-cells = <1>;
>>>> +                #size-cells = <0>;
>>>> +                port@0 {
>>>> +                    reg = <0>;
>>>> +                    endpoint {
>>>> +                            remote-endpoint = <&vga_encoder_in>;
>>>> +                    };
>>>> +                };
>>>> +                port@1 {
>>>> +                    reg = <1>;
>>>> +                    endpoint {
>>>> +                            remote-endpoint = <&dvi_encoder_in>;
>>>> +                    };
>>>> +                };
>>>> +            };
>>>> +        };
>>>> +    };
>>>> +
>>>> +  - |
>>>> +    #include <dt-bindings/interrupt-controller/irq.h>
>>>> +    bus {
>>>> +
>>>> +        #address-cells = <3>;
>>>> +        #size-cells = <2>;
>>>> +        #interrupt-cells = <2>;
>>>> +
>>>> +        display-controller@6,0 {
>>>> +            compatible = "loongson,ls2k1000-dc";
>>>> +            reg = <0x3100 0x0 0x0 0x0 0x0>;
>>>> +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
>>>> +
>>>> +            ports {
>>>> +                #address-cells = <1>;
>>>> +                #size-cells = <0>;
>>>> +                port@0 {
>>>> +                    reg = <0>;
>>>> +                    endpoint {
>>>> +                            remote-endpoint = <&panel_in>;
>>>> +                    };
>>>> +                };
>>>> +                port@1 {
>>>> +                    reg = <1>;
>>>> +                    endpoint {
>>>> +                            remote-endpoint = <&hdmi_encoder_in>;
>>>> +                    };
>>>> +                };
>>>> +            };
>>>> +        };
>>>> +    };
>>>> +...
>>>> -- 
>>>> 2.25.1
>>>>
>>>>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-22 20:49   ` Rob Herring
@ 2022-03-23  4:12     ` Sui Jingfeng
  2022-03-23 13:11       ` Rob Herring
  2022-03-23  4:19     ` Sui Jingfeng
                       ` (6 subsequent siblings)
  7 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-23  4:12 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot


On 2022/3/23 04:49, Rob Herring wrote:
>> +/*
>> + * mainly for dc in ls7a1000 which have builtin gpio emulated i2c
>> + *
>> + * @index : output channel index, 0 for DVO0, 1 for DVO1
>> + */
>> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev, void *base, unsigned int index)
>> +{
>> +	char compat[32] = {0};
>> +	unsigned int udelay = 5;
>> +	unsigned int timeout = 2200;
>> +	int nr = -1;
>> +	struct i2c_adapter *adapter;
>> +	struct lsdc_i2c *li2c;
>> +	struct device_node *i2c_np;
>> +	int ret;
>> +
>> +	li2c = devm_kzalloc(dev, sizeof(*li2c), GFP_KERNEL);
>> +	if (!li2c)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	li2c->index = index;
>> +	li2c->dev = dev;
>> +
>> +	if (index == 0) {
>> +		li2c->sda = 0x01;
>> +		li2c->scl = 0x02;
>> +	} else if (index == 1) {
>> +		li2c->sda = 0x04;
>> +		li2c->scl = 0x08;
> Just require this to be in DT rather than having some default.
>
By design,  I am try very hard to let the code NOT fully  DT dependent. DT is nice , easy to learn and use.
But kernel side developer plan to follow UEFI + ACPI Specification on LS3A5000 + LS7A1000 platform. See [1]
There will no DT support then, provide a convention support  make the driver more flexible. I want the
driver works with minimal requirement. The driver just works on simple boards by put the following dc device
node in arch/mips/dts/loongson/loongson64g_4core_ls7a.dts,

             lsdc: display-controller@6,1 {
                 compatible = "loongson,ls7a1000-dc";

                 reg = <0x3100 0x0 0x0 0x0 0x0>;
                 interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
                 interrupt-parent = <&pic>;
             };

[1] 
https://lwn.net/Articles/869541/#:~:text=LoongArch%20is%20a%20new%20RISC%20ISA%2C%20which%20is,revision%20of%20ACPI%20Specification%20%28current%20revision%20is%206.4%29.


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-22 20:49   ` Rob Herring
  2022-03-23  4:12     ` Sui Jingfeng
@ 2022-03-23  4:19     ` Sui Jingfeng
  2022-03-23  8:49     ` Sui Jingfeng
                       ` (5 subsequent siblings)
  7 siblings, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-23  4:19 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot


On 2022/3/23 04:49, Rob Herring wrote:
> This condition is never true. We're in the 'else' because !state.

Thanks for your sharp eyes,  after the gpio emulate i2c driver works, i do not pay much
attention to it and get hurry to do other things. I will fix this issue at next version
and reply other problem at a letter time.



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-23  2:29           ` Jiaxun Yang
  2022-03-23  3:07             ` Sui Jingfeng
@ 2022-03-23  7:07             ` Sui Jingfeng
  2022-03-23 12:29               ` Jiaxun Yang
  1 sibling, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-23  7:07 UTC (permalink / raw)
  To: Jiaxun Yang, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Rob Herring, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel, chenhuacai,
	Tiezhu Yang, liyi


On 2022/3/23 10:29, Jiaxun Yang wrote:
> If you want to blame somebody for the problem then please don't
> blame us. We tried very hard to fit all those stuff into kernel's model
> of devices. You should blame those who did the initial design of
> Loongson's boot interface that failed to introduce a proper way
> to describe the platform. 

I am not blame anybody, please do not misleading.
I am report problem and try to seek a better solution.

I have my intention and ideas, i just don't want to solve
all of the problems in one shot.

I could provide one more patch wire all board specific dts up.
But i don't know what's the opinions of other reviewers, does
this is plausible?


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-22 20:49   ` Rob Herring
  2022-03-23  4:12     ` Sui Jingfeng
  2022-03-23  4:19     ` Sui Jingfeng
@ 2022-03-23  8:49     ` Sui Jingfeng
  2022-03-23  9:31     ` Sui Jingfeng
                       ` (4 subsequent siblings)
  7 siblings, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-23  8:49 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot


On 2022/3/23 04:49, Rob Herring wrote:
>> +/*
>> + * ls7a_gpio_i2c_set - set the state of a gpio pin indicated by mask
>> + * @mask: gpio pin mask
>> + */
>> +static void ls7a_gpio_i2c_set(struct lsdc_i2c * const li2c, int mask, int state)
>> +{
>> +	unsigned long flags;
>> +	u8 val;
>> +
>> +	spin_lock_irqsave(&li2c->reglock, flags);
> What are you protecting? Doesn't the caller serialize calls to these
> functions?
>
This driver is ported from my work from my downstream work.

Maxime also ask this question before, but i did not answer.
He is right, protect single register access is not necessary.
uncached access have done the job itself.
so i remove it in V11 of my patch set.

There are two way GPIO emulated i2c, I want the code between
spin_lock_irqsave(&li2c->reglock, flags) and spin_unlock_irqrestore(&li2c->reglock, flags);
finished in a atomic way, without any disruption.

The two i2c should not have any influence each other.
I write it by gut feeling, and luckily it works very well in practice.


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-22 20:49   ` Rob Herring
                       ` (2 preceding siblings ...)
  2022-03-23  8:49     ` Sui Jingfeng
@ 2022-03-23  9:31     ` Sui Jingfeng
  2022-03-24  1:39     ` Sui Jingfeng
                       ` (3 subsequent siblings)
  7 siblings, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-23  9:31 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot


On 2022/3/23 04:49, Rob Herring wrote:
>> +
>> +	if (state) {
>> +		val = readb(li2c->dir_reg);
>> +		val |= mask;
>> +		writeb(val, li2c->dir_reg);
>> +	} else {
>> +		val = readb(li2c->dir_reg);
>> +		val &= ~mask;
>> +		writeb(val, li2c->dir_reg);
>> +
>> +		val = readb(li2c->dat_reg);
>> +		if (state)
> This condition is never true. We're in the 'else' because !state.
>
>> +			val |= mask;
>> +		else
>> +			val &= ~mask;
>> +		writeb(val, li2c->dat_reg);
> Shouldn't you set the data register low first and then change the
> direction? Otherwise, you may be driving high for a moment. However, if
> high is always done by setting the direction as input, why write the
> data register each time? I'm assuming whatever is written to the dat_reg
> is maintained regardless of pin state.

To be honest, i have rewrite GPIO emulated i2c several times.
Either give data first, then give the direction
or give the direction first, then the data
will be OK in practice.

In the theory, the GPIO data should be given before the GPIO direction,
I was told doing that way when learning Single-Chip Microcomputer (AT89S52).

But the high "MUST" be done by setting the direction as input.
It is "MUST" not "CAN" because writing code as the following
way works in practice.

         if (state) {
                 val = readb(li2c->dir_reg);
                 val |= mask;
                 writeb(val, li2c->dir_reg);
         } else {
                // ...
         }

If the adjust the above code by first set the detection as output,
then set the GPIO data register with high voltage level("1"). as
the following demonstrate code,

         if (state) {
		/* First set this pin as output */
		val = readb(li2c->dir_reg);
		val |= mask;
		writeb(val, li2c->dir_reg);

		/* Then, set the state to high */
		val = readb(li2c->dat_reg);
		val |= mask;
		writeb(val, li2c->dat_reg);
         } else {
                // ...
         }

Then i2c6 will NOT work as exacted, i2c7 will work, so strangely.
It may because the GPIO is open drained, not Push-pull output.
Output high is achieved by externalpull up resistance on the PCB.


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-23  7:07             ` Sui Jingfeng
@ 2022-03-23 12:29               ` Jiaxun Yang
  0 siblings, 0 replies; 48+ messages in thread
From: Jiaxun Yang @ 2022-03-23 12:29 UTC (permalink / raw)
  To: Sui Jingfeng, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Rob Herring, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng
  Cc: linux-mips, linux-kernel, devicetree, dri-devel, Huacai Chen,
	Tiezhu Yang, liyi



在2022年3月23日三月 上午7:07,Sui Jingfeng写道:
> On 2022/3/23 10:29, Jiaxun Yang wrote:
>> If you want to blame somebody for the problem then please don't
>> blame us. We tried very hard to fit all those stuff into kernel's model
>> of devices. You should blame those who did the initial design of
>> Loongson's boot interface that failed to introduce a proper way
>> to describe the platform. 
>
> I am not blame anybody, please do not misleading.
Your language seems to be aggressive from my point of view.

> I am report problem and try to seek a better solution.
>
> I have my intention and ideas, i just don't want to solve
> all of the problems in one shot.
If so please just drop this part from the patch. I've repeated several times.

>
> I could provide one more patch wire all board specific dts up.
> But i don't know what's the opinions of other reviewers, does
> this is plausible?
Please carefully read section 6.1 about how should you work with reviewers.
https://www.kernel.org/doc/html/latest/process/6.Followthrough.html

Thanks.
-- 
- Jiaxun

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-23  1:53         ` Sui Jingfeng
  2022-03-23  2:29           ` Jiaxun Yang
@ 2022-03-23 12:53           ` Rob Herring
  2022-03-24  1:51             ` Sui Jingfeng
  1 sibling, 1 reply; 48+ messages in thread
From: Rob Herring @ 2022-03-23 12:53 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Jiaxun Yang, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng, linux-mips, linux-kernel, devicetree,
	dri-devel

On Wed, Mar 23, 2022 at 09:53:14AM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/23 00:06, Jiaxun Yang wrote:
> > 
> > 
> > 在 2022/3/22 13:38, Sui Jingfeng 写道:
> > > 
> > > On 2022/3/22 21:05, Jiaxun Yang wrote:
> > > > 
> > > > 
> > > > 在 2022/3/21 16:29, Sui Jingfeng 写道:
> > > > > From: suijingfeng <suijingfeng@loongson.cn>
> > > > > 
> > > > > The board name is LS3A4000_7A1000_EVB_BOARD_V1.4, it consist of 1.8Ghz
> > > > > mips64r5 4-core CPU and LS7A1000 bridge chip. It has PCIe
> > > > > GEN2 x8 slot,
> > > > > therefore can play with discrete graphics card.
> > > > 
> > > > Hi Jingfeng,
> > > > 
> > > > As we've discussed before if you are going to introduce new dts
> > > > then you *MUST*
> > > > include it in makefile and wire it up in code.
> > > > 
> > > > A dts file doing nothing lying in the tree is just suspicious.
> > > > 
> > > > Thanks.
> > > > - Jiaxun
> > > > 
> > > Hi, Jiaxun,
> > > 
> > > I know what you means, but it is the kernel side developer's job.
> > > I am just a naive graphic driver developer,I can not care so much.
> > > Below is my private patch which can be used to built specific dts
> > > into the linux kernel, therefore make the verification easier.
> > Hi Jingfeng,
> > 
> > In kernel world we take care all the stuff we touched ourself :-)
> > 
> > If you are not confident with them please drop those DTS from the
> > patchset
> > besides the generic one. I can do the rest for you after getting this
> > set merged.
> > 
> > Thanks.
> > - Jiaxun
> > 
> Hi, Jiaxun
> 
> Build all dts into vmlinuz will make the vmlinuz bigger and bigger.
> How does the kernel get the dtb is another big issue, either from built-in
> dtb or pass from the firmware(pmon and uefi etc). This should be
> solved with another patch carefully. Providing board specific dts
> helps to code review, it helps reviewers understand that there are
> variant boards and have to be express with different OF graph.

Built-in DTBs are for legacy bootloaders that don't understand DT. I 
would not expect a new platform to need this.

> 
> Now, there are about 6 dts under arch/mips/boot/dts/loongson/,
> Suppose loongson have 1000+ different board, do you want built all
> of them into vmlinuz?

The point was to add the .dts to Makefile so it builds, not so it is 
built-in. How are you testing those build with dtc and dtschema if not 
added to kbuild?

Rob

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-23  3:38         ` Sui Jingfeng
@ 2022-03-23 13:03           ` Rob Herring
  2022-03-24  1:48             ` Sui Jingfeng
  0 siblings, 1 reply; 48+ messages in thread
From: Rob Herring @ 2022-03-23 13:03 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel

On Wed, Mar 23, 2022 at 11:38:55AM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/23 04:55, Rob Herring wrote:
> > On Tue, Mar 22, 2022 at 10:33:45AM +0800, Sui Jingfeng wrote:
> > > On 2022/3/22 07:20, Rob Herring wrote:
> > > > On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
> > > > > From: suijingfeng <suijingfeng@loongson.cn>
> > > > > 
> > > > Needs a commit message.
> > > > 
> > > > > Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> > > > > Signed-off-by: Sui Jingfeng <15330273260@189.cn>
> > > > Same person? Don't need both emails.
> > > Yes,  suijingfeng@loongson.cn is my company's email. But it can not be used
> > > to send patches to dri-devel,
> > > 
> > > when send patches with this email, the patch will not be shown on patch
> > > works.
> > > 
> > > Emails  are either blocked or got  rejected  by loongson's mail server.  It
> > > can only receive emails
> > > 
> > > from you and other people, but not dri-devel. so have to use my personal
> > > email(15330273260@189.cn) to send patches.
> > > 
> > > > > ---
> > > > >    .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
> > > > >    1 file changed, 230 insertions(+)
> > > > >    create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > 
> > > > > diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > new file mode 100644
> > > > > index 000000000000..7be63346289e
> > > > > --- /dev/null
> > > > > +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > @@ -0,0 +1,230 @@
> > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > > +%YAML 1.2
> > > > > +---
> > > > > +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
> > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > +
> > > > > +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
> > > > > +
> > > > > +maintainers:
> > > > > +  - Sui Jingfeng <suijingfeng@loongson.cn>
> > > > > +
> > > > > +description: |+
> > > > > +
> > > > > +  Loongson display controllers are simple which require scanout buffers
> > > > > +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
> > > > > +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
> > > > > +  with a dedicated video RAM which is 64MB or more, precise size can be
> > > > > +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
> > > > > +  chip.
> > > > > +
> > > > > +  LSDC has two display pipes, each way has a DVO interface which provide
> > > > > +  RGB888 signals, vertical & horizontal synchronisations, data enable and
> > > > > +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
> > > > > +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
> > > > > +
> > > > > +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
> > > > > +  located at the DC register space. They are used to emulate two way i2c,
> > > > > +  One for DVO0, another for DVO1.
> > > > > +
> > > > > +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
> > > > > +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
> > > > > +
> > > > > +  LSDC's display pipeline have several components as below description,
> > > > > +
> > > > > +  The display controller in LS7A1000:
> > > > > +     ___________________                                     _________
> > > > > +    |            -------|                                   |         |
> > > > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > > > +    |  _   _     -------|        ^             ^            |_________|
> > > > > +    | | | | |    -------|        |             |
> > > > > +    | |_| |_|    | i2c0 <--------+-------------+
> > > > > +    |            -------|
> > > > > +    |   DC IN LS7A1000  |
> > > > > +    |  _   _     -------|
> > > > > +    | | | | |    | i2c1 <--------+-------------+
> > > > > +    | |_| |_|    -------|        |             |             _________
> > > > > +    |            -------|        |             |            |         |
> > > > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > > > +    |            -------|                                   |_________|
> > > > > +    |___________________|
> > > > > +
> > > > > +  Simple usage of LS7A1000 with LS3A4000 CPU:
> > > > > +
> > > > > +    +------+            +-----------------------------------+
> > > > > +    | DDR4 |            |  +-------------------+            |
> > > > > +    +------+            |  | PCIe Root complex |   LS7A1000 |
> > > > > +       || MC0           |  +--++---------++----+            |
> > > > > +  +----------+  HT 3.0  |     ||         ||                 |
> > > > > +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
> > > > > +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
> > > > > +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
> > > > > +       || MC1           +---------------|--|----------------+
> > > > > +    +------+                            |  |
> > > > > +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
> > > > > +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
> > > > > +                      +-------+                      +------+
> > > > > +
> > > > > +  The display controller in LS2K1000/LS2K0500:
> > > > > +     ___________________                                     _________
> > > > > +    |            -------|                                   |         |
> > > > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > > > +    |  _   _     -------|        ^              ^           |_________|
> > > > > +    | | | | |           |        |              |
> > > > > +    | |_| |_|           |     +------+          |
> > > > > +    |                   <---->| i2c0 |<---------+
> > > > > +    |   DC IN LS2K1000  |     +------+
> > > > > +    |  _   _            |     +------+
> > > > > +    | | | | |           <---->| i2c1 |----------+
> > > > > +    | |_| |_|           |     +------+          |            _________
> > > > > +    |            -------|        |              |           |         |
> > > > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > > > +    |            -------|                                   |_________|
> > > > > +    |___________________|
> > > > > +
> > > > > +properties:
> > > > > +  $nodename:
> > > > > +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
> > > > > +
> > > > > +  compatible:
> > > > > +    oneOf:
> > > > > +      - items:
> > > > > +          - enum:
> > > > > +              - loongson,ls7a1000-dc
> > > > > +              - loongson,ls2k1000-dc
> > > > > +              - loongson,ls2k0500-dc
> > > > > +
> > > > > +  reg:
> > > > > +    maxItems: 1
> > > > > +
> > > > > +  interrupts:
> > > > > +    maxItems: 1
> > > > > +
> > > > > +  '#address-cells':
> > > > > +    const: 1
> > > > > +
> > > > > +  '#size-cells':
> > > > > +    const: 0
> > > > > +
> > > > > +  i2c-gpio@0:
> > > > > +    description: |
> > > > > +      Built-in GPIO emulate i2c exported for external display bridge
> > > > If you have i2c-gpio, that belongs at the DT top-level, not here.
> > > > 
> > > > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > > > +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
> > > > No, there's a defined i2c-gpio compatible already.
> > > This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
> > > By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
> > > adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
> > > LSDC register space, not general purpose GPIOs with separate control register resource.
> > > So i think it is the child node of display-controller@6,1, it belongs to LSDC.
> > > It seems that put it at the DT top-level break the hierarchy and relationship.
> > Okay, I see. Then just 'i2c' for the node names. You need a reference to
> > i2c-controller.yaml for these nodes too.
> > 
> > The compatible should not have an index in it.
> OK, i will fix this at the next version. thanks.
> > > > > +      used to specify a I2c adapter bus number, if you don't specify one
> > > > > +      i2c driver core will dynamically assign a bus number. Please specify
> > > > Bus numbers are a linux detail not relevant to DT binding.
> > > > 
> > > > > +      it only when its bus number matters. Bus number greater than 6 is safe
> > > > > +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
> > > > > +
> > > > > +  i2c-gpio@1:
> > > > > +    description: |
> > > > > +      Built-in GPIO emulate i2c exported for external display bridge
> > > > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > > > +      only. Its compatible must be lsdc,i2c-gpio-1.
> > > > > +
> > > > > +  ports:
> > > > > +    $ref: /schemas/graph.yaml#/properties/ports
> > > > > +
> > > > > +    properties:
> > > > > +      port@0:
> > > > > +        $ref: /schemas/graph.yaml#/properties/port
> > > > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > > > +
> > > > > +      port@1:
> > > > > +        $ref: /schemas/graph.yaml#/properties/port
> > > > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > > > +
> > > > > +    required:
> > > > > +      - port@0
> > > > > +      - port@1
> > > > > +
> > > > > +required:
> > > > > +  - compatible
> > > > > +  - reg
> > > > > +  - interrupts
> > > > > +  - ports
> > > > > +
> > > > > +additionalProperties: false
> > > > > +
> > > > > +examples:
> > > > > +  - |
> > > > > +    #include <dt-bindings/interrupt-controller/irq.h>
> > > > > +    bus {
> > > > > +
> > > > > +        #address-cells = <3>;
> > > > > +        #size-cells = <2>;
> > > > > +        #interrupt-cells = <2>;
> > > > > +
> > > > > +        display-controller@6,1 {
> > > > > +            compatible = "loongson,ls7a1000-dc";
> > > > > +            reg = <0x3100 0x0 0x0 0x0 0x0>;
> > > > > +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
> > > > > +
> > > > > +            #address-cells = <1>;
> > > > > +            #size-cells = <0>;
> > > > > +
> > > > > +            i2c-gpio@0 {
> > > > > +                compatible = "lsdc,i2c-gpio-0";
> > > > > +                reg = <6>;
> > 'reg' needs to be documented with some description of what 6 and 7
> > represent. If they are the control register offset, then make the
> > address translatable (use 'ranges' and define the size).
> 
> By design, the reg property is used to specify a I2c adapter bus number,
> if we don't specify one, i2c driver core will dynamically assign a bus number.
> then the nr of the i2c adapter will started from 0. I want is start from 6
> to avoid potential conflict feature hardware I2C driver.
> 
> Because LS7A1000 bridge chip have 6 hardware I2C controller integrated,
> but its driver is not up-streamed yet. By default these hardware I2C controller's
> nr is started from 0.

Linux's numbering doesn't belong in DT. So no, you can't use 'reg' in 
that way.

> Even through i2c driver core can dynamically generate a number, i still want it
> to be fixed and keep consistent and explicit. That is, i2c6 is for display pipe 0,
> i2c7 is for display pipe 1. This follow the convention and flexible enough.

You may want that, but that is not how the kernel works. Specific 
numbers are not guaranteed. I'm sure you've seen this for disks, network 
interfaces, etc.

Rob

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-23  4:12     ` Sui Jingfeng
@ 2022-03-23 13:11       ` Rob Herring
  2022-03-24  4:05         ` Sui Jingfeng
  2022-04-08  2:09         ` Sui Jingfeng
  0 siblings, 2 replies; 48+ messages in thread
From: Rob Herring @ 2022-03-23 13:11 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot

On Wed, Mar 23, 2022 at 12:12:43PM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/23 04:49, Rob Herring wrote:
> > > +/*
> > > + * mainly for dc in ls7a1000 which have builtin gpio emulated i2c
> > > + *
> > > + * @index : output channel index, 0 for DVO0, 1 for DVO1
> > > + */
> > > +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev, void *base, unsigned int index)
> > > +{
> > > +	char compat[32] = {0};
> > > +	unsigned int udelay = 5;
> > > +	unsigned int timeout = 2200;
> > > +	int nr = -1;
> > > +	struct i2c_adapter *adapter;
> > > +	struct lsdc_i2c *li2c;
> > > +	struct device_node *i2c_np;
> > > +	int ret;
> > > +
> > > +	li2c = devm_kzalloc(dev, sizeof(*li2c), GFP_KERNEL);
> > > +	if (!li2c)
> > > +		return ERR_PTR(-ENOMEM);
> > > +
> > > +	li2c->index = index;
> > > +	li2c->dev = dev;
> > > +
> > > +	if (index == 0) {
> > > +		li2c->sda = 0x01;
> > > +		li2c->scl = 0x02;
> > > +	} else if (index == 1) {
> > > +		li2c->sda = 0x04;
> > > +		li2c->scl = 0x08;
> > Just require this to be in DT rather than having some default.
> > 
> By design,  I am try very hard to let the code NOT fully  DT dependent. DT is nice , easy to learn and use.
> But kernel side developer plan to follow UEFI + ACPI Specification on LS3A5000 + LS7A1000 platform. See [1]
> There will no DT support then, provide a convention support  make the driver more flexible. I want the
> driver works with minimal requirement. The driver just works on simple boards by put the following dc device
> node in arch/mips/dts/loongson/loongson64g_4core_ls7a.dts,

Pick DT or ACPI for the platform, not both. We don't need to have both 
in the kernel to support.

Rob

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-22 20:49   ` Rob Herring
                       ` (3 preceding siblings ...)
  2022-03-23  9:31     ` Sui Jingfeng
@ 2022-03-24  1:39     ` Sui Jingfeng
  2022-03-24 13:42       ` Rob Herring
  2022-03-24  7:32     ` Sui Jingfeng
                       ` (2 subsequent siblings)
  7 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-24  1:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot


On 2022/3/23 04:49, Rob Herring wrote:
> On Tue, Mar 22, 2022 at 12:29:16AM +0800, Sui Jingfeng wrote:
>> From: suijingfeng <suijingfeng@loongson.cn>
>>
>> There is a display controller in loongson's LS2K1000 SoC and LS7A1000
>> bridge chip, the display controller is a PCI device in those chips. It
>> has two display pipes but with only one hardware cursor. Each way has
>> a DVO interface which provide RGB888 signals, vertical & horizontal
>> synchronisations, data enable and the pixel clock. Each CRTC is able to
>> scanout from 1920x1080 resolution at 60Hz, the maxmium resolution is
>> 2048x2048 according to the hardware spec. Loongson display controllers
>> are simple which require scanout buffers to be physically contiguous.
>>
>> For LS7A1000 bridge chip, the DC is equipped with a dedicated video RAM
>> which is typically 64MB or more. In this case, VRAM helper based driver
>> is intend to be used. While LS2K1000 is a SoC, only system memory is
>> available. Therefore CMA helper based driver is intend to be used. It is
>> possible to use VRAM helper based solution by carving out part of system
>> memory as VRAM though.
>>
>> For LS7A1000, there are 4 dedicated GPIOs whose control register is
>> located at the DC register space, They are used to emulate two way i2c.
>> One for DVO0, another for DVO1. LS2K1000 and LS2K0500 SoC don't have such
>> GPIO hardwared, they grab i2c adapter from other module, either general
>> purpose GPIO emulated i2c or hardware i2c adapter.
>>
>>      +------+            +-----------------------------------+
>>      | DDR4 |            |  +-------------------+            |
>>      +------+            |  | PCIe Root complex |   LS7A1000 |
>>         || MC0           |  +--++---------++----+            |
>>    +----------+  HT 3.0  |     ||         ||                 |
>>    | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>>    |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>>    +----------+          | +--------+  +-+--+-+    +---------+   +------+
>>         || MC1           +---------------|--|----------------+
>>      +------+                            |  |
>>      | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>>      +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>>                        +-------+                      +------+
>>
>> The above picture give a simple usage of LS7A1000, note that the encoder
>> is not necessary adv7125 or tfp410, other candicates can be ch7034b,
>> sil9022, ite66121 and lt8618 etc.
>>
>> v2: Fixup warnings reported by kernel test robot
>>
>> v3: Fix more grammar mistakes in Kconfig reported by Randy Dunlap and give
>>      more details about lsdc.
>>
>> v4:
>>     1) Add dts required and explain why device tree is required.
>>     2) Give more description about lsdc and VRAM helper based driver.
>>     3) Fix warnings reported by kernel test robot.
>>     4) Introduce stride_alignment member into struct lsdc_chip_desc, the
>>        stride alignment is 256 bytes for ls7a1000, ls2k1000 and ls2k0500.
>>
>> v5:
>>     1) Using writel and readl replace writeq and readq, to fix kernel test
>>        robot report build error on other archtecture.
>>     2) Set default fb format to XRGB8888 at crtc reset time.
>>
>> v6:
>>     1) Explain why we are not switch to drm dridge subsystem on ls2k1000.
>>     2) Explain why tiny drm driver is not suitable for us.
>>     3) Give a short description of the trival dirty uppdate implement based
>>        on CMA helper.
>>
>> v7:
>>     1) Remove select I2C_GPIO and I2C_LS2X in Kconfig, it is not ready now
>>     2) Licensing issues are fixed suggested by Krzysztof Kozlowski.
>>     3) Remove lsdc_pixpll_print(), part of it move to debugfs.
>>     4) Set prefer_shadow to true if vram based driver is in using.
>>     5) Replace double blank lines with single line in all files.
>>     6) Verbose cmd line parameter is replaced with drm_dbg()
>>     7) All warnnings reported by ./scripts/checkpatch.pl --strict are fixed
>>     8) Get edid from dtb support is removed as suggested by Maxime Ripard
>>     9) Fix typos and various improvement
>>
>> v8:
>>     1) Drop damage update implement and its command line.
>>     2) Drop DRM_LSDC_VRAM_DRIVER config option as suggested by Maxime.
>>     3) Deduce DC's identification from its compatible property.
>>     4) Drop the board specific dts patch.
>>     5) Add documention about the display controller device node.
>>
>> v9:
>>     1) Fix the warnings reported by checkpatch script and fix typos
>>
>> v10:
>>     1) Pass `make dt_binding_check` validation
>>     2) Fix warnings reported by kernel test robot
>>
>> v11:
>>     1) Convert the driver to use drm bridge and of graph framework.
>>     2) Dump register value support through debugfs.
>>
>> Reported-by: kernel test robot <lkp@intel.com>
>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>> ---
>>   drivers/gpu/drm/Kconfig             |   2 +
>>   drivers/gpu/drm/Makefile            |   1 +
>>   drivers/gpu/drm/lsdc/Kconfig        |  23 ++
>>   drivers/gpu/drm/lsdc/Makefile       |  13 +
>>   drivers/gpu/drm/lsdc/lsdc_crtc.c    | 396 +++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_drv.c     | 547 ++++++++++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_drv.h     | 197 ++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_i2c.c     | 235 ++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_i2c.h     |  42 ++
>>   drivers/gpu/drm/lsdc/lsdc_irq.c     |  58 +++
>>   drivers/gpu/drm/lsdc/lsdc_irq.h     |  18 +
>>   drivers/gpu/drm/lsdc/lsdc_output.c  | 262 +++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_output.h  |  24 ++
>>   drivers/gpu/drm/lsdc/lsdc_pci_drv.c | 328 ++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_plane.c   | 470 +++++++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_pll.c     | 574 ++++++++++++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_pll.h     |  88 +++++
>>   drivers/gpu/drm/lsdc/lsdc_regs.h    | 220 +++++++++++
>>   18 files changed, 3498 insertions(+)
>>   create mode 100644 drivers/gpu/drm/lsdc/Kconfig
>>   create mode 100644 drivers/gpu/drm/lsdc/Makefile
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_crtc.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_pci_drv.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_plane.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_regs.h
> [...]
>
>> diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.c b/drivers/gpu/drm/lsdc/lsdc_i2c.c
>> new file mode 100644
>> index 000000000000..55beed9266fa
>> --- /dev/null
>> +++ b/drivers/gpu/drm/lsdc/lsdc_i2c.c
>> @@ -0,0 +1,235 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * KMS driver for Loongson display controller
> Not really a useful comment since every file has the same one.
>
>> + * Copyright (C) 2022 Loongson Corporation
>> + */
>> +
>> +/*
>> + * Authors:
>> + *      Sui Jingfeng <suijingfeng@loongson.cn>
>> + */
>> +
>> +#include <linux/i2c.h>
>> +#include <linux/pci.h>
>> +
>> +#include "lsdc_drv.h"
>> +#include "lsdc_regs.h"
>> +#include "lsdc_i2c.h"
>> +
>> +/*
>> + * ls7a_gpio_i2c_set - set the state of a gpio pin indicated by mask
>> + * @mask: gpio pin mask
>> + */
>> +static void ls7a_gpio_i2c_set(struct lsdc_i2c * const li2c, int mask, int state)
>> +{
>> +	unsigned long flags;
>> +	u8 val;
>> +
>> +	spin_lock_irqsave(&li2c->reglock, flags);
> What are you protecting? Doesn't the caller serialize calls to these
> functions?
>
>> +
>> +	if (state) {
>> +		val = readb(li2c->dir_reg);
>> +		val |= mask;
>> +		writeb(val, li2c->dir_reg);
>> +	} else {
>> +		val = readb(li2c->dir_reg);
>> +		val &= ~mask;
>> +		writeb(val, li2c->dir_reg);
>> +
>> +		val = readb(li2c->dat_reg);
>> +		if (state)
> This condition is never true. We're in the 'else' because !state.
>
>> +			val |= mask;
>> +		else
>> +			val &= ~mask;
>> +		writeb(val, li2c->dat_reg);
> Shouldn't you set the data register low first and then change the
> direction? Otherwise, you may be driving high for a moment. However, if
> high is always done by setting the direction as input, why write the
> data register each time? I'm assuming whatever is written to the dat_reg
> is maintained regardless of pin state.
>
When the pin is input, i am not sure value written to it will be preserved.

I'm worry about it get flushed by the external input value.

Because the output data register is same with the input data register( 
offset is  0x1650).

The hardware designer do not provided a  separation.

>> +	}
>> +
>> +	spin_unlock_irqrestore(&li2c->reglock, flags);
>> +}
>> +
>> +/*
>> + * ls7a_gpio_i2c_get - read value back from gpio pin
>> + * @mask: gpio pin mask
>> + */
>> +static int ls7a_gpio_i2c_get(struct lsdc_i2c * const li2c, int mask)
>> +{
>> +	unsigned long flags;
>> +	u8 val;
>> +
>> +	spin_lock_irqsave(&li2c->reglock, flags);
>> +
>> +	/* first set this pin as input */
>> +	val = readb(li2c->dir_reg);
>> +	val |= mask;
>> +	writeb(val, li2c->dir_reg);
>> +
>> +	/* then get level state from this pin */
>> +	val = readb(li2c->dat_reg);
>> +
>> +	spin_unlock_irqrestore(&li2c->reglock, flags);
>> +
>> +	return (val & mask) ? 1 : 0;
>> +}
>> +
>> +/* set the state on the i2c->sda pin */
>> +static void ls7a_i2c_set_sda(void *i2c, int state)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_set(li2c, li2c->sda, state);
>> +}
>> +
>> +/* set the state on the i2c->scl pin */
>> +static void ls7a_i2c_set_scl(void *i2c, int state)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_set(li2c, li2c->scl, state);
>> +}
>> +
>> +/* read the value from the i2c->sda pin */
>> +static int ls7a_i2c_get_sda(void *i2c)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_get(li2c, li2c->sda);
>> +}
>> +
>> +/* read the value from the i2c->scl pin */
>> +static int ls7a_i2c_get_scl(void *i2c)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_get(li2c, li2c->scl);
>> +}
>> +
>> +/*
>> + * mainly for dc in ls7a1000 which have builtin gpio emulated i2c
>> + *
>> + * @index : output channel index, 0 for DVO0, 1 for DVO1
>> + */
>> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev, void *base, unsigned int index)
>> +{
>> +	char compat[32] = {0};
>> +	unsigned int udelay = 5;
>> +	unsigned int timeout = 2200;
>> +	int nr = -1;
>> +	struct i2c_adapter *adapter;
>> +	struct lsdc_i2c *li2c;
>> +	struct device_node *i2c_np;
>> +	int ret;
>> +
>> +	li2c = devm_kzalloc(dev, sizeof(*li2c), GFP_KERNEL);
>> +	if (!li2c)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	li2c->index = index;
>> +	li2c->dev = dev;
>> +
>> +	if (index == 0) {
>> +		li2c->sda = 0x01;
>> +		li2c->scl = 0x02;
>> +	} else if (index == 1) {
>> +		li2c->sda = 0x04;
>> +		li2c->scl = 0x08;
> Just require this to be in DT rather than having some default.
>
>> +	}
>> +
>> +	spin_lock_init(&li2c->reglock);
>> +
>> +	snprintf(compat, sizeof(compat), "lsdc,i2c-gpio-%d", index);
> compatible values shouldn't have an index and you shouldn't need a
> index in DT. You need to iterate over child nodes with matching
> compatible.
>
>> +	i2c_np = of_find_compatible_node(dev->of_node, NULL, compat);
>> +	if (i2c_np) {
>> +		u32 sda, scl;
>> +
>> +		dev_dbg(dev, "Has %s property in the DT", compat);
>> +
>> +		/*  */
>> +		ret = of_property_read_u32(i2c_np, "sda", &sda);
> Custom properties need a vendor prefix.
>
>> +		if (ret == 0)
>> +			li2c->sda = 1 << sda;
>> +
>> +		ret = of_property_read_u32(i2c_np, "scl", &scl);
>> +		if (ret == 0)
>> +			li2c->scl = 1 << scl;
>> +
>> +		/* Optional properties which made the driver more flexible */
>> +		of_property_read_u32(i2c_np, "udelay", &udelay);
>> +		of_property_read_u32(i2c_np, "timeout", &timeout);
> These aren't documented. Do you really need them in DT?

Yes, in very rare case:

When debugging, sometimes one way I2C works, another way I2C not on 
specific board.

and you want to see what will happen if you change it from 5 to 2.

modify device tree is enough, have to recompile the kernel and driver 
modules every time.

It is optional through.

Please do not ask me to document such a easy thing,
DT itself is a documention, human readable,  it already speak for itself.
>> +		of_property_read_u32(i2c_np, "reg", &nr);
>> +	}
>> +
>> +	dev_dbg(dev, "%s: sda=%u, scl=%u, nr=%d, udelay=%u, timeout=%u\n",
>> +		compat, li2c->sda, li2c->scl, nr, udelay, timeout);
>> +
>> +	li2c->reg_base = base;
>> +
>> +	li2c->dir_reg = li2c->reg_base + LS7A_DC_GPIO_DIR_REG;
>> +	li2c->dat_reg = li2c->reg_base + LS7A_DC_GPIO_DAT_REG;
>> +
>> +	li2c->bit.setsda = ls7a_i2c_set_sda;
>> +	li2c->bit.setscl = ls7a_i2c_set_scl;
>> +	li2c->bit.getsda = ls7a_i2c_get_sda;
>> +	li2c->bit.getscl = ls7a_i2c_get_scl;
>> +	li2c->bit.udelay = udelay;
>> +	li2c->bit.timeout = usecs_to_jiffies(timeout);
>> +	li2c->bit.data = li2c;
>> +
>> +	adapter = &li2c->adapter;
>> +	adapter->algo_data = &li2c->bit;
>> +	adapter->owner = THIS_MODULE;
>> +	adapter->class = I2C_CLASS_DDC;
>> +	adapter->dev.parent = dev;
>> +	adapter->nr = nr;
>> +	if (i2c_np) {
>> +		adapter->dev.of_node = i2c_np;
>> +		of_node_put(i2c_np);
>> +	}
>> +
>> +	strscpy(adapter->name, &compat[5], sizeof(adapter->name));
>> +
>> +	i2c_set_adapdata(adapter, li2c);
>> +
>> +	ret = i2c_bit_add_numbered_bus(adapter);
> Why do you care what the bus number is? You shouldn't need to.
>
>> +	if (ret) {
>> +		if (i2c_np)
>> +			of_node_put(i2c_np);
>> +
>> +		devm_kfree(dev, li2c);
>> +		return ERR_PTR(ret);
>> +	}
>> +
>> +	return li2c;
>> +}
>> +
>> +void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c)
>> +{
>> +	struct i2c_adapter *adapter;
>> +
>> +	if (li2c) {
>> +		adapter = &li2c->adapter;
>> +
>> +		if (adapter && adapter->dev.of_node)
>> +			of_node_put(adapter->dev.of_node);
>> +
>> +		devm_kfree(ddev->dev, li2c);
>> +	}
>> +}
>> +
>> +struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
>> +					 unsigned int index)
>> +{
>> +	const struct lsdc_chip_desc * const descp = ldev->desc;
>> +	struct lsdc_i2c *li2c;
>> +
>> +	if (index >= descp->num_of_crtc) {
>> +		drm_err(ldev->ddev, "I2c adapter is no more than %u, %u\n",
>> +			descp->num_of_crtc, index);
>> +		return NULL;
>> +	}
>> +
>> +	li2c = ldev->li2c[index];
>> +	if (li2c)
>> +		return &li2c->adapter;
>> +
>> +	return NULL;
>> +}
>> diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.h b/drivers/gpu/drm/lsdc/lsdc_i2c.h
>> new file mode 100644
>> index 000000000000..4ab825143eb4
>> --- /dev/null
>> +++ b/drivers/gpu/drm/lsdc/lsdc_i2c.h
>> @@ -0,0 +1,42 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * KMS driver for Loongson display controller
>> + * Copyright (C) 2022 Loongson Corporation
>> + */
>> +
>> +/*
>> + * Authors:
>> + *      Sui Jingfeng <suijingfeng@loongson.cn>
>> + */
>> +
>> +#ifndef __LSDC_I2C__
>> +#define __LSDC_I2C__
>> +
>> +#include <linux/i2c.h>
>> +#include <linux/i2c-algo-bit.h>
>> +#include <linux/pci.h>
>> +
>> +struct lsdc_i2c {
>> +	struct device *dev;
>> +	struct i2c_adapter adapter;
>> +	struct i2c_algo_bit_data bit;
>> +	/* @reglock: protects concurrent register access */
>> +	spinlock_t reglock;
>> +	void __iomem *reg_base;
>> +	void __iomem *dir_reg;
>> +	void __iomem *dat_reg;
>> +	int index;
>> +	/* pin bit mask */
>> +	u8 sda;
>> +	u8 scl;
>> +};
>> +
>> +void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c);
>> +
>> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev,
>> +				      void *base,
>> +				      unsigned int index);
>> +
>> +struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
>> +					 unsigned int index);
>> +#endif

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-23 13:03           ` Rob Herring
@ 2022-03-24  1:48             ` Sui Jingfeng
  2022-03-24 13:26               ` Rob Herring
  0 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-24  1:48 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel


On 2022/3/23 21:03, Rob Herring wrote:
> On Wed, Mar 23, 2022 at 11:38:55AM +0800, Sui Jingfeng wrote:
>> On 2022/3/23 04:55, Rob Herring wrote:
>>> On Tue, Mar 22, 2022 at 10:33:45AM +0800, Sui Jingfeng wrote:
>>>> On 2022/3/22 07:20, Rob Herring wrote:
>>>>> On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
>>>>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>>>>
>>>>> Needs a commit message.
>>>>>
>>>>>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>>>>>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>>>>> Same person? Don't need both emails.
>>>> Yes,  suijingfeng@loongson.cn is my company's email. But it can not be used
>>>> to send patches to dri-devel,
>>>>
>>>> when send patches with this email, the patch will not be shown on patch
>>>> works.
>>>>
>>>> Emails  are either blocked or got  rejected  by loongson's mail server.  It
>>>> can only receive emails
>>>>
>>>> from you and other people, but not dri-devel. so have to use my personal
>>>> email(15330273260@189.cn) to send patches.
>>>>
>>>>>> ---
>>>>>>     .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
>>>>>>     1 file changed, 230 insertions(+)
>>>>>>     create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>>>
>>>>>> diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>>> new file mode 100644
>>>>>> index 000000000000..7be63346289e
>>>>>> --- /dev/null
>>>>>> +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>>> @@ -0,0 +1,230 @@
>>>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>>>>> +%YAML 1.2
>>>>>> +---
>>>>>> +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
>>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>>> +
>>>>>> +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
>>>>>> +
>>>>>> +maintainers:
>>>>>> +  - Sui Jingfeng <suijingfeng@loongson.cn>
>>>>>> +
>>>>>> +description: |+
>>>>>> +
>>>>>> +  Loongson display controllers are simple which require scanout buffers
>>>>>> +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
>>>>>> +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
>>>>>> +  with a dedicated video RAM which is 64MB or more, precise size can be
>>>>>> +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
>>>>>> +  chip.
>>>>>> +
>>>>>> +  LSDC has two display pipes, each way has a DVO interface which provide
>>>>>> +  RGB888 signals, vertical & horizontal synchronisations, data enable and
>>>>>> +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
>>>>>> +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
>>>>>> +
>>>>>> +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
>>>>>> +  located at the DC register space. They are used to emulate two way i2c,
>>>>>> +  One for DVO0, another for DVO1.
>>>>>> +
>>>>>> +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
>>>>>> +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
>>>>>> +
>>>>>> +  LSDC's display pipeline have several components as below description,
>>>>>> +
>>>>>> +  The display controller in LS7A1000:
>>>>>> +     ___________________                                     _________
>>>>>> +    |            -------|                                   |         |
>>>>>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>>>>>> +    |  _   _     -------|        ^             ^            |_________|
>>>>>> +    | | | | |    -------|        |             |
>>>>>> +    | |_| |_|    | i2c0 <--------+-------------+
>>>>>> +    |            -------|
>>>>>> +    |   DC IN LS7A1000  |
>>>>>> +    |  _   _     -------|
>>>>>> +    | | | | |    | i2c1 <--------+-------------+
>>>>>> +    | |_| |_|    -------|        |             |             _________
>>>>>> +    |            -------|        |             |            |         |
>>>>>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>>>>>> +    |            -------|                                   |_________|
>>>>>> +    |___________________|
>>>>>> +
>>>>>> +  Simple usage of LS7A1000 with LS3A4000 CPU:
>>>>>> +
>>>>>> +    +------+            +-----------------------------------+
>>>>>> +    | DDR4 |            |  +-------------------+            |
>>>>>> +    +------+            |  | PCIe Root complex |   LS7A1000 |
>>>>>> +       || MC0           |  +--++---------++----+            |
>>>>>> +  +----------+  HT 3.0  |     ||         ||                 |
>>>>>> +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>>>>>> +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>>>>>> +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
>>>>>> +       || MC1           +---------------|--|----------------+
>>>>>> +    +------+                            |  |
>>>>>> +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>>>>>> +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>>>>>> +                      +-------+                      +------+
>>>>>> +
>>>>>> +  The display controller in LS2K1000/LS2K0500:
>>>>>> +     ___________________                                     _________
>>>>>> +    |            -------|                                   |         |
>>>>>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>>>>>> +    |  _   _     -------|        ^              ^           |_________|
>>>>>> +    | | | | |           |        |              |
>>>>>> +    | |_| |_|           |     +------+          |
>>>>>> +    |                   <---->| i2c0 |<---------+
>>>>>> +    |   DC IN LS2K1000  |     +------+
>>>>>> +    |  _   _            |     +------+
>>>>>> +    | | | | |           <---->| i2c1 |----------+
>>>>>> +    | |_| |_|           |     +------+          |            _________
>>>>>> +    |            -------|        |              |           |         |
>>>>>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>>>>>> +    |            -------|                                   |_________|
>>>>>> +    |___________________|
>>>>>> +
>>>>>> +properties:
>>>>>> +  $nodename:
>>>>>> +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
>>>>>> +
>>>>>> +  compatible:
>>>>>> +    oneOf:
>>>>>> +      - items:
>>>>>> +          - enum:
>>>>>> +              - loongson,ls7a1000-dc
>>>>>> +              - loongson,ls2k1000-dc
>>>>>> +              - loongson,ls2k0500-dc
>>>>>> +
>>>>>> +  reg:
>>>>>> +    maxItems: 1
>>>>>> +
>>>>>> +  interrupts:
>>>>>> +    maxItems: 1
>>>>>> +
>>>>>> +  '#address-cells':
>>>>>> +    const: 1
>>>>>> +
>>>>>> +  '#size-cells':
>>>>>> +    const: 0
>>>>>> +
>>>>>> +  i2c-gpio@0:
>>>>>> +    description: |
>>>>>> +      Built-in GPIO emulate i2c exported for external display bridge
>>>>> If you have i2c-gpio, that belongs at the DT top-level, not here.
>>>>>
>>>>>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>>>>>> +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
>>>>> No, there's a defined i2c-gpio compatible already.
>>>> This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
>>>> By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
>>>> adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
>>>> LSDC register space, not general purpose GPIOs with separate control register resource.
>>>> So i think it is the child node of display-controller@6,1, it belongs to LSDC.
>>>> It seems that put it at the DT top-level break the hierarchy and relationship.
>>> Okay, I see. Then just 'i2c' for the node names. You need a reference to
>>> i2c-controller.yaml for these nodes too.
>>>
>>> The compatible should not have an index in it.
>> OK, i will fix this at the next version. thanks.
>>>>>> +      used to specify a I2c adapter bus number, if you don't specify one
>>>>>> +      i2c driver core will dynamically assign a bus number. Please specify
>>>>> Bus numbers are a linux detail not relevant to DT binding.
>>>>>
>>>>>> +      it only when its bus number matters. Bus number greater than 6 is safe
>>>>>> +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
>>>>>> +
>>>>>> +  i2c-gpio@1:
>>>>>> +    description: |
>>>>>> +      Built-in GPIO emulate i2c exported for external display bridge
>>>>>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>>>>>> +      only. Its compatible must be lsdc,i2c-gpio-1.
>>>>>> +
>>>>>> +  ports:
>>>>>> +    $ref: /schemas/graph.yaml#/properties/ports
>>>>>> +
>>>>>> +    properties:
>>>>>> +      port@0:
>>>>>> +        $ref: /schemas/graph.yaml#/properties/port
>>>>>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>>>>>> +
>>>>>> +      port@1:
>>>>>> +        $ref: /schemas/graph.yaml#/properties/port
>>>>>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>>>>>> +
>>>>>> +    required:
>>>>>> +      - port@0
>>>>>> +      - port@1
>>>>>> +
>>>>>> +required:
>>>>>> +  - compatible
>>>>>> +  - reg
>>>>>> +  - interrupts
>>>>>> +  - ports
>>>>>> +
>>>>>> +additionalProperties: false
>>>>>> +
>>>>>> +examples:
>>>>>> +  - |
>>>>>> +    #include <dt-bindings/interrupt-controller/irq.h>
>>>>>> +    bus {
>>>>>> +
>>>>>> +        #address-cells = <3>;
>>>>>> +        #size-cells = <2>;
>>>>>> +        #interrupt-cells = <2>;
>>>>>> +
>>>>>> +        display-controller@6,1 {
>>>>>> +            compatible = "loongson,ls7a1000-dc";
>>>>>> +            reg = <0x3100 0x0 0x0 0x0 0x0>;
>>>>>> +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
>>>>>> +
>>>>>> +            #address-cells = <1>;
>>>>>> +            #size-cells = <0>;
>>>>>> +
>>>>>> +            i2c-gpio@0 {
>>>>>> +                compatible = "lsdc,i2c-gpio-0";
>>>>>> +                reg = <6>;
>>> 'reg' needs to be documented with some description of what 6 and 7
>>> represent. If they are the control register offset, then make the
>>> address translatable (use 'ranges' and define the size).
>> By design, the reg property is used to specify a I2c adapter bus number,
>> if we don't specify one, i2c driver core will dynamically assign a bus number.
>> then the nr of the i2c adapter will started from 0. I want is start from 6
>> to avoid potential conflict feature hardware I2C driver.
>>
>> Because LS7A1000 bridge chip have 6 hardware I2C controller integrated,
>> but its driver is not up-streamed yet. By default these hardware I2C controller's
>> nr is started from 0.
> Linux's numbering doesn't belong in DT. So no, you can't use 'reg' in
> that way.
Then,  can i use something like lsdc,nr = <6> ?
>> Even through i2c driver core can dynamically generate a number, i still want it
>> to be fixed and keep consistent and explicit. That is, i2c6 is for display pipe 0,
>> i2c7 is for display pipe 1. This follow the convention and flexible enough.
> You may want that, but that is not how the kernel works. Specific
> numbers are not guaranteed. I'm sure you've seen this for disks, network
> interfaces, etc.
>
> Rob

2c_bit_add_numbered_bus() will guarantee it for you as long as If no 
devices have pre-been declared for this bus.

you can read the comment of 2c_bit_add_numbered_bus() at 
drivers/i2c/i2c-core-base.c


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board
  2022-03-23 12:53           ` Rob Herring
@ 2022-03-24  1:51             ` Sui Jingfeng
  0 siblings, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-24  1:51 UTC (permalink / raw)
  To: Rob Herring
  Cc: Jiaxun Yang, Maxime Ripard, Thomas Zimmermann,
	Roland Scheidegger, Zack Rusin, Christian Gmeiner, David Airlie,
	Daniel Vetter, Thomas Bogendoerfer, Dan Carpenter,
	Krzysztof Kozlowski, Andrey Zhizhikin, Sam Ravnborg,
	David S . Miller, Lucas Stach, Maarten Lankhorst, Ilia Mirkin,
	Qing Zhang, suijingfeng, linux-mips, linux-kernel, devicetree,
	dri-devel


On 2022/3/23 20:53, Rob Herring wrote:
> On Wed, Mar 23, 2022 at 09:53:14AM +0800, Sui Jingfeng wrote:
>> On 2022/3/23 00:06, Jiaxun Yang wrote:
>>>
>>> 在 2022/3/22 13:38, Sui Jingfeng 写道:
>>>> On 2022/3/22 21:05, Jiaxun Yang wrote:
>>>>>
>>>>> 在 2022/3/21 16:29, Sui Jingfeng 写道:
>>>>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>>>>
>>>>>> The board name is LS3A4000_7A1000_EVB_BOARD_V1.4, it consist of 1.8Ghz
>>>>>> mips64r5 4-core CPU and LS7A1000 bridge chip. It has PCIe
>>>>>> GEN2 x8 slot,
>>>>>> therefore can play with discrete graphics card.
>>>>> Hi Jingfeng,
>>>>>
>>>>> As we've discussed before if you are going to introduce new dts
>>>>> then you *MUST*
>>>>> include it in makefile and wire it up in code.
>>>>>
>>>>> A dts file doing nothing lying in the tree is just suspicious.
>>>>>
>>>>> Thanks.
>>>>> - Jiaxun
>>>>>
>>>> Hi, Jiaxun,
>>>>
>>>> I know what you means, but it is the kernel side developer's job.
>>>> I am just a naive graphic driver developer,I can not care so much.
>>>> Below is my private patch which can be used to built specific dts
>>>> into the linux kernel, therefore make the verification easier.
>>> Hi Jingfeng,
>>>
>>> In kernel world we take care all the stuff we touched ourself :-)
>>>
>>> If you are not confident with them please drop those DTS from the
>>> patchset
>>> besides the generic one. I can do the rest for you after getting this
>>> set merged.
>>>
>>> Thanks.
>>> - Jiaxun
>>>
>> Hi, Jiaxun
>>
>> Build all dts into vmlinuz will make the vmlinuz bigger and bigger.
>> How does the kernel get the dtb is another big issue, either from built-in
>> dtb or pass from the firmware(pmon and uefi etc). This should be
>> solved with another patch carefully. Providing board specific dts
>> helps to code review, it helps reviewers understand that there are
>> variant boards and have to be express with different OF graph.
> Built-in DTBs are for legacy bootloaders that don't understand DT. I
> would not expect a new platform to need this.
>
>> Now, there are about 6 dts under arch/mips/boot/dts/loongson/,
>> Suppose loongson have 1000+ different board, do you want built all
>> of them into vmlinuz?
> The point was to add the .dts to Makefile so it builds, not so it is
> built-in. How are you testing those build with dtc and dtschema if not
> added to kbuild?
OK, i see the key point.
> Rob

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-23 13:11       ` Rob Herring
@ 2022-03-24  4:05         ` Sui Jingfeng
  2022-04-08  2:09         ` Sui Jingfeng
  1 sibling, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-24  4:05 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot


On 2022/3/23 21:11, Rob Herring wrote:
> On Wed, Mar 23, 2022 at 12:12:43PM +0800, Sui Jingfeng wrote:
>> On 2022/3/23 04:49, Rob Herring wrote:
>>>> +/*
>>>> + * mainly for dc in ls7a1000 which have builtin gpio emulated i2c
>>>> + *
>>>> + * @index : output channel index, 0 for DVO0, 1 for DVO1
>>>> + */
>>>> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev, void *base, unsigned int index)
>>>> +{
>>>> +	char compat[32] = {0};
>>>> +	unsigned int udelay = 5;
>>>> +	unsigned int timeout = 2200;
>>>> +	int nr = -1;
>>>> +	struct i2c_adapter *adapter;
>>>> +	struct lsdc_i2c *li2c;
>>>> +	struct device_node *i2c_np;
>>>> +	int ret;
>>>> +
>>>> +	li2c = devm_kzalloc(dev, sizeof(*li2c), GFP_KERNEL);
>>>> +	if (!li2c)
>>>> +		return ERR_PTR(-ENOMEM);
>>>> +
>>>> +	li2c->index = index;
>>>> +	li2c->dev = dev;
>>>> +
>>>> +	if (index == 0) {
>>>> +		li2c->sda = 0x01;
>>>> +		li2c->scl = 0x02;
>>>> +	} else if (index == 1) {
>>>> +		li2c->sda = 0x04;
>>>> +		li2c->scl = 0x08;
>>> Just require this to be in DT rather than having some default.
>>>
>> By design,  I am try very hard to let the code NOT fully  DT dependent. DT is nice , easy to learn and use.
>> But kernel side developer plan to follow UEFI + ACPI Specification on LS3A5000 + LS7A1000 platform. See [1]
>> There will no DT support then, provide a convention support  make the driver more flexible. I want the
>> driver works with minimal requirement. The driver just works on simple boards by put the following dc device
>> node in arch/mips/dts/loongson/loongson64g_4core_ls7a.dts,
> Pick DT or ACPI for the platform, not both. We don't need to have both
> in the kernel to support.
>
> Rob

Hi Rob,

We can only choose DT currently, we love DT, but it is kernel side developer's choice.
We just avoid deep coupling which tend to lost flexibility.
All I can and should do is make the drivers works, writing code beautiful does not
means it can works like a charm.

 From what i am understanding, DT is not a strict specification, but in return flexible.
Force every driver comply with what already have is tend to prohibit innovation.
It just too late to do so.


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-22 20:49   ` Rob Herring
                       ` (4 preceding siblings ...)
  2022-03-24  1:39     ` Sui Jingfeng
@ 2022-03-24  7:32     ` Sui Jingfeng
  2022-03-24 13:56       ` Rob Herring
  2023-01-17  3:08     ` Sui jingfeng
  2023-02-03  2:48     ` suijingfeng
  7 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-24  7:32 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot


On 2022/3/23 04:49, Rob Herring wrote:
>> +	}
>> +
>> +	spin_lock_init(&li2c->reglock);
>> +
>> +	snprintf(compat, sizeof(compat), "lsdc,i2c-gpio-%d", index);
> compatible values shouldn't have an index and you shouldn't need a
> index in DT. You need to iterate over child nodes with matching
> compatible.

Why compatible values shouldn't have an index, does devicetree
specification prohibit this? [1]

The recommended format is "manufacturer,model", where manufacturer is a string describing the name
of the manufacturer (such as a stock ticker symbol), and model specifies the model number. [1]

[1] https://www.devicetree.org/specifications/


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-24  1:48             ` Sui Jingfeng
@ 2022-03-24 13:26               ` Rob Herring
  2022-03-26 10:04                 ` Sui Jingfeng
  0 siblings, 1 reply; 48+ messages in thread
From: Rob Herring @ 2022-03-24 13:26 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Qing Zhang, David Airlie, Jiaxun Yang, linux-kernel,
	Sam Ravnborg, Krzysztof Kozlowski, Dan Carpenter, devicetree,
	suijingfeng, Thomas Zimmermann, Roland Scheidegger,
	Andrey Zhizhikin, dri-devel, Thomas Bogendoerfer, linux-mips,
	David S . Miller

On Thu, Mar 24, 2022 at 09:48:19AM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/23 21:03, Rob Herring wrote:
> > On Wed, Mar 23, 2022 at 11:38:55AM +0800, Sui Jingfeng wrote:
> > > On 2022/3/23 04:55, Rob Herring wrote:
> > > > On Tue, Mar 22, 2022 at 10:33:45AM +0800, Sui Jingfeng wrote:
> > > > > On 2022/3/22 07:20, Rob Herring wrote:
> > > > > > On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
> > > > > > > From: suijingfeng <suijingfeng@loongson.cn>
> > > > > > > 
> > > > > > Needs a commit message.
> > > > > > 
> > > > > > > Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> > > > > > > Signed-off-by: Sui Jingfeng <15330273260@189.cn>
> > > > > > Same person? Don't need both emails.
> > > > > Yes,  suijingfeng@loongson.cn is my company's email. But it can not be used
> > > > > to send patches to dri-devel,
> > > > > 
> > > > > when send patches with this email, the patch will not be shown on patch
> > > > > works.
> > > > > 
> > > > > Emails  are either blocked or got  rejected  by loongson's mail server.  It
> > > > > can only receive emails
> > > > > 
> > > > > from you and other people, but not dri-devel. so have to use my personal
> > > > > email(15330273260@189.cn) to send patches.
> > > > > 
> > > > > > > ---
> > > > > > >     .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
> > > > > > >     1 file changed, 230 insertions(+)
> > > > > > >     create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > > > 
> > > > > > > diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..7be63346289e
> > > > > > > --- /dev/null
> > > > > > > +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > > > @@ -0,0 +1,230 @@
> > > > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > > > > +%YAML 1.2
> > > > > > > +---
> > > > > > > +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
> > > > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > > > +
> > > > > > > +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
> > > > > > > +
> > > > > > > +maintainers:
> > > > > > > +  - Sui Jingfeng <suijingfeng@loongson.cn>
> > > > > > > +
> > > > > > > +description: |+
> > > > > > > +
> > > > > > > +  Loongson display controllers are simple which require scanout buffers
> > > > > > > +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
> > > > > > > +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
> > > > > > > +  with a dedicated video RAM which is 64MB or more, precise size can be
> > > > > > > +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
> > > > > > > +  chip.
> > > > > > > +
> > > > > > > +  LSDC has two display pipes, each way has a DVO interface which provide
> > > > > > > +  RGB888 signals, vertical & horizontal synchronisations, data enable and
> > > > > > > +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
> > > > > > > +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
> > > > > > > +
> > > > > > > +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
> > > > > > > +  located at the DC register space. They are used to emulate two way i2c,
> > > > > > > +  One for DVO0, another for DVO1.
> > > > > > > +
> > > > > > > +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
> > > > > > > +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
> > > > > > > +
> > > > > > > +  LSDC's display pipeline have several components as below description,
> > > > > > > +
> > > > > > > +  The display controller in LS7A1000:
> > > > > > > +     ___________________                                     _________
> > > > > > > +    |            -------|                                   |         |
> > > > > > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > > > > > +    |  _   _     -------|        ^             ^            |_________|
> > > > > > > +    | | | | |    -------|        |             |
> > > > > > > +    | |_| |_|    | i2c0 <--------+-------------+
> > > > > > > +    |            -------|
> > > > > > > +    |   DC IN LS7A1000  |
> > > > > > > +    |  _   _     -------|
> > > > > > > +    | | | | |    | i2c1 <--------+-------------+
> > > > > > > +    | |_| |_|    -------|        |             |             _________
> > > > > > > +    |            -------|        |             |            |         |
> > > > > > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > > > > > +    |            -------|                                   |_________|
> > > > > > > +    |___________________|
> > > > > > > +
> > > > > > > +  Simple usage of LS7A1000 with LS3A4000 CPU:
> > > > > > > +
> > > > > > > +    +------+            +-----------------------------------+
> > > > > > > +    | DDR4 |            |  +-------------------+            |
> > > > > > > +    +------+            |  | PCIe Root complex |   LS7A1000 |
> > > > > > > +       || MC0           |  +--++---------++----+            |
> > > > > > > +  +----------+  HT 3.0  |     ||         ||                 |
> > > > > > > +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
> > > > > > > +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
> > > > > > > +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
> > > > > > > +       || MC1           +---------------|--|----------------+
> > > > > > > +    +------+                            |  |
> > > > > > > +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
> > > > > > > +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
> > > > > > > +                      +-------+                      +------+
> > > > > > > +
> > > > > > > +  The display controller in LS2K1000/LS2K0500:
> > > > > > > +     ___________________                                     _________
> > > > > > > +    |            -------|                                   |         |
> > > > > > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > > > > > +    |  _   _     -------|        ^              ^           |_________|
> > > > > > > +    | | | | |           |        |              |
> > > > > > > +    | |_| |_|           |     +------+          |
> > > > > > > +    |                   <---->| i2c0 |<---------+
> > > > > > > +    |   DC IN LS2K1000  |     +------+
> > > > > > > +    |  _   _            |     +------+
> > > > > > > +    | | | | |           <---->| i2c1 |----------+
> > > > > > > +    | |_| |_|           |     +------+          |            _________
> > > > > > > +    |            -------|        |              |           |         |
> > > > > > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > > > > > +    |            -------|                                   |_________|
> > > > > > > +    |___________________|
> > > > > > > +
> > > > > > > +properties:
> > > > > > > +  $nodename:
> > > > > > > +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
> > > > > > > +
> > > > > > > +  compatible:
> > > > > > > +    oneOf:
> > > > > > > +      - items:
> > > > > > > +          - enum:
> > > > > > > +              - loongson,ls7a1000-dc
> > > > > > > +              - loongson,ls2k1000-dc
> > > > > > > +              - loongson,ls2k0500-dc
> > > > > > > +
> > > > > > > +  reg:
> > > > > > > +    maxItems: 1
> > > > > > > +
> > > > > > > +  interrupts:
> > > > > > > +    maxItems: 1
> > > > > > > +
> > > > > > > +  '#address-cells':
> > > > > > > +    const: 1
> > > > > > > +
> > > > > > > +  '#size-cells':
> > > > > > > +    const: 0
> > > > > > > +
> > > > > > > +  i2c-gpio@0:
> > > > > > > +    description: |
> > > > > > > +      Built-in GPIO emulate i2c exported for external display bridge
> > > > > > If you have i2c-gpio, that belongs at the DT top-level, not here.
> > > > > > 
> > > > > > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > > > > > +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
> > > > > > No, there's a defined i2c-gpio compatible already.
> > > > > This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
> > > > > By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
> > > > > adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
> > > > > LSDC register space, not general purpose GPIOs with separate control register resource.
> > > > > So i think it is the child node of display-controller@6,1, it belongs to LSDC.
> > > > > It seems that put it at the DT top-level break the hierarchy and relationship.
> > > > Okay, I see. Then just 'i2c' for the node names. You need a reference to
> > > > i2c-controller.yaml for these nodes too.
> > > > 
> > > > The compatible should not have an index in it.
> > > OK, i will fix this at the next version. thanks.
> > > > > > > +      used to specify a I2c adapter bus number, if you don't specify one
> > > > > > > +      i2c driver core will dynamically assign a bus number. Please specify
> > > > > > Bus numbers are a linux detail not relevant to DT binding.
> > > > > > 
> > > > > > > +      it only when its bus number matters. Bus number greater than 6 is safe
> > > > > > > +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
> > > > > > > +
> > > > > > > +  i2c-gpio@1:
> > > > > > > +    description: |
> > > > > > > +      Built-in GPIO emulate i2c exported for external display bridge
> > > > > > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > > > > > +      only. Its compatible must be lsdc,i2c-gpio-1.
> > > > > > > +
> > > > > > > +  ports:
> > > > > > > +    $ref: /schemas/graph.yaml#/properties/ports
> > > > > > > +
> > > > > > > +    properties:
> > > > > > > +      port@0:
> > > > > > > +        $ref: /schemas/graph.yaml#/properties/port
> > > > > > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > > > > > +
> > > > > > > +      port@1:
> > > > > > > +        $ref: /schemas/graph.yaml#/properties/port
> > > > > > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > > > > > +
> > > > > > > +    required:
> > > > > > > +      - port@0
> > > > > > > +      - port@1
> > > > > > > +
> > > > > > > +required:
> > > > > > > +  - compatible
> > > > > > > +  - reg
> > > > > > > +  - interrupts
> > > > > > > +  - ports
> > > > > > > +
> > > > > > > +additionalProperties: false
> > > > > > > +
> > > > > > > +examples:
> > > > > > > +  - |
> > > > > > > +    #include <dt-bindings/interrupt-controller/irq.h>
> > > > > > > +    bus {
> > > > > > > +
> > > > > > > +        #address-cells = <3>;
> > > > > > > +        #size-cells = <2>;
> > > > > > > +        #interrupt-cells = <2>;
> > > > > > > +
> > > > > > > +        display-controller@6,1 {
> > > > > > > +            compatible = "loongson,ls7a1000-dc";
> > > > > > > +            reg = <0x3100 0x0 0x0 0x0 0x0>;
> > > > > > > +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
> > > > > > > +
> > > > > > > +            #address-cells = <1>;
> > > > > > > +            #size-cells = <0>;
> > > > > > > +
> > > > > > > +            i2c-gpio@0 {
> > > > > > > +                compatible = "lsdc,i2c-gpio-0";
> > > > > > > +                reg = <6>;
> > > > 'reg' needs to be documented with some description of what 6 and 7
> > > > represent. If they are the control register offset, then make the
> > > > address translatable (use 'ranges' and define the size).
> > > By design, the reg property is used to specify a I2c adapter bus number,
> > > if we don't specify one, i2c driver core will dynamically assign a bus number.
> > > then the nr of the i2c adapter will started from 0. I want is start from 6
> > > to avoid potential conflict feature hardware I2C driver.
> > > 
> > > Because LS7A1000 bridge chip have 6 hardware I2C controller integrated,
> > > but its driver is not up-streamed yet. By default these hardware I2C controller's
> > > nr is started from 0.
> > Linux's numbering doesn't belong in DT. So no, you can't use 'reg' in
> > that way.
> Then,  can i use something like lsdc,nr = <6> ?
> > > Even through i2c driver core can dynamically generate a number, i still want it
> > > to be fixed and keep consistent and explicit. That is, i2c6 is for display pipe 0,
> > > i2c7 is for display pipe 1. This follow the convention and flexible enough.
> > You may want that, but that is not how the kernel works. Specific
> > numbers are not guaranteed. I'm sure you've seen this for disks, network
> > interfaces, etc.
> > 
> > Rob
> 
> 2c_bit_add_numbered_bus() will guarantee it for you as long as If no devices
> have pre-been declared for this bus.
> 
> you can read the comment of 2c_bit_add_numbered_bus() at
> drivers/i2c/i2c-core-base.c

I didn't say it wasn't possible. It is not best practice. Grep 
i2c_bit_add_numbered_bus and see how many users there are. Even if the 
kernel allows specifying bus numbers, your Linux bus numbers don't 
belong in DT.

Rob

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-24  1:39     ` Sui Jingfeng
@ 2022-03-24 13:42       ` Rob Herring
  0 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2022-03-24 13:42 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	suijingfeng, linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot

On Thu, Mar 24, 2022 at 09:39:49AM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/23 04:49, Rob Herring wrote:
> > On Tue, Mar 22, 2022 at 12:29:16AM +0800, Sui Jingfeng wrote:
> > > From: suijingfeng <suijingfeng@loongson.cn>
> > > 
> > > There is a display controller in loongson's LS2K1000 SoC and LS7A1000
> > > bridge chip, the display controller is a PCI device in those chips. It
> > > has two display pipes but with only one hardware cursor. Each way has
> > > a DVO interface which provide RGB888 signals, vertical & horizontal
> > > synchronisations, data enable and the pixel clock. Each CRTC is able to
> > > scanout from 1920x1080 resolution at 60Hz, the maxmium resolution is
> > > 2048x2048 according to the hardware spec. Loongson display controllers
> > > are simple which require scanout buffers to be physically contiguous.

[...]

> > > +			val |= mask;
> > > +		else
> > > +			val &= ~mask;
> > > +		writeb(val, li2c->dat_reg);
> > Shouldn't you set the data register low first and then change the
> > direction? Otherwise, you may be driving high for a moment. However, if
> > high is always done by setting the direction as input, why write the
> > data register each time? I'm assuming whatever is written to the dat_reg
> > is maintained regardless of pin state.
> > 
> When the pin is input, i am not sure value written to it will be preserved.
> 
> I'm worry about it get flushed by the external input value.
> 
> Because the output data register is same with the input data register(
> offset is  0x1650).
> 
> The hardware designer do not provided a  separation.

Usually for GPIO data registers the read value is current pin state 
regardless of direction and the written value is what to drive as an 
output. But your h/w could be different.


> > > +
> > > +		/* Optional properties which made the driver more flexible */
> > > +		of_property_read_u32(i2c_np, "udelay", &udelay);
> > > +		of_property_read_u32(i2c_np, "timeout", &timeout);
> > These aren't documented. Do you really need them in DT?
> 
> Yes, in very rare case:
> 
> When debugging, sometimes one way I2C works, another way I2C not on specific
> board.

This is not specific to you, so why do you solve it in a way that only 
works for you? If you want to add tuning parameters to the i2c bit 
algorithm, why don't you do so in a way that works for all users? I'm 
sure the I2C maintainer and others have some opinion on this, but 
they'll never see it hidden away in some display driver.


> and you want to see what will happen if you change it from 5 to 2.
> 
> modify device tree is enough, have to recompile the kernel and driver
> modules every time.

Modifying the DT is not the easiest way to debug either.


> It is optional through.

Lots of properties are optional, what's your point?


> Please do not ask me to document such a easy thing,

Everything must be documented. There's nothing more to discuss.


> DT itself is a documention, human readable,  it already speak for itself.

It is machine readable too. Undocumented properties generate warnings 
now.

Rob

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-24  7:32     ` Sui Jingfeng
@ 2022-03-24 13:56       ` Rob Herring
  0 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2022-03-24 13:56 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Qing Zhang, David Airlie, Jiaxun Yang, linux-kernel,
	Sam Ravnborg, kernel test robot, Krzysztof Kozlowski,
	Dan Carpenter, devicetree, suijingfeng, Thomas Zimmermann,
	Roland Scheidegger, Andrey Zhizhikin, dri-devel,
	Thomas Bogendoerfer, linux-mips, David S . Miller

On Thu, Mar 24, 2022 at 03:32:01PM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/23 04:49, Rob Herring wrote:
> > > +	}
> > > +
> > > +	spin_lock_init(&li2c->reglock);
> > > +
> > > +	snprintf(compat, sizeof(compat), "lsdc,i2c-gpio-%d", index);
> > compatible values shouldn't have an index and you shouldn't need a
> > index in DT. You need to iterate over child nodes with matching
> > compatible.
> 
> Why compatible values shouldn't have an index, does devicetree
> specification prohibit this? [1]

Probably not explicitly, but that's fundamentally not how compatible 
works. 'compatible' defines WHAT the device is, not WHICH device and 
that is used for matching devices to drivers. Drivers work on multiple 
instances.

> The recommended format is "manufacturer,model", where manufacturer is a string describing the name
> of the manufacturer (such as a stock ticker symbol), and model specifies the model number. [1]

I don't see anything saying to put the instance in there, do you?

> 
> [1] https://www.devicetree.org/specifications/
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-24 13:26               ` Rob Herring
@ 2022-03-26 10:04                 ` Sui Jingfeng
  2022-03-28 14:04                   ` Rob Herring
  0 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-26 10:04 UTC (permalink / raw)
  To: Rob Herring
  Cc: Qing Zhang, David Airlie, Jiaxun Yang, linux-kernel,
	Sam Ravnborg, Krzysztof Kozlowski, Dan Carpenter, devicetree,
	suijingfeng, Thomas Zimmermann, Roland Scheidegger,
	Andrey Zhizhikin, dri-devel, Thomas Bogendoerfer, linux-mips,
	David S . Miller


On 2022/3/24 21:26, Rob Herring wrote:
> On Thu, Mar 24, 2022 at 09:48:19AM +0800, Sui Jingfeng wrote:
>> On 2022/3/23 21:03, Rob Herring wrote:
>>> On Wed, Mar 23, 2022 at 11:38:55AM +0800, Sui Jingfeng wrote:
>>>> On 2022/3/23 04:55, Rob Herring wrote:
>>>>> On Tue, Mar 22, 2022 at 10:33:45AM +0800, Sui Jingfeng wrote:
>>>>>> On 2022/3/22 07:20, Rob Herring wrote:
>>>>>>> On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
>>>>>>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>>>>>>
>>>>>>> Needs a commit message.
>>>>>>>
>>>>>>>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>>>>>>>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>>>>>>> Same person? Don't need both emails.
>>>>>> Yes,  suijingfeng@loongson.cn is my company's email. But it can not be used
>>>>>> to send patches to dri-devel,
>>>>>>
>>>>>> when send patches with this email, the patch will not be shown on patch
>>>>>> works.
>>>>>>
>>>>>> Emails  are either blocked or got  rejected  by loongson's mail server.  It
>>>>>> can only receive emails
>>>>>>
>>>>>> from you and other people, but not dri-devel. so have to use my personal
>>>>>> email(15330273260@189.cn) to send patches.
>>>>>>
>>>>>>>> ---
>>>>>>>>      .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
>>>>>>>>      1 file changed, 230 insertions(+)
>>>>>>>>      create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>>>>>
>>>>>>>> diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>>>>> new file mode 100644
>>>>>>>> index 000000000000..7be63346289e
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>>>>> @@ -0,0 +1,230 @@
>>>>>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>>>>>>> +%YAML 1.2
>>>>>>>> +---
>>>>>>>> +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
>>>>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>>>>> +
>>>>>>>> +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
>>>>>>>> +
>>>>>>>> +maintainers:
>>>>>>>> +  - Sui Jingfeng <suijingfeng@loongson.cn>
>>>>>>>> +
>>>>>>>> +description: |+
>>>>>>>> +
>>>>>>>> +  Loongson display controllers are simple which require scanout buffers
>>>>>>>> +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
>>>>>>>> +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
>>>>>>>> +  with a dedicated video RAM which is 64MB or more, precise size can be
>>>>>>>> +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
>>>>>>>> +  chip.
>>>>>>>> +
>>>>>>>> +  LSDC has two display pipes, each way has a DVO interface which provide
>>>>>>>> +  RGB888 signals, vertical & horizontal synchronisations, data enable and
>>>>>>>> +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
>>>>>>>> +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
>>>>>>>> +
>>>>>>>> +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
>>>>>>>> +  located at the DC register space. They are used to emulate two way i2c,
>>>>>>>> +  One for DVO0, another for DVO1.
>>>>>>>> +
>>>>>>>> +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
>>>>>>>> +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
>>>>>>>> +
>>>>>>>> +  LSDC's display pipeline have several components as below description,
>>>>>>>> +
>>>>>>>> +  The display controller in LS7A1000:
>>>>>>>> +     ___________________                                     _________
>>>>>>>> +    |            -------|                                   |         |
>>>>>>>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>>>>>>>> +    |  _   _     -------|        ^             ^            |_________|
>>>>>>>> +    | | | | |    -------|        |             |
>>>>>>>> +    | |_| |_|    | i2c0 <--------+-------------+
>>>>>>>> +    |            -------|
>>>>>>>> +    |   DC IN LS7A1000  |
>>>>>>>> +    |  _   _     -------|
>>>>>>>> +    | | | | |    | i2c1 <--------+-------------+
>>>>>>>> +    | |_| |_|    -------|        |             |             _________
>>>>>>>> +    |            -------|        |             |            |         |
>>>>>>>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>>>>>>>> +    |            -------|                                   |_________|
>>>>>>>> +    |___________________|
>>>>>>>> +
>>>>>>>> +  Simple usage of LS7A1000 with LS3A4000 CPU:
>>>>>>>> +
>>>>>>>> +    +------+            +-----------------------------------+
>>>>>>>> +    | DDR4 |            |  +-------------------+            |
>>>>>>>> +    +------+            |  | PCIe Root complex |   LS7A1000 |
>>>>>>>> +       || MC0           |  +--++---------++----+            |
>>>>>>>> +  +----------+  HT 3.0  |     ||         ||                 |
>>>>>>>> +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>>>>>>>> +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>>>>>>>> +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
>>>>>>>> +       || MC1           +---------------|--|----------------+
>>>>>>>> +    +------+                            |  |
>>>>>>>> +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>>>>>>>> +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>>>>>>>> +                      +-------+                      +------+
>>>>>>>> +
>>>>>>>> +  The display controller in LS2K1000/LS2K0500:
>>>>>>>> +     ___________________                                     _________
>>>>>>>> +    |            -------|                                   |         |
>>>>>>>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>>>>>>>> +    |  _   _     -------|        ^              ^           |_________|
>>>>>>>> +    | | | | |           |        |              |
>>>>>>>> +    | |_| |_|           |     +------+          |
>>>>>>>> +    |                   <---->| i2c0 |<---------+
>>>>>>>> +    |   DC IN LS2K1000  |     +------+
>>>>>>>> +    |  _   _            |     +------+
>>>>>>>> +    | | | | |           <---->| i2c1 |----------+
>>>>>>>> +    | |_| |_|           |     +------+          |            _________
>>>>>>>> +    |            -------|        |              |           |         |
>>>>>>>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>>>>>>>> +    |            -------|                                   |_________|
>>>>>>>> +    |___________________|
>>>>>>>> +
>>>>>>>> +properties:
>>>>>>>> +  $nodename:
>>>>>>>> +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
>>>>>>>> +
>>>>>>>> +  compatible:
>>>>>>>> +    oneOf:
>>>>>>>> +      - items:
>>>>>>>> +          - enum:
>>>>>>>> +              - loongson,ls7a1000-dc
>>>>>>>> +              - loongson,ls2k1000-dc
>>>>>>>> +              - loongson,ls2k0500-dc
>>>>>>>> +
>>>>>>>> +  reg:
>>>>>>>> +    maxItems: 1
>>>>>>>> +
>>>>>>>> +  interrupts:
>>>>>>>> +    maxItems: 1
>>>>>>>> +
>>>>>>>> +  '#address-cells':
>>>>>>>> +    const: 1
>>>>>>>> +
>>>>>>>> +  '#size-cells':
>>>>>>>> +    const: 0
>>>>>>>> +
>>>>>>>> +  i2c-gpio@0:
>>>>>>>> +    description: |
>>>>>>>> +      Built-in GPIO emulate i2c exported for external display bridge
>>>>>>> If you have i2c-gpio, that belongs at the DT top-level, not here.
>>>>>>>
>>>>>>>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>>>>>>>> +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
>>>>>>> No, there's a defined i2c-gpio compatible already.
>>>>>> This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
>>>>>> By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
>>>>>> adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
>>>>>> LSDC register space, not general purpose GPIOs with separate control register resource.
>>>>>> So i think it is the child node of display-controller@6,1, it belongs to LSDC.
>>>>>> It seems that put it at the DT top-level break the hierarchy and relationship.
>>>>> Okay, I see. Then just 'i2c' for the node names. You need a reference to
>>>>> i2c-controller.yaml for these nodes too.
>>>>>
>>>>> The compatible should not have an index in it.
>>>> OK, i will fix this at the next version. thanks.
>>>>>>>> +      used to specify a I2c adapter bus number, if you don't specify one
>>>>>>>> +      i2c driver core will dynamically assign a bus number. Please specify
>>>>>>> Bus numbers are a linux detail not relevant to DT binding.
>>>>>>>
>>>>>>>> +      it only when its bus number matters. Bus number greater than 6 is safe
>>>>>>>> +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
>>>>>>>> +
>>>>>>>> +  i2c-gpio@1:
>>>>>>>> +    description: |
>>>>>>>> +      Built-in GPIO emulate i2c exported for external display bridge
>>>>>>>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>>>>>>>> +      only. Its compatible must be lsdc,i2c-gpio-1.
>>>>>>>> +
>>>>>>>> +  ports:
>>>>>>>> +    $ref: /schemas/graph.yaml#/properties/ports
>>>>>>>> +
>>>>>>>> +    properties:
>>>>>>>> +      port@0:
>>>>>>>> +        $ref: /schemas/graph.yaml#/properties/port
>>>>>>>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>>>>>>>> +
>>>>>>>> +      port@1:
>>>>>>>> +        $ref: /schemas/graph.yaml#/properties/port
>>>>>>>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>>>>>>>> +
>>>>>>>> +    required:
>>>>>>>> +      - port@0
>>>>>>>> +      - port@1
>>>>>>>> +
>>>>>>>> +required:
>>>>>>>> +  - compatible
>>>>>>>> +  - reg
>>>>>>>> +  - interrupts
>>>>>>>> +  - ports
>>>>>>>> +
>>>>>>>> +additionalProperties: false
>>>>>>>> +
>>>>>>>> +examples:
>>>>>>>> +  - |
>>>>>>>> +    #include <dt-bindings/interrupt-controller/irq.h>
>>>>>>>> +    bus {
>>>>>>>> +
>>>>>>>> +        #address-cells = <3>;
>>>>>>>> +        #size-cells = <2>;
>>>>>>>> +        #interrupt-cells = <2>;
>>>>>>>> +
>>>>>>>> +        display-controller@6,1 {
>>>>>>>> +            compatible = "loongson,ls7a1000-dc";
>>>>>>>> +            reg = <0x3100 0x0 0x0 0x0 0x0>;
>>>>>>>> +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
>>>>>>>> +
>>>>>>>> +            #address-cells = <1>;
>>>>>>>> +            #size-cells = <0>;
>>>>>>>> +
>>>>>>>> +            i2c-gpio@0 {
>>>>>>>> +                compatible = "lsdc,i2c-gpio-0";
>>>>>>>> +                reg = <6>;
>>>>> 'reg' needs to be documented with some description of what 6 and 7
>>>>> represent. If they are the control register offset, then make the
>>>>> address translatable (use 'ranges' and define the size).
>>>> By design, the reg property is used to specify a I2c adapter bus number,
>>>> if we don't specify one, i2c driver core will dynamically assign a bus number.
>>>> then the nr of the i2c adapter will started from 0. I want is start from 6
>>>> to avoid potential conflict feature hardware I2C driver.
>>>>
>>>> Because LS7A1000 bridge chip have 6 hardware I2C controller integrated,
>>>> but its driver is not up-streamed yet. By default these hardware I2C controller's
>>>> nr is started from 0.
>>> Linux's numbering doesn't belong in DT. So no, you can't use 'reg' in
>>> that way.
>> Then,  can i use something like lsdc,nr = <6> ?
>>>> Even through i2c driver core can dynamically generate a number, i still want it
>>>> to be fixed and keep consistent and explicit. That is, i2c6 is for display pipe 0,
>>>> i2c7 is for display pipe 1. This follow the convention and flexible enough.
>>> You may want that, but that is not how the kernel works. Specific
>>> numbers are not guaranteed. I'm sure you've seen this for disks, network
>>> interfaces, etc.
>>>
>>> Rob
>> 2c_bit_add_numbered_bus() will guarantee it for you as long as If no devices
>> have pre-been declared for this bus.
>>
>> you can read the comment of 2c_bit_add_numbered_bus() at
>> drivers/i2c/i2c-core-base.c
> I didn't say it wasn't possible. It is not best practice. Grep
> i2c_bit_add_numbered_bus and see how many users there are.

i2c-gpio.c at drivers/i2c/busses/ just do the same thing.


+ nvidia,bpmp-bus-id: + $ref: /schemas/types.yaml#/definitions/uint32 + 
description: Indicates the I2C bus number this DT node represents, + as 
defined by the BPMP firmware.

> Even if the kernel allows specifying bus numbers,your Linux bus numbers don't
> belong in DT.

Again, Does does devicetree specification prohibit this?

Nvidia also put i2c bus number in the DT, we learn that from nvidia. [1][2]

[1] Documentation/devicetree/bindings/i2c/nvidia,tegra186-bpmp-i2c.yaml

[2] 
https://lore.kernel.org/all/20211208143306.534700-1-thierry.reding@gmail.com/


>
> Rob

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-26 10:04                 ` Sui Jingfeng
@ 2022-03-28 14:04                   ` Rob Herring
  2022-03-29  2:02                     ` Sui Jingfeng
  0 siblings, 1 reply; 48+ messages in thread
From: Rob Herring @ 2022-03-28 14:04 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Qing Zhang, David Airlie, Jiaxun Yang, linux-kernel,
	Sam Ravnborg, Krzysztof Kozlowski, Dan Carpenter, devicetree,
	suijingfeng, Thomas Zimmermann, Roland Scheidegger,
	Andrey Zhizhikin, dri-devel, Thomas Bogendoerfer, linux-mips,
	David S . Miller

On Sat, Mar 26, 2022 at 06:04:46PM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/24 21:26, Rob Herring wrote:
> > On Thu, Mar 24, 2022 at 09:48:19AM +0800, Sui Jingfeng wrote:
> > > On 2022/3/23 21:03, Rob Herring wrote:
> > > > On Wed, Mar 23, 2022 at 11:38:55AM +0800, Sui Jingfeng wrote:
> > > > > On 2022/3/23 04:55, Rob Herring wrote:
> > > > > > On Tue, Mar 22, 2022 at 10:33:45AM +0800, Sui Jingfeng wrote:
> > > > > > > On 2022/3/22 07:20, Rob Herring wrote:
> > > > > > > > On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
> > > > > > > > > From: suijingfeng <suijingfeng@loongson.cn>
> > > > > > > > > 
> > > > > > > > Needs a commit message.
> > > > > > > > 
> > > > > > > > > Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> > > > > > > > > Signed-off-by: Sui Jingfeng <15330273260@189.cn>
> > > > > > > > Same person? Don't need both emails.
> > > > > > > Yes,  suijingfeng@loongson.cn is my company's email. But it can not be used
> > > > > > > to send patches to dri-devel,
> > > > > > > 
> > > > > > > when send patches with this email, the patch will not be shown on patch
> > > > > > > works.
> > > > > > > 
> > > > > > > Emails  are either blocked or got  rejected  by loongson's mail server.  It
> > > > > > > can only receive emails
> > > > > > > 
> > > > > > > from you and other people, but not dri-devel. so have to use my personal
> > > > > > > email(15330273260@189.cn) to send patches.
> > > > > > > 
> > > > > > > > > ---
> > > > > > > > >      .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
> > > > > > > > >      1 file changed, 230 insertions(+)
> > > > > > > > >      create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > > > > > 
> > > > > > > > > diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > > > > > new file mode 100644
> > > > > > > > > index 000000000000..7be63346289e
> > > > > > > > > --- /dev/null
> > > > > > > > > +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > > > > > @@ -0,0 +1,230 @@
> > > > > > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > > > > > > +%YAML 1.2
> > > > > > > > > +---
> > > > > > > > > +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
> > > > > > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > > > > > +
> > > > > > > > > +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
> > > > > > > > > +
> > > > > > > > > +maintainers:
> > > > > > > > > +  - Sui Jingfeng <suijingfeng@loongson.cn>
> > > > > > > > > +
> > > > > > > > > +description: |+
> > > > > > > > > +
> > > > > > > > > +  Loongson display controllers are simple which require scanout buffers
> > > > > > > > > +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
> > > > > > > > > +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
> > > > > > > > > +  with a dedicated video RAM which is 64MB or more, precise size can be
> > > > > > > > > +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
> > > > > > > > > +  chip.
> > > > > > > > > +
> > > > > > > > > +  LSDC has two display pipes, each way has a DVO interface which provide
> > > > > > > > > +  RGB888 signals, vertical & horizontal synchronisations, data enable and
> > > > > > > > > +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
> > > > > > > > > +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
> > > > > > > > > +
> > > > > > > > > +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
> > > > > > > > > +  located at the DC register space. They are used to emulate two way i2c,
> > > > > > > > > +  One for DVO0, another for DVO1.
> > > > > > > > > +
> > > > > > > > > +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
> > > > > > > > > +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
> > > > > > > > > +
> > > > > > > > > +  LSDC's display pipeline have several components as below description,
> > > > > > > > > +
> > > > > > > > > +  The display controller in LS7A1000:
> > > > > > > > > +     ___________________                                     _________
> > > > > > > > > +    |            -------|                                   |         |
> > > > > > > > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > > > > > > > +    |  _   _     -------|        ^             ^            |_________|
> > > > > > > > > +    | | | | |    -------|        |             |
> > > > > > > > > +    | |_| |_|    | i2c0 <--------+-------------+
> > > > > > > > > +    |            -------|
> > > > > > > > > +    |   DC IN LS7A1000  |
> > > > > > > > > +    |  _   _     -------|
> > > > > > > > > +    | | | | |    | i2c1 <--------+-------------+
> > > > > > > > > +    | |_| |_|    -------|        |             |             _________
> > > > > > > > > +    |            -------|        |             |            |         |
> > > > > > > > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > > > > > > > +    |            -------|                                   |_________|
> > > > > > > > > +    |___________________|
> > > > > > > > > +
> > > > > > > > > +  Simple usage of LS7A1000 with LS3A4000 CPU:
> > > > > > > > > +
> > > > > > > > > +    +------+            +-----------------------------------+
> > > > > > > > > +    | DDR4 |            |  +-------------------+            |
> > > > > > > > > +    +------+            |  | PCIe Root complex |   LS7A1000 |
> > > > > > > > > +       || MC0           |  +--++---------++----+            |
> > > > > > > > > +  +----------+  HT 3.0  |     ||         ||                 |
> > > > > > > > > +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
> > > > > > > > > +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
> > > > > > > > > +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
> > > > > > > > > +       || MC1           +---------------|--|----------------+
> > > > > > > > > +    +------+                            |  |
> > > > > > > > > +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
> > > > > > > > > +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
> > > > > > > > > +                      +-------+                      +------+
> > > > > > > > > +
> > > > > > > > > +  The display controller in LS2K1000/LS2K0500:
> > > > > > > > > +     ___________________                                     _________
> > > > > > > > > +    |            -------|                                   |         |
> > > > > > > > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > > > > > > > +    |  _   _     -------|        ^              ^           |_________|
> > > > > > > > > +    | | | | |           |        |              |
> > > > > > > > > +    | |_| |_|           |     +------+          |
> > > > > > > > > +    |                   <---->| i2c0 |<---------+
> > > > > > > > > +    |   DC IN LS2K1000  |     +------+
> > > > > > > > > +    |  _   _            |     +------+
> > > > > > > > > +    | | | | |           <---->| i2c1 |----------+
> > > > > > > > > +    | |_| |_|           |     +------+          |            _________
> > > > > > > > > +    |            -------|        |              |           |         |
> > > > > > > > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > > > > > > > +    |            -------|                                   |_________|
> > > > > > > > > +    |___________________|
> > > > > > > > > +
> > > > > > > > > +properties:
> > > > > > > > > +  $nodename:
> > > > > > > > > +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
> > > > > > > > > +
> > > > > > > > > +  compatible:
> > > > > > > > > +    oneOf:
> > > > > > > > > +      - items:
> > > > > > > > > +          - enum:
> > > > > > > > > +              - loongson,ls7a1000-dc
> > > > > > > > > +              - loongson,ls2k1000-dc
> > > > > > > > > +              - loongson,ls2k0500-dc
> > > > > > > > > +
> > > > > > > > > +  reg:
> > > > > > > > > +    maxItems: 1
> > > > > > > > > +
> > > > > > > > > +  interrupts:
> > > > > > > > > +    maxItems: 1
> > > > > > > > > +
> > > > > > > > > +  '#address-cells':
> > > > > > > > > +    const: 1
> > > > > > > > > +
> > > > > > > > > +  '#size-cells':
> > > > > > > > > +    const: 0
> > > > > > > > > +
> > > > > > > > > +  i2c-gpio@0:
> > > > > > > > > +    description: |
> > > > > > > > > +      Built-in GPIO emulate i2c exported for external display bridge
> > > > > > > > If you have i2c-gpio, that belongs at the DT top-level, not here.
> > > > > > > > 
> > > > > > > > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > > > > > > > +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
> > > > > > > > No, there's a defined i2c-gpio compatible already.
> > > > > > > This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
> > > > > > > By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
> > > > > > > adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
> > > > > > > LSDC register space, not general purpose GPIOs with separate control register resource.
> > > > > > > So i think it is the child node of display-controller@6,1, it belongs to LSDC.
> > > > > > > It seems that put it at the DT top-level break the hierarchy and relationship.
> > > > > > Okay, I see. Then just 'i2c' for the node names. You need a reference to
> > > > > > i2c-controller.yaml for these nodes too.
> > > > > > 
> > > > > > The compatible should not have an index in it.
> > > > > OK, i will fix this at the next version. thanks.
> > > > > > > > > +      used to specify a I2c adapter bus number, if you don't specify one
> > > > > > > > > +      i2c driver core will dynamically assign a bus number. Please specify
> > > > > > > > Bus numbers are a linux detail not relevant to DT binding.
> > > > > > > > 
> > > > > > > > > +      it only when its bus number matters. Bus number greater than 6 is safe
> > > > > > > > > +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
> > > > > > > > > +
> > > > > > > > > +  i2c-gpio@1:
> > > > > > > > > +    description: |
> > > > > > > > > +      Built-in GPIO emulate i2c exported for external display bridge
> > > > > > > > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > > > > > > > +      only. Its compatible must be lsdc,i2c-gpio-1.
> > > > > > > > > +
> > > > > > > > > +  ports:
> > > > > > > > > +    $ref: /schemas/graph.yaml#/properties/ports
> > > > > > > > > +
> > > > > > > > > +    properties:
> > > > > > > > > +      port@0:
> > > > > > > > > +        $ref: /schemas/graph.yaml#/properties/port
> > > > > > > > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > > > > > > > +
> > > > > > > > > +      port@1:
> > > > > > > > > +        $ref: /schemas/graph.yaml#/properties/port
> > > > > > > > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > > > > > > > +
> > > > > > > > > +    required:
> > > > > > > > > +      - port@0
> > > > > > > > > +      - port@1
> > > > > > > > > +
> > > > > > > > > +required:
> > > > > > > > > +  - compatible
> > > > > > > > > +  - reg
> > > > > > > > > +  - interrupts
> > > > > > > > > +  - ports
> > > > > > > > > +
> > > > > > > > > +additionalProperties: false
> > > > > > > > > +
> > > > > > > > > +examples:
> > > > > > > > > +  - |
> > > > > > > > > +    #include <dt-bindings/interrupt-controller/irq.h>
> > > > > > > > > +    bus {
> > > > > > > > > +
> > > > > > > > > +        #address-cells = <3>;
> > > > > > > > > +        #size-cells = <2>;
> > > > > > > > > +        #interrupt-cells = <2>;
> > > > > > > > > +
> > > > > > > > > +        display-controller@6,1 {
> > > > > > > > > +            compatible = "loongson,ls7a1000-dc";
> > > > > > > > > +            reg = <0x3100 0x0 0x0 0x0 0x0>;
> > > > > > > > > +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
> > > > > > > > > +
> > > > > > > > > +            #address-cells = <1>;
> > > > > > > > > +            #size-cells = <0>;
> > > > > > > > > +
> > > > > > > > > +            i2c-gpio@0 {
> > > > > > > > > +                compatible = "lsdc,i2c-gpio-0";
> > > > > > > > > +                reg = <6>;
> > > > > > 'reg' needs to be documented with some description of what 6 and 7
> > > > > > represent. If they are the control register offset, then make the
> > > > > > address translatable (use 'ranges' and define the size).
> > > > > By design, the reg property is used to specify a I2c adapter bus number,
> > > > > if we don't specify one, i2c driver core will dynamically assign a bus number.
> > > > > then the nr of the i2c adapter will started from 0. I want is start from 6
> > > > > to avoid potential conflict feature hardware I2C driver.
> > > > > 
> > > > > Because LS7A1000 bridge chip have 6 hardware I2C controller integrated,
> > > > > but its driver is not up-streamed yet. By default these hardware I2C controller's
> > > > > nr is started from 0.
> > > > Linux's numbering doesn't belong in DT. So no, you can't use 'reg' in
> > > > that way.
> > > Then,  can i use something like lsdc,nr = <6> ?
> > > > > Even through i2c driver core can dynamically generate a number, i still want it
> > > > > to be fixed and keep consistent and explicit. That is, i2c6 is for display pipe 0,
> > > > > i2c7 is for display pipe 1. This follow the convention and flexible enough.
> > > > You may want that, but that is not how the kernel works. Specific
> > > > numbers are not guaranteed. I'm sure you've seen this for disks, network
> > > > interfaces, etc.
> > > > 
> > > > Rob
> > > 2c_bit_add_numbered_bus() will guarantee it for you as long as If no devices
> > > have pre-been declared for this bus.
> > > 
> > > you can read the comment of 2c_bit_add_numbered_bus() at
> > > drivers/i2c/i2c-core-base.c
> > I didn't say it wasn't possible. It is not best practice. Grep
> > i2c_bit_add_numbered_bus and see how many users there are.
> 
> i2c-gpio.c at drivers/i2c/busses/ just do the same thing.

No, the id for i2c-gpio nodes (any DT node without 'reg') will be -1 
which means dynamically assigned.


> + nvidia,bpmp-bus-id: + $ref: /schemas/types.yaml#/definitions/uint32 +
> description: Indicates the I2C bus number this DT node represents, + as
> defined by the BPMP firmware.

The key difference is the numbering is defined by the BPMP firmware.


> > Even if the kernel allows specifying bus numbers,your Linux bus numbers don't
> > belong in DT.
> 
> Again, Does does devicetree specification prohibit this?

No. The spec is not the last word on what's allowed or not. Lots of 
patterns exist already which we can't change, but that doesn't mean they 
should be copied by new users.

Rob

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-28 14:04                   ` Rob Herring
@ 2022-03-29  2:02                     ` Sui Jingfeng
  2022-03-29 13:24                       ` Rob Herring
  0 siblings, 1 reply; 48+ messages in thread
From: Sui Jingfeng @ 2022-03-29  2:02 UTC (permalink / raw)
  To: Rob Herring
  Cc: Qing Zhang, David Airlie, Jiaxun Yang, linux-kernel,
	Sam Ravnborg, Krzysztof Kozlowski, Dan Carpenter, devicetree,
	suijingfeng, Thomas Zimmermann, Roland Scheidegger,
	Andrey Zhizhikin, dri-devel, Thomas Bogendoerfer, linux-mips,
	David S . Miller


On 2022/3/28 22:04, Rob Herring wrote:
> On Sat, Mar 26, 2022 at 06:04:46PM +0800, Sui Jingfeng wrote:
>> On 2022/3/24 21:26, Rob Herring wrote:
>>> On Thu, Mar 24, 2022 at 09:48:19AM +0800, Sui Jingfeng wrote:
>>>> On 2022/3/23 21:03, Rob Herring wrote:
>>>>> On Wed, Mar 23, 2022 at 11:38:55AM +0800, Sui Jingfeng wrote:
>>>>>> On 2022/3/23 04:55, Rob Herring wrote:
>>>>>>> On Tue, Mar 22, 2022 at 10:33:45AM +0800, Sui Jingfeng wrote:
>>>>>>>> On 2022/3/22 07:20, Rob Herring wrote:
>>>>>>>>> On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
>>>>>>>>>> From: suijingfeng <suijingfeng@loongson.cn>
>>>>>>>>>>
>>>>>>>>> Needs a commit message.
>>>>>>>>>
>>>>>>>>>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>>>>>>>>>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>>>>>>>>> Same person? Don't need both emails.
>>>>>>>> Yes,  suijingfeng@loongson.cn is my company's email. But it can not be used
>>>>>>>> to send patches to dri-devel,
>>>>>>>>
>>>>>>>> when send patches with this email, the patch will not be shown on patch
>>>>>>>> works.
>>>>>>>>
>>>>>>>> Emails  are either blocked or got  rejected  by loongson's mail server.  It
>>>>>>>> can only receive emails
>>>>>>>>
>>>>>>>> from you and other people, but not dri-devel. so have to use my personal
>>>>>>>> email(15330273260@189.cn) to send patches.
>>>>>>>>
>>>>>>>>>> ---
>>>>>>>>>>       .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
>>>>>>>>>>       1 file changed, 230 insertions(+)
>>>>>>>>>>       create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>>>>>>>
>>>>>>>>>> diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>>>>>>> new file mode 100644
>>>>>>>>>> index 000000000000..7be63346289e
>>>>>>>>>> --- /dev/null
>>>>>>>>>> +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
>>>>>>>>>> @@ -0,0 +1,230 @@
>>>>>>>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>>>>>>>>> +%YAML 1.2
>>>>>>>>>> +---
>>>>>>>>>> +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
>>>>>>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>>>>>>> +
>>>>>>>>>> +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
>>>>>>>>>> +
>>>>>>>>>> +maintainers:
>>>>>>>>>> +  - Sui Jingfeng <suijingfeng@loongson.cn>
>>>>>>>>>> +
>>>>>>>>>> +description: |+
>>>>>>>>>> +
>>>>>>>>>> +  Loongson display controllers are simple which require scanout buffers
>>>>>>>>>> +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
>>>>>>>>>> +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
>>>>>>>>>> +  with a dedicated video RAM which is 64MB or more, precise size can be
>>>>>>>>>> +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
>>>>>>>>>> +  chip.
>>>>>>>>>> +
>>>>>>>>>> +  LSDC has two display pipes, each way has a DVO interface which provide
>>>>>>>>>> +  RGB888 signals, vertical & horizontal synchronisations, data enable and
>>>>>>>>>> +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
>>>>>>>>>> +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
>>>>>>>>>> +
>>>>>>>>>> +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
>>>>>>>>>> +  located at the DC register space. They are used to emulate two way i2c,
>>>>>>>>>> +  One for DVO0, another for DVO1.
>>>>>>>>>> +
>>>>>>>>>> +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
>>>>>>>>>> +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
>>>>>>>>>> +
>>>>>>>>>> +  LSDC's display pipeline have several components as below description,
>>>>>>>>>> +
>>>>>>>>>> +  The display controller in LS7A1000:
>>>>>>>>>> +     ___________________                                     _________
>>>>>>>>>> +    |            -------|                                   |         |
>>>>>>>>>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>>>>>>>>>> +    |  _   _     -------|        ^             ^            |_________|
>>>>>>>>>> +    | | | | |    -------|        |             |
>>>>>>>>>> +    | |_| |_|    | i2c0 <--------+-------------+
>>>>>>>>>> +    |            -------|
>>>>>>>>>> +    |   DC IN LS7A1000  |
>>>>>>>>>> +    |  _   _     -------|
>>>>>>>>>> +    | | | | |    | i2c1 <--------+-------------+
>>>>>>>>>> +    | |_| |_|    -------|        |             |             _________
>>>>>>>>>> +    |            -------|        |             |            |         |
>>>>>>>>>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>>>>>>>>>> +    |            -------|                                   |_________|
>>>>>>>>>> +    |___________________|
>>>>>>>>>> +
>>>>>>>>>> +  Simple usage of LS7A1000 with LS3A4000 CPU:
>>>>>>>>>> +
>>>>>>>>>> +    +------+            +-----------------------------------+
>>>>>>>>>> +    | DDR4 |            |  +-------------------+            |
>>>>>>>>>> +    +------+            |  | PCIe Root complex |   LS7A1000 |
>>>>>>>>>> +       || MC0           |  +--++---------++----+            |
>>>>>>>>>> +  +----------+  HT 3.0  |     ||         ||                 |
>>>>>>>>>> +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>>>>>>>>>> +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>>>>>>>>>> +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
>>>>>>>>>> +       || MC1           +---------------|--|----------------+
>>>>>>>>>> +    +------+                            |  |
>>>>>>>>>> +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>>>>>>>>>> +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>>>>>>>>>> +                      +-------+                      +------+
>>>>>>>>>> +
>>>>>>>>>> +  The display controller in LS2K1000/LS2K0500:
>>>>>>>>>> +     ___________________                                     _________
>>>>>>>>>> +    |            -------|                                   |         |
>>>>>>>>>> +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
>>>>>>>>>> +    |  _   _     -------|        ^              ^           |_________|
>>>>>>>>>> +    | | | | |           |        |              |
>>>>>>>>>> +    | |_| |_|           |     +------+          |
>>>>>>>>>> +    |                   <---->| i2c0 |<---------+
>>>>>>>>>> +    |   DC IN LS2K1000  |     +------+
>>>>>>>>>> +    |  _   _            |     +------+
>>>>>>>>>> +    | | | | |           <---->| i2c1 |----------+
>>>>>>>>>> +    | |_| |_|           |     +------+          |            _________
>>>>>>>>>> +    |            -------|        |              |           |         |
>>>>>>>>>> +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
>>>>>>>>>> +    |            -------|                                   |_________|
>>>>>>>>>> +    |___________________|
>>>>>>>>>> +
>>>>>>>>>> +properties:
>>>>>>>>>> +  $nodename:
>>>>>>>>>> +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
>>>>>>>>>> +
>>>>>>>>>> +  compatible:
>>>>>>>>>> +    oneOf:
>>>>>>>>>> +      - items:
>>>>>>>>>> +          - enum:
>>>>>>>>>> +              - loongson,ls7a1000-dc
>>>>>>>>>> +              - loongson,ls2k1000-dc
>>>>>>>>>> +              - loongson,ls2k0500-dc
>>>>>>>>>> +
>>>>>>>>>> +  reg:
>>>>>>>>>> +    maxItems: 1
>>>>>>>>>> +
>>>>>>>>>> +  interrupts:
>>>>>>>>>> +    maxItems: 1
>>>>>>>>>> +
>>>>>>>>>> +  '#address-cells':
>>>>>>>>>> +    const: 1
>>>>>>>>>> +
>>>>>>>>>> +  '#size-cells':
>>>>>>>>>> +    const: 0
>>>>>>>>>> +
>>>>>>>>>> +  i2c-gpio@0:
>>>>>>>>>> +    description: |
>>>>>>>>>> +      Built-in GPIO emulate i2c exported for external display bridge
>>>>>>>>> If you have i2c-gpio, that belongs at the DT top-level, not here.
>>>>>>>>>
>>>>>>>>>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>>>>>>>>>> +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
>>>>>>>>> No, there's a defined i2c-gpio compatible already.
>>>>>>>> This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
>>>>>>>> By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
>>>>>>>> adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
>>>>>>>> LSDC register space, not general purpose GPIOs with separate control register resource.
>>>>>>>> So i think it is the child node of display-controller@6,1, it belongs to LSDC.
>>>>>>>> It seems that put it at the DT top-level break the hierarchy and relationship.
>>>>>>> Okay, I see. Then just 'i2c' for the node names. You need a reference to
>>>>>>> i2c-controller.yaml for these nodes too.
>>>>>>>
>>>>>>> The compatible should not have an index in it.
>>>>>> OK, i will fix this at the next version. thanks.
>>>>>>>>>> +      used to specify a I2c adapter bus number, if you don't specify one
>>>>>>>>>> +      i2c driver core will dynamically assign a bus number. Please specify
>>>>>>>>> Bus numbers are a linux detail not relevant to DT binding.
>>>>>>>>>
>>>>>>>>>> +      it only when its bus number matters. Bus number greater than 6 is safe
>>>>>>>>>> +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
>>>>>>>>>> +
>>>>>>>>>> +  i2c-gpio@1:
>>>>>>>>>> +    description: |
>>>>>>>>>> +      Built-in GPIO emulate i2c exported for external display bridge
>>>>>>>>>> +      configuration, onitor detection and edid read back etc, for ls7a1000
>>>>>>>>>> +      only. Its compatible must be lsdc,i2c-gpio-1.
>>>>>>>>>> +
>>>>>>>>>> +  ports:
>>>>>>>>>> +    $ref: /schemas/graph.yaml#/properties/ports
>>>>>>>>>> +
>>>>>>>>>> +    properties:
>>>>>>>>>> +      port@0:
>>>>>>>>>> +        $ref: /schemas/graph.yaml#/properties/port
>>>>>>>>>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>>>>>>>>>> +
>>>>>>>>>> +      port@1:
>>>>>>>>>> +        $ref: /schemas/graph.yaml#/properties/port
>>>>>>>>>> +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
>>>>>>>>>> +
>>>>>>>>>> +    required:
>>>>>>>>>> +      - port@0
>>>>>>>>>> +      - port@1
>>>>>>>>>> +
>>>>>>>>>> +required:
>>>>>>>>>> +  - compatible
>>>>>>>>>> +  - reg
>>>>>>>>>> +  - interrupts
>>>>>>>>>> +  - ports
>>>>>>>>>> +
>>>>>>>>>> +additionalProperties: false
>>>>>>>>>> +
>>>>>>>>>> +examples:
>>>>>>>>>> +  - |
>>>>>>>>>> +    #include <dt-bindings/interrupt-controller/irq.h>
>>>>>>>>>> +    bus {
>>>>>>>>>> +
>>>>>>>>>> +        #address-cells = <3>;
>>>>>>>>>> +        #size-cells = <2>;
>>>>>>>>>> +        #interrupt-cells = <2>;
>>>>>>>>>> +
>>>>>>>>>> +        display-controller@6,1 {
>>>>>>>>>> +            compatible = "loongson,ls7a1000-dc";
>>>>>>>>>> +            reg = <0x3100 0x0 0x0 0x0 0x0>;
>>>>>>>>>> +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
>>>>>>>>>> +
>>>>>>>>>> +            #address-cells = <1>;
>>>>>>>>>> +            #size-cells = <0>;
>>>>>>>>>> +
>>>>>>>>>> +            i2c-gpio@0 {
>>>>>>>>>> +                compatible = "lsdc,i2c-gpio-0";
>>>>>>>>>> +                reg = <6>;
>>>>>>> 'reg' needs to be documented with some description of what 6 and 7
>>>>>>> represent. If they are the control register offset, then make the
>>>>>>> address translatable (use 'ranges' and define the size).
>>>>>> By design, the reg property is used to specify a I2c adapter bus number,
>>>>>> if we don't specify one, i2c driver core will dynamically assign a bus number.
>>>>>> then the nr of the i2c adapter will started from 0. I want is start from 6
>>>>>> to avoid potential conflict feature hardware I2C driver.
>>>>>>
>>>>>> Because LS7A1000 bridge chip have 6 hardware I2C controller integrated,
>>>>>> but its driver is not up-streamed yet. By default these hardware I2C controller's
>>>>>> nr is started from 0.
>>>>> Linux's numbering doesn't belong in DT. So no, you can't use 'reg' in
>>>>> that way.
>>>> Then,  can i use something like lsdc,nr = <6> ?
>>>>>> Even through i2c driver core can dynamically generate a number, i still want it
>>>>>> to be fixed and keep consistent and explicit. That is, i2c6 is for display pipe 0,
>>>>>> i2c7 is for display pipe 1. This follow the convention and flexible enough.
>>>>> You may want that, but that is not how the kernel works. Specific
>>>>> numbers are not guaranteed. I'm sure you've seen this for disks, network
>>>>> interfaces, etc.
>>>>>
>>>>> Rob
>>>> 2c_bit_add_numbered_bus() will guarantee it for you as long as If no devices
>>>> have pre-been declared for this bus.
>>>>
>>>> you can read the comment of 2c_bit_add_numbered_bus() at
>>>> drivers/i2c/i2c-core-base.c
>>> I didn't say it wasn't possible. It is not best practice. Grep
>>> i2c_bit_add_numbered_bus and see how many users there are.
>> i2c-gpio.c at drivers/i2c/busses/ just do the same thing.
> No, the id for i2c-gpio nodes (any DT node without 'reg') will be -1
> which means dynamically assigned.
>
>
>> + nvidia,bpmp-bus-id: + $ref: /schemas/types.yaml#/definitions/uint32 +
>> description: Indicates the I2C bus number this DT node represents, + as
>> defined by the BPMP firmware.
> The key difference is the numbering is defined by the BPMP firmware.
>
Bus numbers are a linux detail, I am not sure it is relevant to BPMP firmware.
and BPMP firmware is not relevant here.

The point is you applied that patch, you are admit the fact that bus numbers
could be in DT.

>>> Even if the kernel allows specifying bus numbers,your Linux bus numbers don't
>>> belong in DT.
>> Again, Does does devicetree specification prohibit this?
> No. The spec is not the last word on what's allowed or not. Lots of
> patterns exist already which we can't change, but that doesn't mean they
> should be copied by new users.
>
> Rob

We develop that part by our own, only find that there are someone do the 
same thing when it got push back.

We believe that it is very flexible actually, anyway if you still don't 
change you mind we can rewrite it.

I have resend my patches,  see it at 
https://patchwork.freedesktop.org/series/101843/

Please take spare time to review it if you would like, thanks you.


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller
  2022-03-29  2:02                     ` Sui Jingfeng
@ 2022-03-29 13:24                       ` Rob Herring
  0 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2022-03-29 13:24 UTC (permalink / raw)
  To: Sui Jingfeng
  Cc: Qing Zhang, David Airlie, Jiaxun Yang, linux-kernel,
	Sam Ravnborg, Krzysztof Kozlowski, Dan Carpenter, devicetree,
	suijingfeng, Thomas Zimmermann, Roland Scheidegger,
	Andrey Zhizhikin, dri-devel, Thomas Bogendoerfer, linux-mips,
	David S . Miller

On Tue, Mar 29, 2022 at 10:02:11AM +0800, Sui Jingfeng wrote:
> 
> On 2022/3/28 22:04, Rob Herring wrote:
> > On Sat, Mar 26, 2022 at 06:04:46PM +0800, Sui Jingfeng wrote:
> > > On 2022/3/24 21:26, Rob Herring wrote:
> > > > On Thu, Mar 24, 2022 at 09:48:19AM +0800, Sui Jingfeng wrote:
> > > > > On 2022/3/23 21:03, Rob Herring wrote:
> > > > > > On Wed, Mar 23, 2022 at 11:38:55AM +0800, Sui Jingfeng wrote:
> > > > > > > On 2022/3/23 04:55, Rob Herring wrote:
> > > > > > > > On Tue, Mar 22, 2022 at 10:33:45AM +0800, Sui Jingfeng wrote:
> > > > > > > > > On 2022/3/22 07:20, Rob Herring wrote:
> > > > > > > > > > On Tue, Mar 22, 2022 at 12:29:14AM +0800, Sui Jingfeng wrote:
> > > > > > > > > > > From: suijingfeng <suijingfeng@loongson.cn>
> > > > > > > > > > > 
> > > > > > > > > > Needs a commit message.
> > > > > > > > > > 
> > > > > > > > > > > Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
> > > > > > > > > > > Signed-off-by: Sui Jingfeng <15330273260@189.cn>
> > > > > > > > > > Same person? Don't need both emails.
> > > > > > > > > Yes,  suijingfeng@loongson.cn is my company's email. But it can not be used
> > > > > > > > > to send patches to dri-devel,
> > > > > > > > > 
> > > > > > > > > when send patches with this email, the patch will not be shown on patch
> > > > > > > > > works.
> > > > > > > > > 
> > > > > > > > > Emails  are either blocked or got  rejected  by loongson's mail server.  It
> > > > > > > > > can only receive emails
> > > > > > > > > 
> > > > > > > > > from you and other people, but not dri-devel. so have to use my personal
> > > > > > > > > email(15330273260@189.cn) to send patches.
> > > > > > > > > 
> > > > > > > > > > > ---
> > > > > > > > > > >       .../loongson/loongson,display-controller.yaml | 230 ++++++++++++++++++
> > > > > > > > > > >       1 file changed, 230 insertions(+)
> > > > > > > > > > >       create mode 100644 Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > > > > > > > 
> > > > > > > > > > > diff --git a/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > > > > > > > new file mode 100644
> > > > > > > > > > > index 000000000000..7be63346289e
> > > > > > > > > > > --- /dev/null
> > > > > > > > > > > +++ b/Documentation/devicetree/bindings/display/loongson/loongson,display-controller.yaml
> > > > > > > > > > > @@ -0,0 +1,230 @@
> > > > > > > > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > > > > > > > > +%YAML 1.2
> > > > > > > > > > > +---
> > > > > > > > > > > +$id: http://devicetree.org/schemas/display/loongson/loongson,display-controller.yaml#
> > > > > > > > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > > > > > > > +
> > > > > > > > > > > +title: Loongson LS7A1000/LS2K1000/LS2K0500 Display Controller Device Tree Bindings
> > > > > > > > > > > +
> > > > > > > > > > > +maintainers:
> > > > > > > > > > > +  - Sui Jingfeng <suijingfeng@loongson.cn>
> > > > > > > > > > > +
> > > > > > > > > > > +description: |+
> > > > > > > > > > > +
> > > > > > > > > > > +  Loongson display controllers are simple which require scanout buffers
> > > > > > > > > > > +  to be physically contiguous. LS2K1000/LS2K0500 is a SOC, only system
> > > > > > > > > > > +  memory is available. LS7A1000/LS7A2000 is bridge chip which is equipped
> > > > > > > > > > > +  with a dedicated video RAM which is 64MB or more, precise size can be
> > > > > > > > > > > +  read from the PCI BAR 2 of the GPU device(0x0014:0x7A15) in the bridge
> > > > > > > > > > > +  chip.
> > > > > > > > > > > +
> > > > > > > > > > > +  LSDC has two display pipes, each way has a DVO interface which provide
> > > > > > > > > > > +  RGB888 signals, vertical & horizontal synchronisations, data enable and
> > > > > > > > > > > +  the pixel clock. LSDC has two CRTC, each CRTC is able to scanout from
> > > > > > > > > > > +  1920x1080 resolution at 60Hz. Each CRTC has two FB address registers.
> > > > > > > > > > > +
> > > > > > > > > > > +  For LS7A1000, there are 4 dedicated GPIOs whose control register is
> > > > > > > > > > > +  located at the DC register space. They are used to emulate two way i2c,
> > > > > > > > > > > +  One for DVO0, another for DVO1.
> > > > > > > > > > > +
> > > > > > > > > > > +  LS2K1000 and LS2K0500 SoC grab i2c adapter from other module, either
> > > > > > > > > > > +  general purpose GPIO emulated i2c or hardware i2c in the SoC.
> > > > > > > > > > > +
> > > > > > > > > > > +  LSDC's display pipeline have several components as below description,
> > > > > > > > > > > +
> > > > > > > > > > > +  The display controller in LS7A1000:
> > > > > > > > > > > +     ___________________                                     _________
> > > > > > > > > > > +    |            -------|                                   |         |
> > > > > > > > > > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > > > > > > > > > +    |  _   _     -------|        ^             ^            |_________|
> > > > > > > > > > > +    | | | | |    -------|        |             |
> > > > > > > > > > > +    | |_| |_|    | i2c0 <--------+-------------+
> > > > > > > > > > > +    |            -------|
> > > > > > > > > > > +    |   DC IN LS7A1000  |
> > > > > > > > > > > +    |  _   _     -------|
> > > > > > > > > > > +    | | | | |    | i2c1 <--------+-------------+
> > > > > > > > > > > +    | |_| |_|    -------|        |             |             _________
> > > > > > > > > > > +    |            -------|        |             |            |         |
> > > > > > > > > > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > > > > > > > > > +    |            -------|                                   |_________|
> > > > > > > > > > > +    |___________________|
> > > > > > > > > > > +
> > > > > > > > > > > +  Simple usage of LS7A1000 with LS3A4000 CPU:
> > > > > > > > > > > +
> > > > > > > > > > > +    +------+            +-----------------------------------+
> > > > > > > > > > > +    | DDR4 |            |  +-------------------+            |
> > > > > > > > > > > +    +------+            |  | PCIe Root complex |   LS7A1000 |
> > > > > > > > > > > +       || MC0           |  +--++---------++----+            |
> > > > > > > > > > > +  +----------+  HT 3.0  |     ||         ||                 |
> > > > > > > > > > > +  | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
> > > > > > > > > > > +  |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
> > > > > > > > > > > +  +----------+          | +--------+  +-+--+-+    +---------+   +------+
> > > > > > > > > > > +       || MC1           +---------------|--|----------------+
> > > > > > > > > > > +    +------+                            |  |
> > > > > > > > > > > +    | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
> > > > > > > > > > > +    +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
> > > > > > > > > > > +                      +-------+                      +------+
> > > > > > > > > > > +
> > > > > > > > > > > +  The display controller in LS2K1000/LS2K0500:
> > > > > > > > > > > +     ___________________                                     _________
> > > > > > > > > > > +    |            -------|                                   |         |
> > > > > > > > > > > +    |  CRTC0 --> | DVO0 ----> Encoder0 ---> Connector0 ---> | Monitor |
> > > > > > > > > > > +    |  _   _     -------|        ^              ^           |_________|
> > > > > > > > > > > +    | | | | |           |        |              |
> > > > > > > > > > > +    | |_| |_|           |     +------+          |
> > > > > > > > > > > +    |                   <---->| i2c0 |<---------+
> > > > > > > > > > > +    |   DC IN LS2K1000  |     +------+
> > > > > > > > > > > +    |  _   _            |     +------+
> > > > > > > > > > > +    | | | | |           <---->| i2c1 |----------+
> > > > > > > > > > > +    | |_| |_|           |     +------+          |            _________
> > > > > > > > > > > +    |            -------|        |              |           |         |
> > > > > > > > > > > +    |  CRTC1 --> | DVO1 ----> Encoder1 ---> Connector1 ---> |  Panel  |
> > > > > > > > > > > +    |            -------|                                   |_________|
> > > > > > > > > > > +    |___________________|
> > > > > > > > > > > +
> > > > > > > > > > > +properties:
> > > > > > > > > > > +  $nodename:
> > > > > > > > > > > +    pattern: "^display-controller@[0-9a-f],[0-9a-f]$"
> > > > > > > > > > > +
> > > > > > > > > > > +  compatible:
> > > > > > > > > > > +    oneOf:
> > > > > > > > > > > +      - items:
> > > > > > > > > > > +          - enum:
> > > > > > > > > > > +              - loongson,ls7a1000-dc
> > > > > > > > > > > +              - loongson,ls2k1000-dc
> > > > > > > > > > > +              - loongson,ls2k0500-dc
> > > > > > > > > > > +
> > > > > > > > > > > +  reg:
> > > > > > > > > > > +    maxItems: 1
> > > > > > > > > > > +
> > > > > > > > > > > +  interrupts:
> > > > > > > > > > > +    maxItems: 1
> > > > > > > > > > > +
> > > > > > > > > > > +  '#address-cells':
> > > > > > > > > > > +    const: 1
> > > > > > > > > > > +
> > > > > > > > > > > +  '#size-cells':
> > > > > > > > > > > +    const: 0
> > > > > > > > > > > +
> > > > > > > > > > > +  i2c-gpio@0:
> > > > > > > > > > > +    description: |
> > > > > > > > > > > +      Built-in GPIO emulate i2c exported for external display bridge
> > > > > > > > > > If you have i2c-gpio, that belongs at the DT top-level, not here.
> > > > > > > > > > 
> > > > > > > > > > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > > > > > > > > > +      only. Its compatible must be lsdc,i2c-gpio-0. The reg property can be
> > > > > > > > > > No, there's a defined i2c-gpio compatible already.
> > > > > > > > > This is different from the i2c-gpio already defined under drivers/i2c/busses/i2c-gpio.c,
> > > > > > > > > By design, my i2c-gpio is vendor specific properties, lsdc device driver create the i2c
> > > > > > > > > adapter at runtime. These are 4 dedicated GPIOs whose control register is located at the
> > > > > > > > > LSDC register space, not general purpose GPIOs with separate control register resource.
> > > > > > > > > So i think it is the child node of display-controller@6,1, it belongs to LSDC.
> > > > > > > > > It seems that put it at the DT top-level break the hierarchy and relationship.
> > > > > > > > Okay, I see. Then just 'i2c' for the node names. You need a reference to
> > > > > > > > i2c-controller.yaml for these nodes too.
> > > > > > > > 
> > > > > > > > The compatible should not have an index in it.
> > > > > > > OK, i will fix this at the next version. thanks.
> > > > > > > > > > > +      used to specify a I2c adapter bus number, if you don't specify one
> > > > > > > > > > > +      i2c driver core will dynamically assign a bus number. Please specify
> > > > > > > > > > Bus numbers are a linux detail not relevant to DT binding.
> > > > > > > > > > 
> > > > > > > > > > > +      it only when its bus number matters. Bus number greater than 6 is safe
> > > > > > > > > > > +      because ls7a1000 bridge have 6 hardware I2C controller integrated.
> > > > > > > > > > > +
> > > > > > > > > > > +  i2c-gpio@1:
> > > > > > > > > > > +    description: |
> > > > > > > > > > > +      Built-in GPIO emulate i2c exported for external display bridge
> > > > > > > > > > > +      configuration, onitor detection and edid read back etc, for ls7a1000
> > > > > > > > > > > +      only. Its compatible must be lsdc,i2c-gpio-1.
> > > > > > > > > > > +
> > > > > > > > > > > +  ports:
> > > > > > > > > > > +    $ref: /schemas/graph.yaml#/properties/ports
> > > > > > > > > > > +
> > > > > > > > > > > +    properties:
> > > > > > > > > > > +      port@0:
> > > > > > > > > > > +        $ref: /schemas/graph.yaml#/properties/port
> > > > > > > > > > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > > > > > > > > > +
> > > > > > > > > > > +      port@1:
> > > > > > > > > > > +        $ref: /schemas/graph.yaml#/properties/port
> > > > > > > > > > > +        description: output port node connected with DPI panels or external encoders, with only one endpoint.
> > > > > > > > > > > +
> > > > > > > > > > > +    required:
> > > > > > > > > > > +      - port@0
> > > > > > > > > > > +      - port@1
> > > > > > > > > > > +
> > > > > > > > > > > +required:
> > > > > > > > > > > +  - compatible
> > > > > > > > > > > +  - reg
> > > > > > > > > > > +  - interrupts
> > > > > > > > > > > +  - ports
> > > > > > > > > > > +
> > > > > > > > > > > +additionalProperties: false
> > > > > > > > > > > +
> > > > > > > > > > > +examples:
> > > > > > > > > > > +  - |
> > > > > > > > > > > +    #include <dt-bindings/interrupt-controller/irq.h>
> > > > > > > > > > > +    bus {
> > > > > > > > > > > +
> > > > > > > > > > > +        #address-cells = <3>;
> > > > > > > > > > > +        #size-cells = <2>;
> > > > > > > > > > > +        #interrupt-cells = <2>;
> > > > > > > > > > > +
> > > > > > > > > > > +        display-controller@6,1 {
> > > > > > > > > > > +            compatible = "loongson,ls7a1000-dc";
> > > > > > > > > > > +            reg = <0x3100 0x0 0x0 0x0 0x0>;
> > > > > > > > > > > +            interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
> > > > > > > > > > > +
> > > > > > > > > > > +            #address-cells = <1>;
> > > > > > > > > > > +            #size-cells = <0>;
> > > > > > > > > > > +
> > > > > > > > > > > +            i2c-gpio@0 {
> > > > > > > > > > > +                compatible = "lsdc,i2c-gpio-0";
> > > > > > > > > > > +                reg = <6>;
> > > > > > > > 'reg' needs to be documented with some description of what 6 and 7
> > > > > > > > represent. If they are the control register offset, then make the
> > > > > > > > address translatable (use 'ranges' and define the size).
> > > > > > > By design, the reg property is used to specify a I2c adapter bus number,
> > > > > > > if we don't specify one, i2c driver core will dynamically assign a bus number.
> > > > > > > then the nr of the i2c adapter will started from 0. I want is start from 6
> > > > > > > to avoid potential conflict feature hardware I2C driver.
> > > > > > > 
> > > > > > > Because LS7A1000 bridge chip have 6 hardware I2C controller integrated,
> > > > > > > but its driver is not up-streamed yet. By default these hardware I2C controller's
> > > > > > > nr is started from 0.
> > > > > > Linux's numbering doesn't belong in DT. So no, you can't use 'reg' in
> > > > > > that way.
> > > > > Then,  can i use something like lsdc,nr = <6> ?
> > > > > > > Even through i2c driver core can dynamically generate a number, i still want it
> > > > > > > to be fixed and keep consistent and explicit. That is, i2c6 is for display pipe 0,
> > > > > > > i2c7 is for display pipe 1. This follow the convention and flexible enough.
> > > > > > You may want that, but that is not how the kernel works. Specific
> > > > > > numbers are not guaranteed. I'm sure you've seen this for disks, network
> > > > > > interfaces, etc.
> > > > > > 
> > > > > > Rob
> > > > > 2c_bit_add_numbered_bus() will guarantee it for you as long as If no devices
> > > > > have pre-been declared for this bus.
> > > > > 
> > > > > you can read the comment of 2c_bit_add_numbered_bus() at
> > > > > drivers/i2c/i2c-core-base.c
> > > > I didn't say it wasn't possible. It is not best practice. Grep
> > > > i2c_bit_add_numbered_bus and see how many users there are.
> > > i2c-gpio.c at drivers/i2c/busses/ just do the same thing.
> > No, the id for i2c-gpio nodes (any DT node without 'reg') will be -1
> > which means dynamically assigned.
> > 
> > 
> > > + nvidia,bpmp-bus-id: + $ref: /schemas/types.yaml#/definitions/uint32 +
> > > description: Indicates the I2C bus number this DT node represents, + as
> > > defined by the BPMP firmware.
> > The key difference is the numbering is defined by the BPMP firmware.
> > 
> Bus numbers are a linux detail, I am not sure it is relevant to BPMP firmware.
> and BPMP firmware is not relevant here.
> 

Read the review of it[1]. The key part is this:

> +The BPMP firmware defines no single global name-/numbering-space for such
> +services. Put another way, the numbering scheme for I2C buses is distinct from
> +the numbering scheme for any other service the BPMP may provide (e.g. a future
> +hypothetical SPI bus service). As such, child device nodes will have no reg
> +property, and the BPMP node will have no #address-cells or #size-cells property.

> My understanding is that the I2C bus number is passed as part of the
> request to the BPMP firmware. Does that not count as addressing? Could
> we not represent that generically using a device tree hierarchy? I'm
> thinking something along these lines:


The bus numbers are NOT defined by Linux nor defined in the DT.

> The point is you applied that patch, you are admit the fact that bus numbers
> could be in DT.

That actually is not an argument for your patch. There are lots of 
things we accepted in the past that now will be rejected. This case 
however is not something that changed. You may still find examples as 
bindings didn't always get reviewed (very well).


> > > > Even if the kernel allows specifying bus numbers,your Linux bus numbers don't
> > > > belong in DT.
> > > Again, Does does devicetree specification prohibit this?
> > No. The spec is not the last word on what's allowed or not. Lots of
> > patterns exist already which we can't change, but that doesn't mean they
> > should be copied by new users.
> > 
> > Rob
> 
> We develop that part by our own, only find that there are someone do the
> same thing when it got push back.
> 
> We believe that it is very flexible actually, anyway if you still don't
> change you mind we can rewrite it.
> 
> I have resend my patches,  see it at
> https://patchwork.freedesktop.org/series/101843/

Don't send new versions when the discussion on the prior one is ongoing. 
Though in this case there is nothing more to discuss.

Rob

[1] https://lore.kernel.org/all/20160726100302.GE2433@ulmo.ba.sec/


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-23 13:11       ` Rob Herring
  2022-03-24  4:05         ` Sui Jingfeng
@ 2022-04-08  2:09         ` Sui Jingfeng
  1 sibling, 0 replies; 48+ messages in thread
From: Sui Jingfeng @ 2022-04-08  2:09 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Lucas Stach,
	Maarten Lankhorst, Ilia Mirkin, suijingfeng, linux-mips,
	linux-kernel, devicetree, dri-devel, kernel test robot


On 2022/3/23 21:11, Rob Herring wrote:
> On Wed, Mar 23, 2022 at 12:12:43PM +0800, Sui Jingfeng wrote:
>> On 2022/3/23 04:49, Rob Herring wrote:
>>>> +/*
>>>> + * mainly for dc in ls7a1000 which have builtin gpio emulated i2c
>>>> + *
>>>> + * @index : output channel index, 0 for DVO0, 1 for DVO1
>>>> + */
>>>> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev, void *base, unsigned int index)
>>>> +{
>>>> +	char compat[32] = {0};
>>>> +	unsigned int udelay = 5;
>>>> +	unsigned int timeout = 2200;
>>>> +	int nr = -1;
>>>> +	struct i2c_adapter *adapter;
>>>> +	struct lsdc_i2c *li2c;
>>>> +	struct device_node *i2c_np;
>>>> +	int ret;
>>>> +
>>>> +	li2c = devm_kzalloc(dev, sizeof(*li2c), GFP_KERNEL);
>>>> +	if (!li2c)
>>>> +		return ERR_PTR(-ENOMEM);
>>>> +
>>>> +	li2c->index = index;
>>>> +	li2c->dev = dev;
>>>> +
>>>> +	if (index == 0) {
>>>> +		li2c->sda = 0x01;
>>>> +		li2c->scl = 0x02;
>>>> +	} else if (index == 1) {
>>>> +		li2c->sda = 0x04;
>>>> +		li2c->scl = 0x08;
>>> Just require this to be in DT rather than having some default.
>>>
>> By design,  I am try very hard to let the code NOT fully  DT dependent. DT is nice , easy to learn and use.
>> But kernel side developer plan to follow UEFI + ACPI Specification on LS3A5000 + LS7A1000 platform. See [1]
>> There will no DT support then, provide a convention support  make the driver more flexible. I want the
>> driver works with minimal requirement. The driver just works on simple boards by put the following dc device
>> node in arch/mips/dts/loongson/loongson64g_4core_ls7a.dts,
> Pick DT or ACPI for the platform, not both. We don't need to have both
> in the kernel to support.
>
> Rob

Hi, everybody

I have send new version of my patch,  there may still have flaws though.

Would you like to help to review it again?

https://patchwork.freedesktop.org/series/102104/

@Rob @Maxime  @Krzysztof

I have  correct many issues as you guys mentioned  before,

if something get ignored and I may miss the point,  would like to 
mention it again

on my new patches?  because mails received previously got lost(flushed 
by new mails).

I can only reply to new reviews.

Thanks for your time.


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-22 20:49   ` Rob Herring
                       ` (5 preceding siblings ...)
  2022-03-24  7:32     ` Sui Jingfeng
@ 2023-01-17  3:08     ` Sui jingfeng
  2023-02-03  2:48     ` suijingfeng
  7 siblings, 0 replies; 48+ messages in thread
From: Sui jingfeng @ 2023-01-17  3:08 UTC (permalink / raw)
  To: Rob Herring, Sui Jingfeng
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot, suijingfeng


On 2022/3/23 04:49, Rob Herring wrote:
> On Tue, Mar 22, 2022 at 12:29:16AM +0800, Sui Jingfeng wrote:
>> From: suijingfeng <suijingfeng@loongson.cn>
>>
>> There is a display controller in loongson's LS2K1000 SoC and LS7A1000
>> bridge chip, the display controller is a PCI device in those chips. It
>> has two display pipes but with only one hardware cursor. Each way has
>> a DVO interface which provide RGB888 signals, vertical & horizontal
>> synchronisations, data enable and the pixel clock. Each CRTC is able to
>> scanout from 1920x1080 resolution at 60Hz, the maxmium resolution is
>> 2048x2048 according to the hardware spec. Loongson display controllers
>> are simple which require scanout buffers to be physically contiguous.
>>
>> For LS7A1000 bridge chip, the DC is equipped with a dedicated video RAM
>> which is typically 64MB or more. In this case, VRAM helper based driver
>> is intend to be used. While LS2K1000 is a SoC, only system memory is
>> available. Therefore CMA helper based driver is intend to be used. It is
>> possible to use VRAM helper based solution by carving out part of system
>> memory as VRAM though.
>>
>> For LS7A1000, there are 4 dedicated GPIOs whose control register is
>> located at the DC register space, They are used to emulate two way i2c.
>> One for DVO0, another for DVO1. LS2K1000 and LS2K0500 SoC don't have such
>> GPIO hardwared, they grab i2c adapter from other module, either general
>> purpose GPIO emulated i2c or hardware i2c adapter.
>>
>>      +------+            +-----------------------------------+
>>      | DDR4 |            |  +-------------------+            |
>>      +------+            |  | PCIe Root complex |   LS7A1000 |
>>         || MC0           |  +--++---------++----+            |
>>    +----------+  HT 3.0  |     ||         ||                 |
>>    | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>>    |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>>    +----------+          | +--------+  +-+--+-+    +---------+   +------+
>>         || MC1           +---------------|--|----------------+
>>      +------+                            |  |
>>      | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>>      +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>>                        +-------+                      +------+
>>
>> The above picture give a simple usage of LS7A1000, note that the encoder
>> is not necessary adv7125 or tfp410, other candicates can be ch7034b,
>> sil9022, ite66121 and lt8618 etc.
>>
>> v2: Fixup warnings reported by kernel test robot
>>
>> v3: Fix more grammar mistakes in Kconfig reported by Randy Dunlap and give
>>      more details about lsdc.
>>
>> v4:
>>     1) Add dts required and explain why device tree is required.
>>     2) Give more description about lsdc and VRAM helper based driver.
>>     3) Fix warnings reported by kernel test robot.
>>     4) Introduce stride_alignment member into struct lsdc_chip_desc, the
>>        stride alignment is 256 bytes for ls7a1000, ls2k1000 and ls2k0500.
>>
>> v5:
>>     1) Using writel and readl replace writeq and readq, to fix kernel test
>>        robot report build error on other archtecture.
>>     2) Set default fb format to XRGB8888 at crtc reset time.
>>
>> v6:
>>     1) Explain why we are not switch to drm dridge subsystem on ls2k1000.
>>     2) Explain why tiny drm driver is not suitable for us.
>>     3) Give a short description of the trival dirty uppdate implement based
>>        on CMA helper.
>>
>> v7:
>>     1) Remove select I2C_GPIO and I2C_LS2X in Kconfig, it is not ready now
>>     2) Licensing issues are fixed suggested by Krzysztof Kozlowski.
>>     3) Remove lsdc_pixpll_print(), part of it move to debugfs.
>>     4) Set prefer_shadow to true if vram based driver is in using.
>>     5) Replace double blank lines with single line in all files.
>>     6) Verbose cmd line parameter is replaced with drm_dbg()
>>     7) All warnnings reported by ./scripts/checkpatch.pl --strict are fixed
>>     8) Get edid from dtb support is removed as suggested by Maxime Ripard
>>     9) Fix typos and various improvement
>>
>> v8:
>>     1) Drop damage update implement and its command line.
>>     2) Drop DRM_LSDC_VRAM_DRIVER config option as suggested by Maxime.
>>     3) Deduce DC's identification from its compatible property.
>>     4) Drop the board specific dts patch.
>>     5) Add documention about the display controller device node.
>>
>> v9:
>>     1) Fix the warnings reported by checkpatch script and fix typos
>>
>> v10:
>>     1) Pass `make dt_binding_check` validation
>>     2) Fix warnings reported by kernel test robot
>>
>> v11:
>>     1) Convert the driver to use drm bridge and of graph framework.
>>     2) Dump register value support through debugfs.
>>
>> Reported-by: kernel test robot <lkp@intel.com>
>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>> ---
>>   drivers/gpu/drm/Kconfig             |   2 +
>>   drivers/gpu/drm/Makefile            |   1 +
>>   drivers/gpu/drm/lsdc/Kconfig        |  23 ++
>>   drivers/gpu/drm/lsdc/Makefile       |  13 +
>>   drivers/gpu/drm/lsdc/lsdc_crtc.c    | 396 +++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_drv.c     | 547 ++++++++++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_drv.h     | 197 ++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_i2c.c     | 235 ++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_i2c.h     |  42 ++
>>   drivers/gpu/drm/lsdc/lsdc_irq.c     |  58 +++
>>   drivers/gpu/drm/lsdc/lsdc_irq.h     |  18 +
>>   drivers/gpu/drm/lsdc/lsdc_output.c  | 262 +++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_output.h  |  24 ++
>>   drivers/gpu/drm/lsdc/lsdc_pci_drv.c | 328 ++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_plane.c   | 470 +++++++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_pll.c     | 574 ++++++++++++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_pll.h     |  88 +++++
>>   drivers/gpu/drm/lsdc/lsdc_regs.h    | 220 +++++++++++
>>   18 files changed, 3498 insertions(+)
>>   create mode 100644 drivers/gpu/drm/lsdc/Kconfig
>>   create mode 100644 drivers/gpu/drm/lsdc/Makefile
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_crtc.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_pci_drv.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_plane.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_regs.h
> [...]
>
>> diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.c b/drivers/gpu/drm/lsdc/lsdc_i2c.c
>> new file mode 100644
>> index 000000000000..55beed9266fa
>> --- /dev/null
>> +++ b/drivers/gpu/drm/lsdc/lsdc_i2c.c
>> @@ -0,0 +1,235 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * KMS driver for Loongson display controller
> Not really a useful comment since every file has the same one.
>
>> + * Copyright (C) 2022 Loongson Corporation
>> + */
>> +
>> +/*
>> + * Authors:
>> + *      Sui Jingfeng <suijingfeng@loongson.cn>
>> + */
>> +
>> +#include <linux/i2c.h>
>> +#include <linux/pci.h>
>> +
>> +#include "lsdc_drv.h"
>> +#include "lsdc_regs.h"
>> +#include "lsdc_i2c.h"
>> +
>> +/*
>> + * ls7a_gpio_i2c_set - set the state of a gpio pin indicated by mask
>> + * @mask: gpio pin mask
>> + */
>> +static void ls7a_gpio_i2c_set(struct lsdc_i2c * const li2c, int mask, int state)
>> +{
>> +	unsigned long flags;
>> +	u8 val;
>> +
>> +	spin_lock_irqsave(&li2c->reglock, flags);
> What are you protecting? Doesn't the caller serialize calls to these
> functions?

Hi,  there are some old ls7a1000 bridge chip product still in use at 
china market,

The display controller in old ls7a1000 bridge chip does not support 
concurrent  register access properly,

when two or more threads writing the dc registers at the same time, the  
ls7a1000 bridge chip will hung.

But the hung only happen at low occurrence, wrap register access with 
spin lock is more stable in practice

for old ls7a1000 bridge chip.

>> +
>> +	if (state) {
>> +		val = readb(li2c->dir_reg);
>> +		val |= mask;
>> +		writeb(val, li2c->dir_reg);
>> +	} else {
>> +		val = readb(li2c->dir_reg);
>> +		val &= ~mask;
>> +		writeb(val, li2c->dir_reg);
>> +
>> +		val = readb(li2c->dat_reg);
>> +		if (state)
> This condition is never true. We're in the 'else' because !state.
>
>> +			val |= mask;
>> +		else
>> +			val &= ~mask;
>> +		writeb(val, li2c->dat_reg);
> Shouldn't you set the data register low first and then change the
> direction? Otherwise, you may be driving high for a moment. However, if
> high is always done by setting the direction as input, why write the
> data register each time? I'm assuming whatever is written to the dat_reg
> is maintained regardless of pin state.
>
>> +	}
>> +
>> +	spin_unlock_irqrestore(&li2c->reglock, flags);
>> +}
>> +
>> +/*
>> + * ls7a_gpio_i2c_get - read value back from gpio pin
>> + * @mask: gpio pin mask
>> + */
>> +static int ls7a_gpio_i2c_get(struct lsdc_i2c * const li2c, int mask)
>> +{
>> +	unsigned long flags;
>> +	u8 val;
>> +
>> +	spin_lock_irqsave(&li2c->reglock, flags);
>> +
>> +	/* first set this pin as input */
>> +	val = readb(li2c->dir_reg);
>> +	val |= mask;
>> +	writeb(val, li2c->dir_reg);
>> +
>> +	/* then get level state from this pin */
>> +	val = readb(li2c->dat_reg);
>> +
>> +	spin_unlock_irqrestore(&li2c->reglock, flags);
>> +
>> +	return (val & mask) ? 1 : 0;
>> +}
>> +
>> +/* set the state on the i2c->sda pin */
>> +static void ls7a_i2c_set_sda(void *i2c, int state)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_set(li2c, li2c->sda, state);
>> +}
>> +
>> +/* set the state on the i2c->scl pin */
>> +static void ls7a_i2c_set_scl(void *i2c, int state)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_set(li2c, li2c->scl, state);
>> +}
>> +
>> +/* read the value from the i2c->sda pin */
>> +static int ls7a_i2c_get_sda(void *i2c)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_get(li2c, li2c->sda);
>> +}
>> +
>> +/* read the value from the i2c->scl pin */
>> +static int ls7a_i2c_get_scl(void *i2c)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_get(li2c, li2c->scl);
>> +}
>> +
>> +/*
>> + * mainly for dc in ls7a1000 which have builtin gpio emulated i2c
>> + *
>> + * @index : output channel index, 0 for DVO0, 1 for DVO1
>> + */
>> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev, void *base, unsigned int index)
>> +{
>> +	char compat[32] = {0};
>> +	unsigned int udelay = 5;
>> +	unsigned int timeout = 2200;
>> +	int nr = -1;
>> +	struct i2c_adapter *adapter;
>> +	struct lsdc_i2c *li2c;
>> +	struct device_node *i2c_np;
>> +	int ret;
>> +
>> +	li2c = devm_kzalloc(dev, sizeof(*li2c), GFP_KERNEL);
>> +	if (!li2c)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	li2c->index = index;
>> +	li2c->dev = dev;
>> +
>> +	if (index == 0) {
>> +		li2c->sda = 0x01;
>> +		li2c->scl = 0x02;
>> +	} else if (index == 1) {
>> +		li2c->sda = 0x04;
>> +		li2c->scl = 0x08;
> Just require this to be in DT rather than having some default.
>
>> +	}
>> +
>> +	spin_lock_init(&li2c->reglock);
>> +
>> +	snprintf(compat, sizeof(compat), "lsdc,i2c-gpio-%d", index);
> compatible values shouldn't have an index and you shouldn't need a
> index in DT. You need to iterate over child nodes with matching
> compatible.
>
>> +	i2c_np = of_find_compatible_node(dev->of_node, NULL, compat);
>> +	if (i2c_np) {
>> +		u32 sda, scl;
>> +
>> +		dev_dbg(dev, "Has %s property in the DT", compat);
>> +
>> +		/*  */
>> +		ret = of_property_read_u32(i2c_np, "sda", &sda);
> Custom properties need a vendor prefix.
>
>> +		if (ret == 0)
>> +			li2c->sda = 1 << sda;
>> +
>> +		ret = of_property_read_u32(i2c_np, "scl", &scl);
>> +		if (ret == 0)
>> +			li2c->scl = 1 << scl;
>> +
>> +		/* Optional properties which made the driver more flexible */
>> +		of_property_read_u32(i2c_np, "udelay", &udelay);
>> +		of_property_read_u32(i2c_np, "timeout", &timeout);
> These aren't documented. Do you really need them in DT?
>
>> +		of_property_read_u32(i2c_np, "reg", &nr);
>> +	}
>> +
>> +	dev_dbg(dev, "%s: sda=%u, scl=%u, nr=%d, udelay=%u, timeout=%u\n",
>> +		compat, li2c->sda, li2c->scl, nr, udelay, timeout);
>> +
>> +	li2c->reg_base = base;
>> +
>> +	li2c->dir_reg = li2c->reg_base + LS7A_DC_GPIO_DIR_REG;
>> +	li2c->dat_reg = li2c->reg_base + LS7A_DC_GPIO_DAT_REG;
>> +
>> +	li2c->bit.setsda = ls7a_i2c_set_sda;
>> +	li2c->bit.setscl = ls7a_i2c_set_scl;
>> +	li2c->bit.getsda = ls7a_i2c_get_sda;
>> +	li2c->bit.getscl = ls7a_i2c_get_scl;
>> +	li2c->bit.udelay = udelay;
>> +	li2c->bit.timeout = usecs_to_jiffies(timeout);
>> +	li2c->bit.data = li2c;
>> +
>> +	adapter = &li2c->adapter;
>> +	adapter->algo_data = &li2c->bit;
>> +	adapter->owner = THIS_MODULE;
>> +	adapter->class = I2C_CLASS_DDC;
>> +	adapter->dev.parent = dev;
>> +	adapter->nr = nr;
>> +	if (i2c_np) {
>> +		adapter->dev.of_node = i2c_np;
>> +		of_node_put(i2c_np);
>> +	}
>> +
>> +	strscpy(adapter->name, &compat[5], sizeof(adapter->name));
>> +
>> +	i2c_set_adapdata(adapter, li2c);
>> +
>> +	ret = i2c_bit_add_numbered_bus(adapter);
> Why do you care what the bus number is? You shouldn't need to.
>
>> +	if (ret) {
>> +		if (i2c_np)
>> +			of_node_put(i2c_np);
>> +
>> +		devm_kfree(dev, li2c);
>> +		return ERR_PTR(ret);
>> +	}
>> +
>> +	return li2c;
>> +}
>> +
>> +void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c)
>> +{
>> +	struct i2c_adapter *adapter;
>> +
>> +	if (li2c) {
>> +		adapter = &li2c->adapter;
>> +
>> +		if (adapter && adapter->dev.of_node)
>> +			of_node_put(adapter->dev.of_node);
>> +
>> +		devm_kfree(ddev->dev, li2c);
>> +	}
>> +}
>> +
>> +struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
>> +					 unsigned int index)
>> +{
>> +	const struct lsdc_chip_desc * const descp = ldev->desc;
>> +	struct lsdc_i2c *li2c;
>> +
>> +	if (index >= descp->num_of_crtc) {
>> +		drm_err(ldev->ddev, "I2c adapter is no more than %u, %u\n",
>> +			descp->num_of_crtc, index);
>> +		return NULL;
>> +	}
>> +
>> +	li2c = ldev->li2c[index];
>> +	if (li2c)
>> +		return &li2c->adapter;
>> +
>> +	return NULL;
>> +}
>> diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.h b/drivers/gpu/drm/lsdc/lsdc_i2c.h
>> new file mode 100644
>> index 000000000000..4ab825143eb4
>> --- /dev/null
>> +++ b/drivers/gpu/drm/lsdc/lsdc_i2c.h
>> @@ -0,0 +1,42 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * KMS driver for Loongson display controller
>> + * Copyright (C) 2022 Loongson Corporation
>> + */
>> +
>> +/*
>> + * Authors:
>> + *      Sui Jingfeng <suijingfeng@loongson.cn>
>> + */
>> +
>> +#ifndef __LSDC_I2C__
>> +#define __LSDC_I2C__
>> +
>> +#include <linux/i2c.h>
>> +#include <linux/i2c-algo-bit.h>
>> +#include <linux/pci.h>
>> +
>> +struct lsdc_i2c {
>> +	struct device *dev;
>> +	struct i2c_adapter adapter;
>> +	struct i2c_algo_bit_data bit;
>> +	/* @reglock: protects concurrent register access */
>> +	spinlock_t reglock;
>> +	void __iomem *reg_base;
>> +	void __iomem *dir_reg;
>> +	void __iomem *dat_reg;
>> +	int index;
>> +	/* pin bit mask */
>> +	u8 sda;
>> +	u8 scl;
>> +};
>> +
>> +void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c);
>> +
>> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev,
>> +				      void *base,
>> +				      unsigned int index);
>> +
>> +struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
>> +					 unsigned int index);
>> +#endif


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller
  2022-03-22 20:49   ` Rob Herring
                       ` (6 preceding siblings ...)
  2023-01-17  3:08     ` Sui jingfeng
@ 2023-02-03  2:48     ` suijingfeng
  7 siblings, 0 replies; 48+ messages in thread
From: suijingfeng @ 2023-02-03  2:48 UTC (permalink / raw)
  To: Rob Herring, Sui Jingfeng
  Cc: Maxime Ripard, Thomas Zimmermann, Roland Scheidegger, Zack Rusin,
	Christian Gmeiner, David Airlie, Daniel Vetter,
	Thomas Bogendoerfer, Dan Carpenter, Krzysztof Kozlowski,
	Andrey Zhizhikin, Sam Ravnborg, David S . Miller, Jiaxun Yang,
	Lucas Stach, Maarten Lankhorst, Ilia Mirkin, Qing Zhang,
	linux-mips, linux-kernel, devicetree, dri-devel,
	kernel test robot


On 2022/3/23 04:49, Rob Herring wrote:
> On Tue, Mar 22, 2022 at 12:29:16AM +0800, Sui Jingfeng wrote:
>> From: suijingfeng <suijingfeng@loongson.cn>
>>
>> There is a display controller in loongson's LS2K1000 SoC and LS7A1000
>> bridge chip, the display controller is a PCI device in those chips. It
>> has two display pipes but with only one hardware cursor. Each way has
>> a DVO interface which provide RGB888 signals, vertical & horizontal
>> synchronisations, data enable and the pixel clock. Each CRTC is able to
>> scanout from 1920x1080 resolution at 60Hz, the maxmium resolution is
>> 2048x2048 according to the hardware spec. Loongson display controllers
>> are simple which require scanout buffers to be physically contiguous.
>>
>> For LS7A1000 bridge chip, the DC is equipped with a dedicated video RAM
>> which is typically 64MB or more. In this case, VRAM helper based driver
>> is intend to be used. While LS2K1000 is a SoC, only system memory is
>> available. Therefore CMA helper based driver is intend to be used. It is
>> possible to use VRAM helper based solution by carving out part of system
>> memory as VRAM though.
>>
>> For LS7A1000, there are 4 dedicated GPIOs whose control register is
>> located at the DC register space, They are used to emulate two way i2c.
>> One for DVO0, another for DVO1. LS2K1000 and LS2K0500 SoC don't have such
>> GPIO hardwared, they grab i2c adapter from other module, either general
>> purpose GPIO emulated i2c or hardware i2c adapter.
>>
>>      +------+            +-----------------------------------+
>>      | DDR4 |            |  +-------------------+            |
>>      +------+            |  | PCIe Root complex |   LS7A1000 |
>>         || MC0           |  +--++---------++----+            |
>>    +----------+  HT 3.0  |     ||         ||                 |
>>    | LS3A4000 |<-------->| +---++---+  +--++--+    +---------+   +------+
>>    |   CPU    |<-------->| | GC1000 |  | LSDC |<-->| DDR3 MC |<->| VRAM |
>>    +----------+          | +--------+  +-+--+-+    +---------+   +------+
>>         || MC1           +---------------|--|----------------+
>>      +------+                            |  |
>>      | DDR4 |          +-------+   DVO0  |  |  DVO1   +------+
>>      +------+   VGA <--|ADV7125|<--------+  +-------->|TFP410|--> DVI/HDMI
>>                        +-------+                      +------+
>>
>> The above picture give a simple usage of LS7A1000, note that the encoder
>> is not necessary adv7125 or tfp410, other candicates can be ch7034b,
>> sil9022, ite66121 and lt8618 etc.
>>
>> v2: Fixup warnings reported by kernel test robot
>>
>> v3: Fix more grammar mistakes in Kconfig reported by Randy Dunlap and give
>>      more details about lsdc.
>>
>> v4:
>>     1) Add dts required and explain why device tree is required.
>>     2) Give more description about lsdc and VRAM helper based driver.
>>     3) Fix warnings reported by kernel test robot.
>>     4) Introduce stride_alignment member into struct lsdc_chip_desc, the
>>        stride alignment is 256 bytes for ls7a1000, ls2k1000 and ls2k0500.
>>
>> v5:
>>     1) Using writel and readl replace writeq and readq, to fix kernel test
>>        robot report build error on other archtecture.
>>     2) Set default fb format to XRGB8888 at crtc reset time.
>>
>> v6:
>>     1) Explain why we are not switch to drm dridge subsystem on ls2k1000.
>>     2) Explain why tiny drm driver is not suitable for us.
>>     3) Give a short description of the trival dirty uppdate implement based
>>        on CMA helper.
>>
>> v7:
>>     1) Remove select I2C_GPIO and I2C_LS2X in Kconfig, it is not ready now
>>     2) Licensing issues are fixed suggested by Krzysztof Kozlowski.
>>     3) Remove lsdc_pixpll_print(), part of it move to debugfs.
>>     4) Set prefer_shadow to true if vram based driver is in using.
>>     5) Replace double blank lines with single line in all files.
>>     6) Verbose cmd line parameter is replaced with drm_dbg()
>>     7) All warnnings reported by ./scripts/checkpatch.pl --strict are fixed
>>     8) Get edid from dtb support is removed as suggested by Maxime Ripard
>>     9) Fix typos and various improvement
>>
>> v8:
>>     1) Drop damage update implement and its command line.
>>     2) Drop DRM_LSDC_VRAM_DRIVER config option as suggested by Maxime.
>>     3) Deduce DC's identification from its compatible property.
>>     4) Drop the board specific dts patch.
>>     5) Add documention about the display controller device node.
>>
>> v9:
>>     1) Fix the warnings reported by checkpatch script and fix typos
>>
>> v10:
>>     1) Pass `make dt_binding_check` validation
>>     2) Fix warnings reported by kernel test robot
>>
>> v11:
>>     1) Convert the driver to use drm bridge and of graph framework.
>>     2) Dump register value support through debugfs.
>>
>> Reported-by: kernel test robot <lkp@intel.com>
>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>> Signed-off-by: Sui Jingfeng <15330273260@189.cn>
>> Signed-off-by: suijingfeng <suijingfeng@loongson.cn>
>> ---
>>   drivers/gpu/drm/Kconfig             |   2 +
>>   drivers/gpu/drm/Makefile            |   1 +
>>   drivers/gpu/drm/lsdc/Kconfig        |  23 ++
>>   drivers/gpu/drm/lsdc/Makefile       |  13 +
>>   drivers/gpu/drm/lsdc/lsdc_crtc.c    | 396 +++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_drv.c     | 547 ++++++++++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_drv.h     | 197 ++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_i2c.c     | 235 ++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_i2c.h     |  42 ++
>>   drivers/gpu/drm/lsdc/lsdc_irq.c     |  58 +++
>>   drivers/gpu/drm/lsdc/lsdc_irq.h     |  18 +
>>   drivers/gpu/drm/lsdc/lsdc_output.c  | 262 +++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_output.h  |  24 ++
>>   drivers/gpu/drm/lsdc/lsdc_pci_drv.c | 328 ++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_plane.c   | 470 +++++++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_pll.c     | 574 ++++++++++++++++++++++++++++
>>   drivers/gpu/drm/lsdc/lsdc_pll.h     |  88 +++++
>>   drivers/gpu/drm/lsdc/lsdc_regs.h    | 220 +++++++++++
>>   18 files changed, 3498 insertions(+)
>>   create mode 100644 drivers/gpu/drm/lsdc/Kconfig
>>   create mode 100644 drivers/gpu/drm/lsdc/Makefile
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_crtc.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_drv.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_i2c.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_irq.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_output.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_pci_drv.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_plane.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.c
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_pll.h
>>   create mode 100644 drivers/gpu/drm/lsdc/lsdc_regs.h
> [...]
>
>> diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.c b/drivers/gpu/drm/lsdc/lsdc_i2c.c
>> new file mode 100644
>> index 000000000000..55beed9266fa
>> --- /dev/null
>> +++ b/drivers/gpu/drm/lsdc/lsdc_i2c.c
>> @@ -0,0 +1,235 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * KMS driver for Loongson display controller
> Not really a useful comment since every file has the same one.
>
>> + * Copyright (C) 2022 Loongson Corporation
>> + */
>> +
>> +/*
>> + * Authors:
>> + *      Sui Jingfeng <suijingfeng@loongson.cn>
>> + */
>> +
>> +#include <linux/i2c.h>
>> +#include <linux/pci.h>
>> +
>> +#include "lsdc_drv.h"
>> +#include "lsdc_regs.h"
>> +#include "lsdc_i2c.h"
>> +
>> +/*
>> + * ls7a_gpio_i2c_set - set the state of a gpio pin indicated by mask
>> + * @mask: gpio pin mask
>> + */
>> +static void ls7a_gpio_i2c_set(struct lsdc_i2c * const li2c, int mask, int state)
>> +{
>> +	unsigned long flags;
>> +	u8 val;
>> +
>> +	spin_lock_irqsave(&li2c->reglock, flags);
> What are you protecting? Doesn't the caller serialize calls to these
> functions?
>
>> +
>> +	if (state) {
>> +		val = readb(li2c->dir_reg);
>> +		val |= mask;
>> +		writeb(val, li2c->dir_reg);
>> +	} else {
>> +		val = readb(li2c->dir_reg);
>> +		val &= ~mask;
>> +		writeb(val, li2c->dir_reg);
>> +
>> +		val = readb(li2c->dat_reg);
>> +		if (state)
> This condition is never true. We're in the 'else' because !state.
>
>> +			val |= mask;
>> +		else
>> +			val &= ~mask;
>> +		writeb(val, li2c->dat_reg);
> Shouldn't you set the data register low first and then change the
> direction? Otherwise, you may be driving high for a moment. However, if
> high is always done by setting the direction as input,

Setting the direction as input will get high, because the external
pull-up resistor will pull the level up.

> why write the
> data register each time? I'm assuming whatever is written to the dat_reg
> is maintained regardless of pin state.
>
Because we have only one data reg corresponding two direction(input and 
output).

our DC hardware design engineer is not good. :(

Value written to the dat_reg will get flushed when pin state changed.

Changed from output to input, for example. Otherwise, how can we read the pin level state back?

>> +	}
>> +
>> +	spin_unlock_irqrestore(&li2c->reglock, flags);
>> +}
>> +
>> +/*
>> + * ls7a_gpio_i2c_get - read value back from gpio pin
>> + * @mask: gpio pin mask
>> + */
>> +static int ls7a_gpio_i2c_get(struct lsdc_i2c * const li2c, int mask)
>> +{
>> +	unsigned long flags;
>> +	u8 val;
>> +
>> +	spin_lock_irqsave(&li2c->reglock, flags);
>> +
>> +	/* first set this pin as input */
>> +	val = readb(li2c->dir_reg);
>> +	val |= mask;
>> +	writeb(val, li2c->dir_reg);
>> +
>> +	/* then get level state from this pin */
>> +	val = readb(li2c->dat_reg);
>> +
>> +	spin_unlock_irqrestore(&li2c->reglock, flags);
>> +
>> +	return (val & mask) ? 1 : 0;
>> +}
>> +
>> +/* set the state on the i2c->sda pin */
>> +static void ls7a_i2c_set_sda(void *i2c, int state)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_set(li2c, li2c->sda, state);
>> +}
>> +
>> +/* set the state on the i2c->scl pin */
>> +static void ls7a_i2c_set_scl(void *i2c, int state)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_set(li2c, li2c->scl, state);
>> +}
>> +
>> +/* read the value from the i2c->sda pin */
>> +static int ls7a_i2c_get_sda(void *i2c)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_get(li2c, li2c->sda);
>> +}
>> +
>> +/* read the value from the i2c->scl pin */
>> +static int ls7a_i2c_get_scl(void *i2c)
>> +{
>> +	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
>> +
>> +	return ls7a_gpio_i2c_get(li2c, li2c->scl);
>> +}
>> +
>> +/*
>> + * mainly for dc in ls7a1000 which have builtin gpio emulated i2c
>> + *
>> + * @index : output channel index, 0 for DVO0, 1 for DVO1
>> + */
>> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev, void *base, unsigned int index)
>> +{
>> +	char compat[32] = {0};
>> +	unsigned int udelay = 5;
>> +	unsigned int timeout = 2200;
>> +	int nr = -1;
>> +	struct i2c_adapter *adapter;
>> +	struct lsdc_i2c *li2c;
>> +	struct device_node *i2c_np;
>> +	int ret;
>> +
>> +	li2c = devm_kzalloc(dev, sizeof(*li2c), GFP_KERNEL);
>> +	if (!li2c)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	li2c->index = index;
>> +	li2c->dev = dev;
>> +
>> +	if (index == 0) {
>> +		li2c->sda = 0x01;
>> +		li2c->scl = 0x02;
>> +	} else if (index == 1) {
>> +		li2c->sda = 0x04;
>> +		li2c->scl = 0x08;
> Just require this to be in DT rather than having some default.
>
If only this driver  be used in embedded environment(like arms and 
risc-v), relay on DT solely is the right way.

But Loongson display controller have been applied in both PC class 
desktop(using UEFI+ACPI) and  embedded environment(using DT),  this is 
the key difference. I suddenly realize that  i didn't explain this fact 
clearly at that time.

The default code works in almost 99% case, through.

>> +	}
>> +
>> +	spin_lock_init(&li2c->reglock);
>> +
>> +	snprintf(compat, sizeof(compat), "lsdc,i2c-gpio-%d", index);
> compatible values shouldn't have an index and you shouldn't need a
> index in DT. You need to iterate over child nodes with matching
> compatible.
>
>> +	i2c_np = of_find_compatible_node(dev->of_node, NULL, compat);
>> +	if (i2c_np) {
>> +		u32 sda, scl;
>> +
>> +		dev_dbg(dev, "Has %s property in the DT", compat);
>> +
>> +		/*  */
>> +		ret = of_property_read_u32(i2c_np, "sda", &sda);
> Custom properties need a vendor prefix.
>
>> +		if (ret == 0)
>> +			li2c->sda = 1 << sda;
>> +
>> +		ret = of_property_read_u32(i2c_np, "scl", &scl);
>> +		if (ret == 0)
>> +			li2c->scl = 1 << scl;
>> +
>> +		/* Optional properties which made the driver more flexible */
>> +		of_property_read_u32(i2c_np, "udelay", &udelay);
>> +		of_property_read_u32(i2c_np, "timeout", &timeout);
> These aren't documented. Do you really need them in DT?
>
>> +		of_property_read_u32(i2c_np, "reg", &nr);
>> +	}
>> +
>> +	dev_dbg(dev, "%s: sda=%u, scl=%u, nr=%d, udelay=%u, timeout=%u\n",
>> +		compat, li2c->sda, li2c->scl, nr, udelay, timeout);
>> +
>> +	li2c->reg_base = base;
>> +
>> +	li2c->dir_reg = li2c->reg_base + LS7A_DC_GPIO_DIR_REG;
>> +	li2c->dat_reg = li2c->reg_base + LS7A_DC_GPIO_DAT_REG;
>> +
>> +	li2c->bit.setsda = ls7a_i2c_set_sda;
>> +	li2c->bit.setscl = ls7a_i2c_set_scl;
>> +	li2c->bit.getsda = ls7a_i2c_get_sda;
>> +	li2c->bit.getscl = ls7a_i2c_get_scl;
>> +	li2c->bit.udelay = udelay;
>> +	li2c->bit.timeout = usecs_to_jiffies(timeout);
>> +	li2c->bit.data = li2c;
>> +
>> +	adapter = &li2c->adapter;
>> +	adapter->algo_data = &li2c->bit;
>> +	adapter->owner = THIS_MODULE;
>> +	adapter->class = I2C_CLASS_DDC;
>> +	adapter->dev.parent = dev;
>> +	adapter->nr = nr;
>> +	if (i2c_np) {
>> +		adapter->dev.of_node = i2c_np;
>> +		of_node_put(i2c_np);
>> +	}
>> +
>> +	strscpy(adapter->name, &compat[5], sizeof(adapter->name));
>> +
>> +	i2c_set_adapdata(adapter, li2c);
>> +
>> +	ret = i2c_bit_add_numbered_bus(adapter);
> Why do you care what the bus number is? You shouldn't need to.

Yes, we didn't need that. the i2c core will allocate one for us automatically.

Your advice is valuable, thanks your kindness review.

>> +	if (ret) {
>> +		if (i2c_np)
>> +			of_node_put(i2c_np);
>> +
>> +		devm_kfree(dev, li2c);
>> +		return ERR_PTR(ret);
>> +	}
>> +
>> +	return li2c;
>> +}
>> +
>> +void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c)
>> +{
>> +	struct i2c_adapter *adapter;
>> +
>> +	if (li2c) {
>> +		adapter = &li2c->adapter;
>> +
>> +		if (adapter && adapter->dev.of_node)
>> +			of_node_put(adapter->dev.of_node);
>> +
>> +		devm_kfree(ddev->dev, li2c);
>> +	}
>> +}
>> +
>> +struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
>> +					 unsigned int index)
>> +{
>> +	const struct lsdc_chip_desc * const descp = ldev->desc;
>> +	struct lsdc_i2c *li2c;
>> +
>> +	if (index >= descp->num_of_crtc) {
>> +		drm_err(ldev->ddev, "I2c adapter is no more than %u, %u\n",
>> +			descp->num_of_crtc, index);
>> +		return NULL;
>> +	}
>> +
>> +	li2c = ldev->li2c[index];
>> +	if (li2c)
>> +		return &li2c->adapter;
>> +
>> +	return NULL;
>> +}
>> diff --git a/drivers/gpu/drm/lsdc/lsdc_i2c.h b/drivers/gpu/drm/lsdc/lsdc_i2c.h
>> new file mode 100644
>> index 000000000000..4ab825143eb4
>> --- /dev/null
>> +++ b/drivers/gpu/drm/lsdc/lsdc_i2c.h
>> @@ -0,0 +1,42 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * KMS driver for Loongson display controller
>> + * Copyright (C) 2022 Loongson Corporation
>> + */
>> +
>> +/*
>> + * Authors:
>> + *      Sui Jingfeng <suijingfeng@loongson.cn>
>> + */
>> +
>> +#ifndef __LSDC_I2C__
>> +#define __LSDC_I2C__
>> +
>> +#include <linux/i2c.h>
>> +#include <linux/i2c-algo-bit.h>
>> +#include <linux/pci.h>
>> +
>> +struct lsdc_i2c {
>> +	struct device *dev;
>> +	struct i2c_adapter adapter;
>> +	struct i2c_algo_bit_data bit;
>> +	/* @reglock: protects concurrent register access */
>> +	spinlock_t reglock;
>> +	void __iomem *reg_base;
>> +	void __iomem *dir_reg;
>> +	void __iomem *dat_reg;
>> +	int index;
>> +	/* pin bit mask */
>> +	u8 sda;
>> +	u8 scl;
>> +};
>> +
>> +void lsdc_destroy_i2c(struct drm_device *ddev, struct lsdc_i2c *li2c);
>> +
>> +struct lsdc_i2c *lsdc_create_i2c_chan(struct device *dev,
>> +				      void *base,
>> +				      unsigned int index);
>> +
>> +struct i2c_adapter *lsdc_get_i2c_adapter(struct lsdc_device *ldev,
>> +					 unsigned int index);
>> +#endif


^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2023-02-03  2:48 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-21 16:29 [PATCH v11 0/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
2022-03-21 16:29 ` [PATCH v11 1/7] MIPS: Loongson64: dts: update the display controller device node Sui Jingfeng
2022-03-21 16:29 ` [PATCH v11 2/7] MIPS: Loongson64: dts: introduce ls3A4000 evaluation board Sui Jingfeng
2022-03-22 13:05   ` Jiaxun Yang
2022-03-22 13:38     ` Sui Jingfeng
2022-03-22 16:06       ` Jiaxun Yang
2022-03-23  1:53         ` Sui Jingfeng
2022-03-23  2:29           ` Jiaxun Yang
2022-03-23  3:07             ` Sui Jingfeng
2022-03-23  3:14               ` Jiaxun Yang
2022-03-23  7:07             ` Sui Jingfeng
2022-03-23 12:29               ` Jiaxun Yang
2022-03-23 12:53           ` Rob Herring
2022-03-24  1:51             ` Sui Jingfeng
2022-03-21 16:29 ` [PATCH v11 3/7] MIPS: Loongson64: dts: introduce lemote A1901 motherboard Sui Jingfeng
2022-03-21 16:29 ` [PATCH v11 4/7] MIPS: Loongson64: dts: introduce ls2k1000 pai evaluation board Sui Jingfeng
2022-03-21 16:29 ` [PATCH v11 5/7] dt-bindings: display: Add Loongson display controller Sui Jingfeng
2022-03-21 23:20   ` Rob Herring
2022-03-22  2:33     ` Sui Jingfeng
2022-03-22 13:08       ` Jiaxun Yang
2022-03-22 13:54         ` Sui Jingfeng
2022-03-22 16:08           ` Jiaxun Yang
2022-03-22 20:03           ` Rob Herring
2022-03-22 20:55       ` Rob Herring
2022-03-23  3:38         ` Sui Jingfeng
2022-03-23 13:03           ` Rob Herring
2022-03-24  1:48             ` Sui Jingfeng
2022-03-24 13:26               ` Rob Herring
2022-03-26 10:04                 ` Sui Jingfeng
2022-03-28 14:04                   ` Rob Herring
2022-03-29  2:02                     ` Sui Jingfeng
2022-03-29 13:24                       ` Rob Herring
2022-03-21 16:29 ` [PATCH v11 6/7] MIPS: Loongson64: defconfig: enable display bridge drivers on Loongson64 Sui Jingfeng
2022-03-21 16:29 ` [PATCH v11 7/7] drm/lsdc: add drm driver for loongson display controller Sui Jingfeng
2022-03-22 20:49   ` Rob Herring
2022-03-23  4:12     ` Sui Jingfeng
2022-03-23 13:11       ` Rob Herring
2022-03-24  4:05         ` Sui Jingfeng
2022-04-08  2:09         ` Sui Jingfeng
2022-03-23  4:19     ` Sui Jingfeng
2022-03-23  8:49     ` Sui Jingfeng
2022-03-23  9:31     ` Sui Jingfeng
2022-03-24  1:39     ` Sui Jingfeng
2022-03-24 13:42       ` Rob Herring
2022-03-24  7:32     ` Sui Jingfeng
2022-03-24 13:56       ` Rob Herring
2023-01-17  3:08     ` Sui jingfeng
2023-02-03  2:48     ` suijingfeng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).