[PATCH v2 2/2] drm/bridge: panel: Check device dependency before managing device link

2023-11-26 Thread Liu Ying
Some panel devices already depend on DRM device, like the panel in
arch/arm/boot/dts/st/ste-ux500-samsung-skomer.dts, because DRM device is
the ancestor of those panel devices.  device_link_add() would fail by
returning a NULL pointer for those panel devices because of the existing
dependency.  So, check the dependency by calling device_is_dependent()
before adding or deleting device link between panel device and DRM device
so that the link is managed only for independent panel devices.

Fixes: 887878014534 ("drm/bridge: panel: Fix device link for 
DRM_BRIDGE_ATTACH_NO_CONNECTOR")
Fixes: 199cf07ebd2b ("drm/bridge: panel: Add a device link between drm device 
and panel device")
Reported-by: Linus Walleij 
Closes: 
https://lore.kernel.org/lkml/cacrpkdagzxd6hbix7mvunjajtmepg00pp6+nj1p0jrfj-ar...@mail.gmail.com/T/
Tested-by: Linus Walleij 
Signed-off-by: Liu Ying 
---
v2:
* No change.

 drivers/gpu/drm/bridge/panel.c | 27 ++-
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index e48823a4f1ed..5e8980023407 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -23,6 +23,7 @@ struct panel_bridge {
struct drm_panel *panel;
struct device_link *link;
u32 connector_type;
+   bool is_independent;
 };
 
 static inline struct panel_bridge *
@@ -67,12 +68,17 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
struct drm_device *drm_dev = bridge->dev;
int ret;
 
-   panel_bridge->link = device_link_add(drm_dev->dev, panel->dev,
-DL_FLAG_STATELESS);
-   if (!panel_bridge->link) {
-   DRM_ERROR("Failed to add device link between %s and %s\n",
- dev_name(drm_dev->dev), dev_name(panel->dev));
-   return -EINVAL;
+   panel_bridge->is_independent = !device_is_dependent(drm_dev->dev,
+   panel->dev);
+
+   if (panel_bridge->is_independent) {
+   panel_bridge->link = device_link_add(drm_dev->dev, panel->dev,
+DL_FLAG_STATELESS);
+   if (!panel_bridge->link) {
+   DRM_ERROR("Failed to add device link between %s and 
%s\n",
+ dev_name(drm_dev->dev), dev_name(panel->dev));
+   return -EINVAL;
+   }
}
 
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
@@ -80,7 +86,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 
if (!bridge->encoder) {
DRM_ERROR("Missing encoder\n");
-   device_link_del(panel_bridge->link);
+   if (panel_bridge->is_independent)
+   device_link_del(panel_bridge->link);
return -ENODEV;
}
 
@@ -92,7 +99,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 panel_bridge->connector_type);
if (ret) {
DRM_ERROR("Failed to initialize connector\n");
-   device_link_del(panel_bridge->link);
+   if (panel_bridge->is_independent)
+   device_link_del(panel_bridge->link);
return ret;
}
 
@@ -115,7 +123,8 @@ static void panel_bridge_detach(struct drm_bridge *bridge)
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
struct drm_connector *connector = _bridge->connector;
 
-   device_link_del(panel_bridge->link);
+   if (panel_bridge->is_independent)
+   device_link_del(panel_bridge->link);
 
/*
 * Cleanup the connector if we know it was initialized.
-- 
2.37.1



[PATCH v2 1/2] driver core: Export device_is_dependent() to modules

2023-11-26 Thread Liu Ying
Export device_is_dependent() since the drm_kms_helper module is starting
to use it.

Signed-off-by: Liu Ying 
---
v2:
* Newly introduced as needed by patch 2.

 drivers/base/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 67ba592afc77..bfd2bf0364b7 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -328,6 +328,7 @@ int device_is_dependent(struct device *dev, void *target)
}
return ret;
 }
+EXPORT_SYMBOL_GPL(device_is_dependent);
 
 static void device_link_init_status(struct device_link *link,
struct device *consumer,
-- 
2.37.1



[PATCH v2 0/2] drm/bridge: panel: Check device dependency before managing device link

2023-11-26 Thread Liu Ying
Hi,

This series aims to check panel device dependency upon DRM device before
managing device link between them.  It fixes eariler patches in v6.7-rc1
which tried to manage the link.  Without this series, the link fails to
be added for dependent panel devices and hence relevant panel bridges
fail to be attached.  A real broken panel is "novatek,nt35510" defined
in arch/arm/boot/dts/st/ste-ux500-samsung-skomer.dts as reported by
Linus Walleij.

Patch 1 exports device_is_dependent() to modules as needed by patch 2.
Patch 2 checks device dependency before managing the device link.

Note that patch 2 is already in drm-misc/drm-misc-fixes and
drm-misc/for-linux-next-fixes.  Patch 1 needs to be reviewed and picked up.

v2:
* Introduce patch 1 to export device_is_dependent() to modules as needed by
  patch 2.

Liu Ying (2):
  driver core: Export device_is_dependent() to modules
  drm/bridge: panel: Check device dependency before managing device link

 drivers/base/core.c|  1 +
 drivers/gpu/drm/bridge/panel.c | 27 ++-
 2 files changed, 19 insertions(+), 9 deletions(-)

-- 
2.37.1



[PATCH v2] drm/bridge: imx93-mipi-dsi: Fix a couple of building warnings

2023-11-22 Thread Liu Ying
Fix a couple of building warnings on used uninitialized 'best_m' and
'best_n' local variables by initializing 'best_m' to zero and 'best_n'
to UINT_MAX.  This makes compiler happy only.  No functional change.

Fixes: ce62f8ea7e3f ("drm/bridge: imx: Add i.MX93 MIPI DSI support")
Reported-by: kernel test robot 
Closes: 
https://lore.kernel.org/oe-kbuild-all/202311151746.f7u7dzbz-...@intel.com/
Signed-off-by: Liu Ying 
---
v2:
* Initialize 'best_n' to UINT_MAX instead of zero. (Maxime)

 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c 
b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
index 3ff30ce80c5b..2347f8dd632f 100644
--- a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
@@ -226,8 +226,8 @@ dphy_pll_get_configure_from_opts(struct imx93_dsi *dsi,
unsigned long fout;
unsigned long best_fout = 0;
unsigned int fvco_div;
-   unsigned int min_n, max_n, n, best_n;
-   unsigned long m, best_m;
+   unsigned int min_n, max_n, n, best_n = UINT_MAX;
+   unsigned long m, best_m = 0;
unsigned long min_delta = ULONG_MAX;
unsigned long delta;
u64 tmp;
-- 
2.37.1



[PATCH] drm/bridge: panel: Check device dependency before managing device link

2023-11-22 Thread Liu Ying
Some panel devices already depend on DRM device, like the panel in
arch/arm/boot/dts/st/ste-ux500-samsung-skomer.dts, because DRM device is
the ancestor of those panel devices.  device_link_add() would fail by
returning a NULL pointer for those panel devices because of the existing
dependency.  So, check the dependency by calling device_is_dependent()
before adding or deleting device link between panel device and DRM device
so that the link is managed only for independent panel devices.

Fixes: 887878014534 ("drm/bridge: panel: Fix device link for 
DRM_BRIDGE_ATTACH_NO_CONNECTOR")
Fixes: 199cf07ebd2b ("drm/bridge: panel: Add a device link between drm device 
and panel device")
Reported-by: Linus Walleij 
Closes: 
https://lore.kernel.org/lkml/cacrpkdagzxd6hbix7mvunjajtmepg00pp6+nj1p0jrfj-ar...@mail.gmail.com/T/
Tested-by: Linus Walleij 
Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/panel.c | 27 ++-
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index e48823a4f1ed..5e8980023407 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -23,6 +23,7 @@ struct panel_bridge {
struct drm_panel *panel;
struct device_link *link;
u32 connector_type;
+   bool is_independent;
 };
 
 static inline struct panel_bridge *
@@ -67,12 +68,17 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
struct drm_device *drm_dev = bridge->dev;
int ret;
 
-   panel_bridge->link = device_link_add(drm_dev->dev, panel->dev,
-DL_FLAG_STATELESS);
-   if (!panel_bridge->link) {
-   DRM_ERROR("Failed to add device link between %s and %s\n",
- dev_name(drm_dev->dev), dev_name(panel->dev));
-   return -EINVAL;
+   panel_bridge->is_independent = !device_is_dependent(drm_dev->dev,
+   panel->dev);
+
+   if (panel_bridge->is_independent) {
+   panel_bridge->link = device_link_add(drm_dev->dev, panel->dev,
+DL_FLAG_STATELESS);
+   if (!panel_bridge->link) {
+   DRM_ERROR("Failed to add device link between %s and 
%s\n",
+ dev_name(drm_dev->dev), dev_name(panel->dev));
+   return -EINVAL;
+   }
}
 
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
@@ -80,7 +86,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 
if (!bridge->encoder) {
DRM_ERROR("Missing encoder\n");
-   device_link_del(panel_bridge->link);
+   if (panel_bridge->is_independent)
+   device_link_del(panel_bridge->link);
return -ENODEV;
}
 
@@ -92,7 +99,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 panel_bridge->connector_type);
if (ret) {
DRM_ERROR("Failed to initialize connector\n");
-   device_link_del(panel_bridge->link);
+   if (panel_bridge->is_independent)
+   device_link_del(panel_bridge->link);
return ret;
}
 
@@ -115,7 +123,8 @@ static void panel_bridge_detach(struct drm_bridge *bridge)
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
struct drm_connector *connector = _bridge->connector;
 
-   device_link_del(panel_bridge->link);
+   if (panel_bridge->is_independent)
+   device_link_del(panel_bridge->link);
 
/*
 * Cleanup the connector if we know it was initialized.
-- 
2.37.1



[PATCH] drm/bridge: imx93-mipi-dsi: Fix a couple of building warnings

2023-11-21 Thread Liu Ying
Fix a couple of building warnings on used uninitialized 'best_m' and
'best_n' local variables by initializing them to zero.  This makes compiler
happy only.  No functional change.

Fixes: ce62f8ea7e3f ("drm/bridge: imx: Add i.MX93 MIPI DSI support")
Reported-by: kernel test robot 
Closes: 
https://lore.kernel.org/oe-kbuild-all/202311151746.f7u7dzbz-...@intel.com/
Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c 
b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
index 3ff30ce80c5b..7b3b4f985098 100644
--- a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
@@ -226,8 +226,8 @@ dphy_pll_get_configure_from_opts(struct imx93_dsi *dsi,
unsigned long fout;
unsigned long best_fout = 0;
unsigned int fvco_div;
-   unsigned int min_n, max_n, n, best_n;
-   unsigned long m, best_m;
+   unsigned int min_n, max_n, n, best_n = 0;
+   unsigned long m, best_m = 0;
unsigned long min_delta = ULONG_MAX;
unsigned long delta;
u64 tmp;
-- 
2.37.1



[PATCH] drm/bridge: synopsys: dw-mipi-dsi: Fix hcomponent lbcc for burst mode

2023-10-17 Thread Liu Ying
In order to support burst mode, vendor drivers set lane_mbps higher than
bandwidth through DPI interface.  So, calculate horizontal component lane
byte clock cycle(lbcc) based on lane_mbps instead of pixel clock rate for
burst mode.

Fixes: ac87d23694f4 ("drm/bridge: synopsys: dw-mipi-dsi: Use pixel clock rate 
to calculate lbcc")
Reported-by: Heiko Stübner 
Closes: https://lore.kernel.org/linux-arm-kernel/5979575.UjTJXf6HLC@diego/T/#u
Tested-by: Heiko Stübner  # px30 minievb with xinpeng 
xpp055c272
Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 8789eca26188..824fb3c65742 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -774,13 +774,19 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct 
dw_mipi_dsi *dsi,
u32 frac, lbcc, minimum_lbcc;
int bpp;
 
-   bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
-   if (bpp < 0) {
-   dev_err(dsi->dev, "failed to get bpp\n");
-   return 0;
-   }
+   if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
+   /* lbcc based on lane_mbps */
+   lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8;
+   } else {
+   /* lbcc based on pixel clock rate */
+   bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+   if (bpp < 0) {
+   dev_err(dsi->dev, "failed to get bpp\n");
+   return 0;
+   }
 
-   lbcc = div_u64((u64)hcomponent * mode->clock * bpp, dsi->lanes * 8);
+   lbcc = div_u64((u64)hcomponent * mode->clock * bpp, dsi->lanes 
* 8);
+   }
 
frac = lbcc % mode->clock;
lbcc = lbcc / mode->clock;
-- 
2.37.1



[PATCH v14 RESEND 6/6] MAINTAINERS: add maintainer for i.MX8qxp DPU DRM driver

2023-08-22 Thread Liu Ying
Add myself as the maintainer of the i.MX8qxp DPU DRM driver.

Acked-by: Laurentiu Palcu 
Signed-off-by: Liu Ying 
---
v11->v14:
* No change.

v10->v11:
* Rebase upon v6.0-rc1.

v9->v10:
* Add Laurentiu's A-b tag.

v1->v9:
* No change.

 MAINTAINERS | 9 +
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 6308efa121e1..dc0a0d15edad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6918,6 +6918,15 @@ F:   
Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-link.yaml
 F: 
Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pxl2dpi.yaml
 F: drivers/gpu/drm/bridge/imx/
 
+DRM DRIVERS FOR FREESCALE i.MX8QXP
+M: Liu Ying 
+L: dri-devel@lists.freedesktop.org
+S: Maintained
+F: Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dprc.yaml
+F: Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dpu.yaml
+F: Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-prg.yaml
+F: drivers/gpu/drm/imx/dpu/
+
 DRM DRIVERS FOR GMA500 (Poulsbo, Moorestown and derivative chipsets)
 M: Patrik Jakobsson 
 L: dri-devel@lists.freedesktop.org
-- 
2.37.1



[PATCH v14 RESEND 3/6] dt-bindings: display: imx: Add i.MX8qxp/qm DPR channel binding

2023-08-22 Thread Liu Ying
This patch adds bindings for i.MX8qxp/qm Display Prefetch Resolve Channel.

Reviewed-by: Rob Herring 
Signed-off-by: Liu Ying 
---
v10->v14:
* No change.

v9->v10:
* Add Rob's R-b tag.

v8->v9:
* Reference 'interrupts-extended' schema instead of 'interrupts' to require
  an additional interrupt(r_rtram_stall) because the reference manual does
  mention it, though the driver doesn't get/use it for now.
  Reference 'interrupt-names' schema to define the two interrupt names -
  'dpr_wrap' and 'r_rtram_stall'.
* Drop Rob's R-b tag, as review is needed.

v4->v8:
* No change.

v3->v4:
* Improve compatible property by using enum instead of oneOf+const. (Rob)
* Add Rob's R-b tag.

v2->v3:
* No change.

v1->v2:
* Use new dt binding way to add clocks in the example.

 .../display/imx/fsl,imx8qxp-dprc.yaml | 100 ++
 1 file changed, 100 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dprc.yaml

diff --git 
a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dprc.yaml 
b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dprc.yaml
new file mode 100644
index ..bd94254c1288
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dprc.yaml
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dprc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX8qm/qxp Display Prefetch Resolve Channel
+
+maintainers:
+  - Liu Ying 
+
+description: |
+  The i.MX8qm/qxp Display Prefetch Resolve Channel(DPRC) is an engine which
+  fetches display data before the display pipeline needs the data to drive
+  pixels in the active display region.  This data is transformed, or resolved,
+  from a variety of tiled buffer formats into linear format, if needed.
+  The DPR works with a double bank memory structure.  This memory structure is
+  implemented in the Resolve Tile Memory(RTRAM) and the banks are referred to
+  as A and B.  Each bank is either 4 or 8 lines high depending on the source
+  frame buffer format.
+
+properties:
+  compatible:
+enum:
+  - fsl,imx8qxp-dpr-channel
+  - fsl,imx8qm-dpr-channel
+
+  reg:
+maxItems: 1
+
+  interrupts-extended:
+items:
+  - description: DPR wrap interrupt
+  - description: |
+  'r_rtram_stall' interrupt which indicates relevant i.MX8qm/qxp
+  Prefetch Resolve Gasket(PRG) or PRGs are forcing an underflow
+  condition in the RTRAM.
+
+  interrupt-names:
+items:
+  - const: dpr_wrap
+  - const: r_rtram_stall
+
+  clocks:
+items:
+  - description: apb clock
+  - description: b clock
+  - description: rtram clock
+
+  clock-names:
+items:
+  - const: apb
+  - const: b
+  - const: rtram
+
+  fsl,sc-resource:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: The SCU resource ID associated with this DPRC instance.
+
+  fsl,prgs:
+$ref: /schemas/types.yaml#/definitions/phandle-array
+description: |
+  List of phandle which points to PRG or PRGs associated with
+  this DPRC instance.
+
+  power-domains:
+maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts-extended
+  - interrupt-names
+  - clocks
+  - clock-names
+  - fsl,sc-resource
+  - fsl,prgs
+  - power-domains
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+dpr-channel@5610 {
+compatible = "fsl,imx8qxp-dpr-channel";
+reg = <0x5610 0x1>;
+interrupts-extended = < GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+  <_irqsteer 324>;
+interrupt-names = "dpr_wrap", "r_rtram_stall";
+clocks = <_dpr1_lpcg IMX_LPCG_CLK_4>,
+ <_dpr1_lpcg IMX_LPCG_CLK_5>,
+ <_rtram1_lpcg IMX_LPCG_CLK_0>;
+clock-names = "apb", "b", "rtram";
+fsl,sc-resource = ;
+fsl,prgs = <_prg4>, <_prg5>;
+power-domains = < IMX_SC_R_DC_0>;
+};
-- 
2.37.1



[PATCH v14 RESEND 4/6] drm/atomic: Avoid unused-but-set-variable warning on for_each_old_plane_in_state

2023-08-22 Thread Liu Ying
Artificially use 'plane' and 'old_plane_state' to avoid 'not used' warning.
The precedent has already been set by other macros in the same file.

Acked-by: Daniel Vetter 
Signed-off-by: Liu Ying 
---
v6->v14:
* No change.

v5->v6:
* Fix commit message typo - s/Artifically/Artificially/

v4->v5:
* No change.

v3->v4:
* Add Daniel's A-b tag.

v2->v3:
* Add a missing blank line.

v1->v2:
* No change.

 include/drm/drm_atomic.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index cf8e1220a4ac..33fcc38a1dc9 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -954,7 +954,10 @@ void drm_state_dump(struct drm_device *dev, struct 
drm_printer *p);
 (__i)++)   \
for_each_if ((__state)->planes[__i].ptr &&  \
 ((plane) = (__state)->planes[__i].ptr, \
- (old_plane_state) = 
(__state)->planes[__i].old_state, 1))
+ (void)(plane) /* Only to avoid 
unused-but-set-variable warning */, \
+ (old_plane_state) = 
(__state)->planes[__i].old_state, \
+ (void)(old_plane_state) /* Only to avoid 
unused-but-set-variable warning */, 1))
+
 /**
  * for_each_new_plane_in_state - iterate over all planes in an atomic update
  * @__state:  drm_atomic_state pointer
-- 
2.37.1



[PATCH v14 RESEND 2/6] dt-bindings: display: imx: Add i.MX8qxp/qm PRG binding

2023-08-22 Thread Liu Ying
This patch adds bindings for i.MX8qxp/qm Display Prefetch Resolve Gasket.

Reviewed-by: Rob Herring 
Signed-off-by: Liu Ying 
---
v4->v14:
* No change.

v3->v4:
* Improve compatible property by using enum instead of oneOf+const. (Rob)
* Add Rob's R-b tag.

v2->v3:
* No change.

v1->v2:
* Use new dt binding way to add clocks in the example.

 .../bindings/display/imx/fsl,imx8qxp-prg.yaml | 60 +++
 1 file changed, 60 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-prg.yaml

diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-prg.yaml 
b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-prg.yaml
new file mode 100644
index ..3ff46e0d4e73
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-prg.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-prg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX8qm/qxp Display Prefetch Resolve Gasket
+
+maintainers:
+  - Liu Ying 
+
+description: |
+  The i.MX8qm/qxp Prefetch Resolve Gasket (PRG) is a gasket interface between
+  RTRAM controller and Display Controller.  The main function is to convert
+  the AXI interface to the RTRAM interface, which includes re-mapping the
+  ARADDR to a RTRAM address.
+
+properties:
+  compatible:
+enum:
+  - fsl,imx8qxp-prg
+  - fsl,imx8qm-prg
+
+  reg:
+maxItems: 1
+
+  clocks:
+items:
+  - description: rtram clock
+  - description: apb clock
+
+  clock-names:
+items:
+  - const: rtram
+  - const: apb
+
+  power-domains:
+maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - power-domains
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+prg@5604 {
+compatible = "fsl,imx8qxp-prg";
+reg = <0x5604 0x1>;
+clocks = <_prg0_lpcg IMX_LPCG_CLK_0>,
+ <_prg0_lpcg IMX_LPCG_CLK_4>;
+clock-names = "rtram", "apb";
+power-domains = < IMX_SC_R_DC_0>;
+};
-- 
2.37.1



[PATCH v14 RESEND 1/6] dt-bindings: display: imx: Add i.MX8qxp/qm DPU binding

2023-08-22 Thread Liu Ying
This patch adds bindings for i.MX8qxp/qm Display Processing Unit.

Reviewed-by: Rob Herring 
Signed-off-by: Liu Ying 
---
v7->v14:
* No change.

v6->v7:
* Add Rob's R-b tag back.

v5->v6:
* Use graph schema. So, drop Rob's R-b tag as review is needed.

v4->v5:
* No change.

v3->v4:
* Improve compatible property by using enum instead of oneOf+const. (Rob)
* Add Rob's R-b tag.

v2->v3:
* No change.

v1->v2:
* Fix yamllint warnings.
* Require bypass0 and bypass1 clocks for both i.MX8qxp and i.MX8qm, as the
  display controller subsystem spec does say that they exist.
* Use new dt binding way to add clocks in the example.
* Trivial tweaks for the example.

 .../bindings/display/imx/fsl,imx8qxp-dpu.yaml | 387 ++
 1 file changed, 387 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dpu.yaml

diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dpu.yaml 
b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dpu.yaml
new file mode 100644
index ..6b05c586cd9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dpu.yaml
@@ -0,0 +1,387 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX8qm/qxp Display Processing Unit
+
+maintainers:
+  - Liu Ying 
+
+description: |
+  The Freescale i.MX8qm/qxp Display Processing Unit(DPU) is comprised of two
+  main components that include a blit engine for 2D graphics accelerations
+  and a display controller for display output processing, as well as a command
+  sequencer.
+
+properties:
+  compatible:
+enum:
+  - fsl,imx8qxp-dpu
+  - fsl,imx8qm-dpu
+
+  reg:
+maxItems: 1
+
+  interrupts:
+items:
+  - description: |
+  store9 shadow load interrupt(blit engine)
+  - description: |
+  store9 frame complete interrupt(blit engine)
+  - description: |
+  store9 sequence complete interrupt(blit engine)
+  - description: |
+  extdst0 shadow load interrupt
+  (display controller, content stream 0)
+  - description: |
+  extdst0 frame complete interrupt
+  (display controller, content stream 0)
+  - description: |
+  extdst0 sequence complete interrupt
+  (display controller, content stream 0)
+  - description: |
+  extdst4 shadow load interrupt
+  (display controller, safety stream 0)
+  - description: |
+  extdst4 frame complete interrupt
+  (display controller, safety stream 0)
+  - description: |
+  extdst4 sequence complete interrupt
+  (display controller, safety stream 0)
+  - description: |
+  extdst1 shadow load interrupt
+  (display controller, content stream 1)
+  - description: |
+  extdst1 frame complete interrupt
+  (display controller, content stream 1)
+  - description: |
+  extdst1 sequence complete interrupt
+  (display controller, content stream 1)
+  - description: |
+  extdst5 shadow load interrupt
+  (display controller, safety stream 1)
+  - description: |
+  extdst5 frame complete interrupt
+  (display controller, safety stream 1)
+  - description: |
+  extdst5 sequence complete interrupt
+  (display controller, safety stream 1)
+  - description: |
+  disengcfg0 shadow load interrupt
+  (display controller, display stream 0)
+  - description: |
+  disengcfg0 frame complete interrupt
+  (display controller, display stream 0)
+  - description: |
+  disengcfg0 sequence complete interrupt
+  (display controller, display stream 0)
+  - description: |
+  framegen0 programmable interrupt0
+  (display controller, display stream 0)
+  - description: |
+  framegen0 programmable interrupt1
+  (display controller, display stream 0)
+  - description: |
+  framegen0 programmable interrupt2
+  (display controller, display stream 0)
+  - description: |
+  framegen0 programmable interrupt3
+  (display controller, display stream 0)
+  - description: |
+  signature0 shadow load interrupt
+  (display controller, display stream 0)
+  - description: |
+  signature0 measurement valid interrupt
+  (display controller, display stream 0)
+  - description: |
+  signature0 error condition interrupt
+  (display controller, display stream 0)
+  - description: |
+  disengcfg1 shadow load interrupt
+  (display controller, display stream 1)
+  - description: |
+  disengcfg1 frame complete interrupt
+  (display controller, display stream 1)

[PATCH v14 RESEND 0/6] drm/imx: Introduce i.MX8qm/qxp DPU DRM

2023-08-22 Thread Liu Ying
s error.
* Drop calling dev_set_drvdata() from dpu_drm_bind/unbind() in the DPU DRM
  driver as it is done in dpu_drm_probe().
* Some trivial tweaks.

v4->v5:
* Rebase up onto the latest drm-misc-next branch and remove the hook to
  drm_atomic_helper_legacy_gamma_set() from patch 5/6, because it was dropped
  by the newly landed commit 'drm: automatic legacy gamma support'.
* Remove a redundant blank line from dpu_plane_atomic_update() in patch 5/6.

v3->v4:
* Improve compatible properties in DPU and prefetch engines' dt bindings
  by using enum instead of oneOf+const.
* Add Rob's R-b tags on dt binding patches(patch 1/6, 2/6 and 3/6).
* Add Daniel's A-b tag on patch 4/6.

v2->v3:
* Fix DPU DRM driver build warnings which are
  Reported-by: kernel test robot .
* Drop DPU DRM driver build dependency on IMX_SCU, as dummy SCU functions have
  been added in header files by the patch 'firmware: imx: add dummy functions'
  which has landed in linux-next/master branch.
* Add a missing blank line in include/drm/drm_atomic.h.

v1->v2:
* Test this patch set also with i.MX8qm LVDS displays.
* Drop the device tree patches because we'll use new dt binding way to
  support i.MX8qm/qxp clocks.  This depends on a not-yet-landed patch set
  to do basic conversions for the platforms.
* Fix dt binding yamllint warnings.
* Require bypass0 and bypass1 clocks for both i.MX8qxp and i.MX8qm in DPU's
  dt binding documentation.
* Use new dt binding way to add clocks in the dt binding examples.
* Address several comments from Laurentiu on the DPU DRM patch.


Liu Ying (6):
  dt-bindings: display: imx: Add i.MX8qxp/qm DPU binding
  dt-bindings: display: imx: Add i.MX8qxp/qm PRG binding
  dt-bindings: display: imx: Add i.MX8qxp/qm DPR channel binding
  drm/atomic: Avoid unused-but-set-variable warning on
for_each_old_plane_in_state
  drm/imx: Introduce i.MX8qm/qxp DPU DRM
  MAINTAINERS: add maintainer for i.MX8qxp DPU DRM driver

 .../display/imx/fsl,imx8qxp-dprc.yaml |  100 ++
 .../bindings/display/imx/fsl,imx8qxp-dpu.yaml |  387 ++
 .../bindings/display/imx/fsl,imx8qxp-prg.yaml |   60 +
 MAINTAINERS   |9 +
 drivers/gpu/drm/imx/Kconfig   |1 +
 drivers/gpu/drm/imx/Makefile  |1 +
 drivers/gpu/drm/imx/dpu/Kconfig   |9 +
 drivers/gpu/drm/imx/dpu/Makefile  |   10 +
 drivers/gpu/drm/imx/dpu/dpu-constframe.c  |  171 +++
 drivers/gpu/drm/imx/dpu/dpu-core.c| 1044 +
 drivers/gpu/drm/imx/dpu/dpu-crtc.c|  969 +++
 drivers/gpu/drm/imx/dpu/dpu-crtc.h|   72 ++
 drivers/gpu/drm/imx/dpu/dpu-disengcfg.c   |  117 ++
 drivers/gpu/drm/imx/dpu/dpu-dprc.c|  715 +++
 drivers/gpu/drm/imx/dpu/dpu-dprc.h|   40 +
 drivers/gpu/drm/imx/dpu/dpu-drv.c |  294 +
 drivers/gpu/drm/imx/dpu/dpu-drv.h |   28 +
 drivers/gpu/drm/imx/dpu/dpu-extdst.c  |  299 +
 drivers/gpu/drm/imx/dpu/dpu-fetchdecode.c |  292 +
 drivers/gpu/drm/imx/dpu/dpu-fetcheco.c|  224 
 drivers/gpu/drm/imx/dpu/dpu-fetchlayer.c  |  152 +++
 drivers/gpu/drm/imx/dpu/dpu-fetchunit.c   |  610 ++
 drivers/gpu/drm/imx/dpu/dpu-fetchunit.h   |  195 +++
 drivers/gpu/drm/imx/dpu/dpu-fetchwarp.c   |  248 
 drivers/gpu/drm/imx/dpu/dpu-framegen.c|  395 +++
 drivers/gpu/drm/imx/dpu/dpu-gammacor.c|  223 
 drivers/gpu/drm/imx/dpu/dpu-hscaler.c |  275 +
 drivers/gpu/drm/imx/dpu/dpu-kms.c |  542 +
 drivers/gpu/drm/imx/dpu/dpu-kms.h |   23 +
 drivers/gpu/drm/imx/dpu/dpu-layerblend.c  |  348 ++
 drivers/gpu/drm/imx/dpu/dpu-plane.c   |  804 +
 drivers/gpu/drm/imx/dpu/dpu-plane.h   |   59 +
 drivers/gpu/drm/imx/dpu/dpu-prg.c |  433 +++
 drivers/gpu/drm/imx/dpu/dpu-prg.h |   45 +
 drivers/gpu/drm/imx/dpu/dpu-prv.h |  231 
 drivers/gpu/drm/imx/dpu/dpu-tcon.c|  250 
 drivers/gpu/drm/imx/dpu/dpu-vscaler.c |  308 +
 drivers/gpu/drm/imx/dpu/dpu.h |  385 ++
 include/drm/drm_atomic.h  |5 +-
 39 files changed, 10372 insertions(+), 1 deletion(-)
 create mode 100644 
Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dprc.yaml
 create mode 100644 
Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dpu.yaml
 create mode 100644 
Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-prg.yaml
 create mode 100644 drivers/gpu/drm/imx/dpu/Kconfig
 create mode 100644 drivers/gpu/drm/imx/dpu/Makefile
 create mode 100644 drivers/gpu/drm/imx/dpu/dpu-constframe.c
 create mode 100644 drivers/gpu/drm/imx/dpu/dpu-core.c
 create mode 100644 drivers/gpu/drm/imx/dpu/dpu-crtc.c
 create mode 100644 drivers/gpu/drm/imx/dpu/dpu-crtc.h
 create mode 100644 drivers/gpu/drm/imx/dpu/dpu-disengcfg.c
 create mode 100

[PATCH v3 RESEND 9/9] drm/bridge: imx: Add i.MX93 MIPI DSI support

2023-08-20 Thread Liu Ying
Freescale i.MX93 SoC embeds a Synopsys Designware MIPI DSI host
controller and a Synopsys Designware MIPI DPHY.  Some configurations
and extensions to them are controlled by i.MX93 media blk-ctrl.

Add a DRM bridge for i.MX93 MIPI DSI by using existing DW MIPI DSI
bridge helpers and implementing i.MX93 MIPI DSI specific extensions.

Signed-off-by: Liu Ying 
---
v2->v3:
* Select GENERIC_PHY to fix Kconfig warning for GENERIC_PHY_MIPI_DPHY
  dependency.

v1->v2:
* Use dev_err_probe() to replace DRM_DEV_ERROR().  (Sam and Alexander)
* Use dev_*() to replace DRM_*().  (Sam)
* Fix build for arm architecture.
  (Reported-by: kernel test robot )
* Improve error messages for imx93_dsi_phy_init().

 drivers/gpu/drm/bridge/imx/Kconfig  |  11 +
 drivers/gpu/drm/bridge/imx/Makefile |   1 +
 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c | 917 
 3 files changed, 929 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c

diff --git a/drivers/gpu/drm/bridge/imx/Kconfig 
b/drivers/gpu/drm/bridge/imx/Kconfig
index 9fae28db6aa7..5a4f3d58501e 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -49,4 +49,15 @@ config DRM_IMX8QXP_PIXEL_LINK_TO_DPI
  Choose this to enable pixel link to display pixel interface(PXL2DPI)
  found in Freescale i.MX8qxp processor.
 
+config DRM_IMX93_MIPI_DSI
+   tristate "Freescale i.MX93 specific extensions for Synopsys DW MIPI DSI"
+   depends on OF
+   depends on COMMON_CLK
+   select DRM_DW_MIPI_DSI
+   select GENERIC_PHY
+   select GENERIC_PHY_MIPI_DPHY
+   help
+ Choose this to enable MIPI DSI controller found in Freescale i.MX93
+ processor.
+
 endif # ARCH_MXC || COMPILE_TEST
diff --git a/drivers/gpu/drm/bridge/imx/Makefile 
b/drivers/gpu/drm/bridge/imx/Makefile
index 8e2ebf3399a1..2b0c2e44aa1b 100644
--- a/drivers/gpu/drm/bridge/imx/Makefile
+++ b/drivers/gpu/drm/bridge/imx/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_DRM_IMX8QXP_LDB) += imx8qxp-ldb.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o
+obj-$(CONFIG_DRM_IMX93_MIPI_DSI) += imx93-mipi-dsi.o
diff --git a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c 
b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
new file mode 100644
index ..3ff30ce80c5b
--- /dev/null
+++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
@@ -0,0 +1,917 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2022,2023 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/* DPHY PLL configuration registers */
+#define DSI_REG0x4c
+#define  CFGCLKFREQRANGE_MASK  GENMASK(5, 0)
+#define  CFGCLKFREQRANGE(x)FIELD_PREP(CFGCLKFREQRANGE_MASK, (x))
+#define  CLKSEL_MASK   GENMASK(7, 6)
+#define  CLKSEL_STOP   FIELD_PREP(CLKSEL_MASK, 0)
+#define  CLKSEL_GENFIELD_PREP(CLKSEL_MASK, 1)
+#define  CLKSEL_EXTFIELD_PREP(CLKSEL_MASK, 2)
+#define  HSFREQRANGE_MASK  GENMASK(14, 8)
+#define  HSFREQRANGE(x)FIELD_PREP(HSFREQRANGE_MASK, 
(x))
+#define  UPDATE_PLLBIT(17)
+#define  SHADOW_CLRBIT(18)
+#define  CLK_EXT   BIT(19)
+
+#define DSI_WRITE_REG0 0x50
+#define  M_MASKGENMASK(9, 0)
+#define  M(x)  FIELD_PREP(M_MASK, ((x) - 2))
+#define  N_MASKGENMASK(13, 10)
+#define  N(x)  FIELD_PREP(N_MASK, ((x) - 1))
+#define  VCO_CTRL_MASK GENMASK(19, 14)
+#define  VCO_CTRL(x)   FIELD_PREP(VCO_CTRL_MASK, (x))
+#define  PROP_CTRL_MASKGENMASK(25, 20)
+#define  PROP_CTRL(x)  FIELD_PREP(PROP_CTRL_MASK, (x))
+#define  INT_CTRL_MASK GENMASK(31, 26)
+#define  INT_CTRL(x)   FIELD_PREP(INT_CTRL_MASK, (x))
+
+#define DSI_WRITE_REG1 0x54
+#define  GMP_CTRL_MASK GENMASK(1, 0)
+#define  GMP_CTRL(x)   FIELD_PREP(GMP_CTRL_MASK, (x))
+#define  CPBIAS_CTRL_MASK  GENMASK(8, 2)
+#define  CPBIAS_CTRL(x)FIELD_PREP(CPBIAS_CTRL_MASK, 
(x))
+#define  PLL_SHADOW_CTRL   BIT(9)
+
+/* display mux control register */
+#define DISPLAY_MUX0x60
+#define  MIPI_DSI_RGB666_MAP_CFG   GENMASK(7, 6)
+#define  RGB666_CONFIG1
FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 0)
+#define  RGB666_CONFIG2
FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 1)
+#define  MIPI_DSI_RGB565_MAP_CFG   

[PATCH v3 RESEND 8/9] dt-bindings: display: bridge: Document Freescale i.MX93 MIPI DSI

2023-08-20 Thread Liu Ying
Freescale i.MX93 SoC embeds a Synopsys Designware MIPI DSI host
controller and a Synopsys Designware MIPI DPHY.  Some configurations
and extensions to them are controlled by i.MX93 media blk-ctrl.

Signed-off-by: Liu Ying 
Reviewed-by: Rob Herring 
---
v2->v3:
* No change.

v1->v2:
* Add Rob's R-b tag.

 .../display/bridge/fsl,imx93-mipi-dsi.yaml| 115 ++
 1 file changed, 115 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml

diff --git 
a/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml 
b/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
new file mode 100644
index ..d6e51d0cf546
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/fsl,imx93-mipi-dsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX93 specific extensions to Synopsys Designware MIPI DSI
+
+maintainers:
+  - Liu Ying 
+
+description: |
+  There is a Synopsys Designware MIPI DSI Host Controller and a Synopsys
+  Designware MIPI DPHY embedded in Freescale i.MX93 SoC.  Some configurations
+  and extensions to them are controlled by i.MX93 media blk-ctrl.
+
+allOf:
+  - $ref: snps,dw-mipi-dsi.yaml#
+
+properties:
+  compatible:
+const: fsl,imx93-mipi-dsi
+
+  clocks:
+items:
+  - description: apb clock
+  - description: pixel clock
+  - description: PHY configuration clock
+  - description: PHY reference clock
+
+  clock-names:
+items:
+  - const: pclk
+  - const: pix
+  - const: phy_cfg
+  - const: phy_ref
+
+  interrupts:
+maxItems: 1
+
+  fsl,media-blk-ctrl:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  i.MX93 media blk-ctrl, as a syscon, controls pixel component bit map
+  configurations from LCDIF display controller to the MIPI DSI host
+  controller and MIPI DPHY PLL related configurations through PLL SoC
+  interface.
+
+  power-domains:
+maxItems: 1
+
+required:
+  - compatible
+  - interrupts
+  - fsl,media-blk-ctrl
+  - power-domains
+
+unevaluatedProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+#include 
+
+dsi@4ae1 {
+compatible = "fsl,imx93-mipi-dsi";
+reg = <0x4ae1 0x1>;
+interrupts = ;
+clocks = < IMX93_CLK_MIPI_DSI_GATE>,
+ < IMX93_CLK_MEDIA_DISP_PIX>,
+ < IMX93_CLK_MIPI_PHY_CFG>,
+ < IMX93_CLK_24M>;
+clock-names = "pclk", "pix", "phy_cfg", "phy_ref";
+fsl,media-blk-ctrl = <_blk_ctrl>;
+power-domains = <_blk_ctrl IMX93_MEDIABLK_PD_MIPI_DSI>;
+#address-cells = <1>;
+#size-cells = <0>;
+
+panel@0 {
+compatible = "raydium,rm67191";
+reg = <0>;
+reset-gpios = < 6 GPIO_ACTIVE_LOW>;
+dsi-lanes = <4>;
+video-mode = <2>;
+
+port {
+panel_in: endpoint {
+remote-endpoint = <_out>;
+};
+};
+};
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+
+dsi_to_lcdif: endpoint {
+remote-endpoint = <_to_dsi>;
+};
+};
+
+port@1 {
+reg = <1>;
+
+dsi_out: endpoint {
+remote-endpoint = <_in>;
+};
+};
+};
+};
-- 
2.37.1



[PATCH v3 RESEND 7/9] drm/bridge: synopsys: dw-mipi-dsi: Disable HSTX and LPRX timeout check

2023-08-20 Thread Liu Ying
According to Synopsys DW MIPI DSI host databook, HSTX and LPRX timeout
contention detections are measured in TO_CLK_DIVISION cycles.  However,
the current driver programs magic values to TO_CLK_DIVISION, HSTX_TO_CNT
and LPRX_TO_CNT register fields, which makes timeout error event wrongly
happen for some video modes, at least for the typical 1920x1080p@60 video
mode read from a HDMI monitor driven by ADV7535 DSI to HDMI bridge.
While at it, the current driver doesn't enable interrupt to handle or
complain about the error status, so true error just happens silently
except for display distortions by visual check.

Disable the timeout check by setting those timeout register fields to
zero for now until someone comes along with better computations for the
timeout values.  Although the databook doesn't mention what happens when
they are set to zero, it turns out the false error doesn't happen for
the 1920x1080p@60 video mode at least.

Signed-off-by: Liu Ying 
Reviewed-by: Neil Armstrong 
---
v2->v3:
* Add Neil's R-b tag from v1.

v1->v2:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index c10ca32dff0b..9af97895c243 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -686,7 +686,7 @@ static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi)
 * timeout clock division should be computed with the
 * high speed transmission counter timeout and byte lane...
 */
-   dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVISION(10) |
+   dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVISION(0) |
  TX_ESC_CLK_DIVISION(esc_clk_division));
 }
 
@@ -749,7 +749,7 @@ static void dw_mipi_dsi_command_mode_config(struct 
dw_mipi_dsi *dsi)
 * compute high speed transmission counter timeout according
 * to the timeout clock division (TO_CLK_DIVISION) and byte lane...
 */
-   dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(1000) | LPRX_TO_CNT(1000));
+   dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(0) | LPRX_TO_CNT(0));
/*
 * TODO dw drv improvements
 * the Bus-Turn-Around Timeout Counter should be computed
-- 
2.37.1



[PATCH v3 RESEND 6/9] drm/bridge: synopsys: dw-mipi-dsi: Set minimum lane byte clock cycles for HSA and HBP

2023-08-20 Thread Liu Ying
According to Synopsys support channel, each region of HSA, HBP and HFP must
have minimum number of 10 bytes where constant 4 bytes are for HSS or HSE
and 6 bytes are for blanking packet(header + CRC).  Hence, the below table
comes in.

++--+---+
| data lanes | min lbcc | bytes |
++--+---+
| 1  |10|  1*10 |
++--+---+
| 2  |5 |  2*5  |
++--+---+
| 3  |4 |  3*4  |
++--+---+
| 4  |3 |  4*3  |
++--+---+

Implement the minimum lbcc numbers to make sure that the values programmed
into DSI_VID_HSA_TIME and DSI_VID_HBP_TIME registers meet the minimum
number requirement.  For DSI_VID_HLINE_TIME register, it seems that the
value programmed should be based on mode->htotal as-is, instead of sum up
HSA, HBP, HFP and HDISPLAY.

This helps the case where Raydium RM67191 DSI panel is connected, since
it's video timing for hsync length is only 2 pixels and without this patch
the programmed value for DSI_VID_HSA_TIME is only 2 with 4 data lanes.

Signed-off-by: Liu Ying 
Reviewed-by: Neil Armstrong 
---
v2->v3:
* Add Neil's R-b tag from v1.

v1->v2:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 18e7d64b0216..c10ca32dff0b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -759,12 +759,19 @@ static void dw_mipi_dsi_command_mode_config(struct 
dw_mipi_dsi *dsi)
dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
 }
 
+static const u32 minimum_lbccs[] = {10, 5, 4, 3};
+
+static inline u32 dw_mipi_dsi_get_minimum_lbcc(struct dw_mipi_dsi *dsi)
+{
+   return minimum_lbccs[dsi->lanes - 1];
+}
+
 /* Get lane byte clock cycles. */
 static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi,
   const struct drm_display_mode *mode,
   u32 hcomponent)
 {
-   u32 frac, lbcc;
+   u32 frac, lbcc, minimum_lbcc;
int bpp;
 
bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
@@ -780,6 +787,11 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct 
dw_mipi_dsi *dsi,
if (frac)
lbcc++;
 
+   minimum_lbcc = dw_mipi_dsi_get_minimum_lbcc(dsi);
+
+   if (lbcc < minimum_lbcc)
+   lbcc = minimum_lbcc;
+
return lbcc;
 }
 
-- 
2.37.1



[PATCH v3 RESEND 5/9] drm/bridge: synopsys: dw-mipi-dsi: Use pixel clock rate to calculate lbcc

2023-08-20 Thread Liu Ying
To get better accuration, use pixel clock rate to calculate lbcc instead of
lane_mbps since the pixel clock rate is in KHz while lane_mbps is in MHz.
Without this, distorted image can be seen on a HDMI monitor connected with
i.MX93 11x11 EVK through ADV7535 DSI to HDMI bridge in 1920x1080p@60 video
mode.

Signed-off-by: Liu Ying 
Reviewed-by: Neil Armstrong 
---
v2->v3:
* Add Neil's R-b tag from v1.

v1->v2:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index b2da803c9de7..18e7d64b0216 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -764,8 +765,15 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct 
dw_mipi_dsi *dsi,
   u32 hcomponent)
 {
u32 frac, lbcc;
+   int bpp;
 
-   lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8;
+   bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+   if (bpp < 0) {
+   dev_err(dsi->dev, "failed to get bpp\n");
+   return 0;
+   }
+
+   lbcc = div_u64((u64)hcomponent * mode->clock * bpp, dsi->lanes * 8);
 
frac = lbcc % mode->clock;
lbcc = lbcc / mode->clock;
-- 
2.37.1



[PATCH v3 RESEND 4/9] drm/bridge: synopsys: dw-mipi-dsi: Add mode fixup support

2023-08-20 Thread Liu Ying
Vendor drivers may need to fixup mode due to pixel clock tree limitation,
so introduce the ->mode_fixup() callcack to struct dw_mipi_dsi_plat_data
and call it at atomic check stage if available.

Signed-off-by: Liu Ying 
---
v1->v3:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 14 ++
 include/drm/bridge/dw_mipi_dsi.h  |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index ed9288a9c444..b2da803c9de7 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -573,9 +573,23 @@ static int dw_mipi_dsi_bridge_atomic_check(struct 
drm_bridge *bridge,
   struct drm_crtc_state *crtc_state,
   struct drm_connector_state 
*conn_state)
 {
+   struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
+   const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
+   bool ret;
+
bridge_state->input_bus_cfg.flags =
DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
 
+   if (pdata->mode_fixup) {
+   ret = pdata->mode_fixup(pdata->priv_data, _state->mode,
+   _state->adjusted_mode);
+   if (!ret) {
+   DRM_DEBUG_DRIVER("failed to fixup mode " DRM_MODE_FMT 
"\n",
+DRM_MODE_ARG(_state->mode));
+   return -EINVAL;
+   }
+   }
+
return 0;
 }
 
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index 246650f2814f..65d5e68065e3 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -59,6 +59,9 @@ struct dw_mipi_dsi_plat_data {
   unsigned long mode_flags,
   u32 lanes, u32 format);
 
+   bool (*mode_fixup)(void *priv_data, const struct drm_display_mode *mode,
+  struct drm_display_mode *adjusted_mode);
+
u32 *(*get_input_bus_fmts)(void *priv_data,
   struct drm_bridge *bridge,
   struct drm_bridge_state *bridge_state,
-- 
2.37.1



[PATCH v3 RESEND 3/9] drm/bridge: synopsys: dw-mipi-dsi: Force input bus flags

2023-08-20 Thread Liu Ying
The DATAEN_ACTIVE_LOW bit in DSI_DPI_CFG_POL register is set to zero,
so set the DRM_BUS_FLAG_DE_HIGH flag in input_bus_cfg.flags.  It appears
that the DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE flag also makes sense, so
set it in input_bus_cfg.flags too.  With this patch, the flags set by
drm_atomic_bridge_propagate_bus_flags() are overridden (see comment in
that function) in case any downstream bridges propagates invalid flags
to this bridge.  A real problematic case is to connect a RM67191 MIPI
DSI panel whose driver sets DRM_BUS_FLAG_DE_LOW and
DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE bus flags.

Signed-off-by: Liu Ying 
---
v1->v3:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 945d46a76995..ed9288a9c444 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -567,6 +568,17 @@ dw_mipi_dsi_bridge_atomic_get_input_bus_fmts(struct 
drm_bridge *bridge,
return input_fmts;
 }
 
+static int dw_mipi_dsi_bridge_atomic_check(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*bridge_state,
+  struct drm_crtc_state *crtc_state,
+  struct drm_connector_state 
*conn_state)
+{
+   bridge_state->input_bus_cfg.flags =
+   DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
+
+   return 0;
+}
+
 static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
 {
u32 val;
@@ -1036,6 +1048,7 @@ static const struct drm_bridge_funcs 
dw_mipi_dsi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_bridge_destroy_state,
.atomic_get_input_bus_fmts = 
dw_mipi_dsi_bridge_atomic_get_input_bus_fmts,
+   .atomic_check   = dw_mipi_dsi_bridge_atomic_check,
.atomic_reset   = drm_atomic_helper_bridge_reset,
.atomic_pre_enable  = dw_mipi_dsi_bridge_atomic_pre_enable,
.atomic_enable  = dw_mipi_dsi_bridge_atomic_enable,
-- 
2.37.1



[PATCH v3 RESEND 2/9] drm/bridge: synopsys: dw-mipi-dsi: Add input bus format negotiation support

2023-08-20 Thread Liu Ying
Introduce ->get_input_bus_fmts() callback to struct dw_mipi_dsi_plat_data
so that vendor drivers can implement specific methods to get input bus
formats for Synopsys DW MIPI DSI.

While at it, implement a generic callback for ->atomic_get_input_bus_fmts(),
where we try to get the input bus formats through pdata->get_input_bus_fmts()
first.  If it's unavailable, fall back to the only format - MEDIA_BUS_FMT_FIXED,
which matches the default behavior if ->atomic_get_input_bus_fmts() is not
implemented as ->atomic_get_input_bus_fmts()'s kerneldoc indicates.

Signed-off-by: Liu Ying 
---
v1->v3:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 30 +++
 include/drm/bridge/dw_mipi_dsi.h  | 11 +++
 2 files changed, 41 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index ba3cd2a3e339..945d46a76995 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -538,6 +539,34 @@ static const struct mipi_dsi_host_ops dw_mipi_dsi_host_ops 
= {
.transfer = dw_mipi_dsi_host_transfer,
 };
 
+static u32 *
+dw_mipi_dsi_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+struct drm_bridge_state 
*bridge_state,
+struct drm_crtc_state *crtc_state,
+struct drm_connector_state 
*conn_state,
+u32 output_fmt,
+unsigned int *num_input_fmts)
+{
+   struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
+   const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
+   u32 *input_fmts;
+
+   if (pdata->get_input_bus_fmts)
+   return pdata->get_input_bus_fmts(pdata->priv_data,
+bridge, bridge_state,
+crtc_state, conn_state,
+output_fmt, num_input_fmts);
+
+   /* Fall back to MEDIA_BUS_FMT_FIXED as the only input format. */
+   input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+   input_fmts[0] = MEDIA_BUS_FMT_FIXED;
+   *num_input_fmts = 1;
+
+   return input_fmts;
+}
+
 static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
 {
u32 val;
@@ -1006,6 +1035,7 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge 
*bridge,
 static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_bridge_destroy_state,
+   .atomic_get_input_bus_fmts = 
dw_mipi_dsi_bridge_atomic_get_input_bus_fmts,
.atomic_reset   = drm_atomic_helper_bridge_reset,
.atomic_pre_enable  = dw_mipi_dsi_bridge_atomic_pre_enable,
.atomic_enable  = dw_mipi_dsi_bridge_atomic_enable,
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index f54621b17a69..246650f2814f 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -11,7 +11,10 @@
 
 #include 
 
+#include 
 #include 
+#include 
+#include 
 #include 
 
 struct drm_display_mode;
@@ -56,6 +59,14 @@ struct dw_mipi_dsi_plat_data {
   unsigned long mode_flags,
   u32 lanes, u32 format);
 
+   u32 *(*get_input_bus_fmts)(void *priv_data,
+  struct drm_bridge *bridge,
+  struct drm_bridge_state *bridge_state,
+  struct drm_crtc_state *crtc_state,
+  struct drm_connector_state *conn_state,
+  u32 output_fmt,
+  unsigned int *num_input_fmts);
+
const struct dw_mipi_dsi_phy_ops *phy_ops;
const struct dw_mipi_dsi_host_ops *host_ops;
 
-- 
2.37.1



[PATCH v3 RESEND 1/9] drm/bridge: synopsys: dw-mipi-dsi: Add dw_mipi_dsi_get_bridge() helper

2023-08-20 Thread Liu Ying
Add dw_mipi_dsi_get_bridge() helper so that it can be used by vendor
drivers which implement vendor specific extensions to Synopsys DW MIPI DSI.

Signed-off-by: Liu Ying 
---
v1->v3:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 6 ++
 include/drm/bridge/dw_mipi_dsi.h  | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 04d4a1a10698..ba3cd2a3e339 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -1211,6 +1211,12 @@ void dw_mipi_dsi_set_slave(struct dw_mipi_dsi *dsi, 
struct dw_mipi_dsi *slave)
 }
 EXPORT_SYMBOL_GPL(dw_mipi_dsi_set_slave);
 
+struct drm_bridge *dw_mipi_dsi_get_bridge(struct dw_mipi_dsi *dsi)
+{
+   return >bridge;
+}
+EXPORT_SYMBOL_GPL(dw_mipi_dsi_get_bridge);
+
 /*
  * Probe/remove API, used from platforms based on the DRM bridge API.
  */
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index 5286a53a1875..f54621b17a69 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -11,6 +11,7 @@
 
 #include 
 
+#include 
 #include 
 
 struct drm_display_mode;
@@ -68,5 +69,6 @@ void dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi);
 int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder);
 void dw_mipi_dsi_unbind(struct dw_mipi_dsi *dsi);
 void dw_mipi_dsi_set_slave(struct dw_mipi_dsi *dsi, struct dw_mipi_dsi *slave);
+struct drm_bridge *dw_mipi_dsi_get_bridge(struct dw_mipi_dsi *dsi);
 
 #endif /* __DW_MIPI_DSI__ */
-- 
2.37.1



[PATCH v3 RESEND 0/9] drm/bridge: imx: Add i.MX93 MIPI DSI support

2023-08-20 Thread Liu Ying
Hi,

This series aims to add MIPI DSI support for Freescale i.MX93 SoC.

There is a Synopsys DesignWare MIPI DSI host controller and a Synopsys
Designware MIPI DPHY embedded in i.MX93.  Some configurations and
extensions to them are controlled by i.MX93 media blk-ctrl.

Add a DRM bridge for i.MX93 MIPI DSI by using existing DW MIPI DSI
bridge helpers and implementing i.MX93 MIPI DSI specific extensions.

Note that since this series touches the dw-mipi-dsi driver, tests are
needed to be done for meson, rockchip and stm.

Patch 1 ~ 7 do preparation work for adding i.MX93 MIPI DSI DRM bridge driver.

Patch 8 adds DT-binding documentation for i.MX93 MIPI DSI.

Patch 9 adds i.MX93 MIPI DSI DRM bridge.

v2->v3:
* Add Neil's R-b tags from v1 on patch 5/6/7.
* Select GENERIC_PHY to fix Kconfig warning for GENERIC_PHY_MIPI_DPHY
  dependency in patch 9.
* Cc stm and rockchip folks.
* Resend based on the latest drm-misc-next.

v1->v2:
* Add Rob's R-b tag on patch 8.
* Use dev_err_probe() to replace DRM_DEV_ERROR() in patch 9.  (Sam and 
Alexander)
* Use dev_*() to replace DRM_*() in patch 9.  (Sam)
* Fix build for arm architecture in patch 9.
  (Reported-by: kernel test robot )
* Improve error messages for imx93_dsi_phy_init() in patch 9.

Liu Ying (9):
  drm/bridge: synopsys: dw-mipi-dsi: Add dw_mipi_dsi_get_bridge() helper
  drm/bridge: synopsys: dw-mipi-dsi: Add input bus format negotiation
support
  drm/bridge: synopsys: dw-mipi-dsi: Force input bus flags
  drm/bridge: synopsys: dw-mipi-dsi: Add mode fixup support
  drm/bridge: synopsys: dw-mipi-dsi: Use pixel clock rate to calculate
lbcc
  drm/bridge: synopsys: dw-mipi-dsi: Set minimum lane byte clock cycles
for HSA and HBP
  drm/bridge: synopsys: dw-mipi-dsi: Disable HSTX and LPRX timeout check
  dt-bindings: display: bridge: Document Freescale i.MX93 MIPI DSI
  drm/bridge: imx: Add i.MX93 MIPI DSI support

 .../display/bridge/fsl,imx93-mipi-dsi.yaml| 115 +++
 drivers/gpu/drm/bridge/imx/Kconfig|  11 +
 drivers/gpu/drm/bridge/imx/Makefile   |   1 +
 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c   | 917 ++
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c |  91 +-
 include/drm/bridge/dw_mipi_dsi.h  |  16 +
 6 files changed, 1147 insertions(+), 4 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c

 base-commit: 25205087df1ffe06ccea9302944ed1f77dc68c6f

-- 
2.37.1



[PATCH v3] drm/bridge: panel: Add a device link between drm device and panel device

2023-08-07 Thread Liu Ying
Add the device link when panel bridge is attached and delete the link
when panel bridge is detached.  The drm device is the consumer while
the panel device is the supplier.  This makes sure that the drm device
suspends eariler and resumes later than the panel device, hence resolves
problems where the order is reversed, like the problematic case mentioned
in the below link.

Link: 
https://lore.kernel.org/lkml/capdykfr0xjru_udkoukq_q8rwaukyql+8fv-7s1ctmqi7u3...@mail.gmail.com/T/
Suggested-by: Ulf Hansson 
Signed-off-by: Liu Ying 
---
v2->v3:
* Improve commit message s/swapped/reversed/.

v1->v2:
* Fix bailout for panel_bridge_attach() in case device_link_add() fails.

 drivers/gpu/drm/bridge/panel.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 9316384b4474..a6587d233505 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -4,6 +4,8 @@
  * Copyright (C) 2017 Broadcom
  */
 
+#include 
+
 #include 
 #include 
 #include 
@@ -19,6 +21,7 @@ struct panel_bridge {
struct drm_bridge bridge;
struct drm_connector connector;
struct drm_panel *panel;
+   struct device_link *link;
u32 connector_type;
 };
 
@@ -60,6 +63,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
struct drm_connector *connector = _bridge->connector;
+   struct drm_panel *panel = panel_bridge->panel;
+   struct drm_device *drm_dev = bridge->dev;
int ret;
 
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
@@ -70,6 +75,14 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
return -ENODEV;
}
 
+   panel_bridge->link = device_link_add(drm_dev->dev, panel->dev,
+DL_FLAG_STATELESS);
+   if (!panel_bridge->link) {
+   DRM_ERROR("Failed to add device link between %s and %s\n",
+ dev_name(drm_dev->dev), dev_name(panel->dev));
+   return -EINVAL;
+   }
+
drm_connector_helper_add(connector,
 _bridge_connector_helper_funcs);
 
@@ -78,6 +91,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 panel_bridge->connector_type);
if (ret) {
DRM_ERROR("Failed to initialize connector\n");
+   device_link_del(panel_bridge->link);
return ret;
}
 
@@ -100,6 +114,8 @@ static void panel_bridge_detach(struct drm_bridge *bridge)
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
struct drm_connector *connector = _bridge->connector;
 
+   device_link_del(panel_bridge->link);
+
/*
 * Cleanup the connector if we know it was initialized.
 *
-- 
2.37.1



[PATCH v3 9/9] drm/bridge: imx: Add i.MX93 MIPI DSI support

2023-08-06 Thread Liu Ying
Freescale i.MX93 SoC embeds a Synopsys Designware MIPI DSI host
controller and a Synopsys Designware MIPI DPHY.  Some configurations
and extensions to them are controlled by i.MX93 media blk-ctrl.

Add a DRM bridge for i.MX93 MIPI DSI by using existing DW MIPI DSI
bridge helpers and implementing i.MX93 MIPI DSI specific extensions.

Signed-off-by: Liu Ying 
---
v2->v3:
* Select GENERIC_PHY to fix Kconfig warning for GENERIC_PHY_MIPI_DPHY
  dependency.

v1->v2:
* Use dev_err_probe() to replace DRM_DEV_ERROR().  (Sam and Alexander)
* Use dev_*() to replace DRM_*().  (Sam)
* Fix build for arm architecture.
  (Reported-by: kernel test robot )
* Improve error messages for imx93_dsi_phy_init().

 drivers/gpu/drm/bridge/imx/Kconfig  |  11 +
 drivers/gpu/drm/bridge/imx/Makefile |   1 +
 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c | 917 
 3 files changed, 929 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c

diff --git a/drivers/gpu/drm/bridge/imx/Kconfig 
b/drivers/gpu/drm/bridge/imx/Kconfig
index 9fae28db6aa7..5a4f3d58501e 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -49,4 +49,15 @@ config DRM_IMX8QXP_PIXEL_LINK_TO_DPI
  Choose this to enable pixel link to display pixel interface(PXL2DPI)
  found in Freescale i.MX8qxp processor.
 
+config DRM_IMX93_MIPI_DSI
+   tristate "Freescale i.MX93 specific extensions for Synopsys DW MIPI DSI"
+   depends on OF
+   depends on COMMON_CLK
+   select DRM_DW_MIPI_DSI
+   select GENERIC_PHY
+   select GENERIC_PHY_MIPI_DPHY
+   help
+ Choose this to enable MIPI DSI controller found in Freescale i.MX93
+ processor.
+
 endif # ARCH_MXC || COMPILE_TEST
diff --git a/drivers/gpu/drm/bridge/imx/Makefile 
b/drivers/gpu/drm/bridge/imx/Makefile
index 8e2ebf3399a1..2b0c2e44aa1b 100644
--- a/drivers/gpu/drm/bridge/imx/Makefile
+++ b/drivers/gpu/drm/bridge/imx/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_DRM_IMX8QXP_LDB) += imx8qxp-ldb.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o
+obj-$(CONFIG_DRM_IMX93_MIPI_DSI) += imx93-mipi-dsi.o
diff --git a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c 
b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
new file mode 100644
index ..3ff30ce80c5b
--- /dev/null
+++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
@@ -0,0 +1,917 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2022,2023 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/* DPHY PLL configuration registers */
+#define DSI_REG0x4c
+#define  CFGCLKFREQRANGE_MASK  GENMASK(5, 0)
+#define  CFGCLKFREQRANGE(x)FIELD_PREP(CFGCLKFREQRANGE_MASK, (x))
+#define  CLKSEL_MASK   GENMASK(7, 6)
+#define  CLKSEL_STOP   FIELD_PREP(CLKSEL_MASK, 0)
+#define  CLKSEL_GENFIELD_PREP(CLKSEL_MASK, 1)
+#define  CLKSEL_EXTFIELD_PREP(CLKSEL_MASK, 2)
+#define  HSFREQRANGE_MASK  GENMASK(14, 8)
+#define  HSFREQRANGE(x)FIELD_PREP(HSFREQRANGE_MASK, 
(x))
+#define  UPDATE_PLLBIT(17)
+#define  SHADOW_CLRBIT(18)
+#define  CLK_EXT   BIT(19)
+
+#define DSI_WRITE_REG0 0x50
+#define  M_MASKGENMASK(9, 0)
+#define  M(x)  FIELD_PREP(M_MASK, ((x) - 2))
+#define  N_MASKGENMASK(13, 10)
+#define  N(x)  FIELD_PREP(N_MASK, ((x) - 1))
+#define  VCO_CTRL_MASK GENMASK(19, 14)
+#define  VCO_CTRL(x)   FIELD_PREP(VCO_CTRL_MASK, (x))
+#define  PROP_CTRL_MASKGENMASK(25, 20)
+#define  PROP_CTRL(x)  FIELD_PREP(PROP_CTRL_MASK, (x))
+#define  INT_CTRL_MASK GENMASK(31, 26)
+#define  INT_CTRL(x)   FIELD_PREP(INT_CTRL_MASK, (x))
+
+#define DSI_WRITE_REG1 0x54
+#define  GMP_CTRL_MASK GENMASK(1, 0)
+#define  GMP_CTRL(x)   FIELD_PREP(GMP_CTRL_MASK, (x))
+#define  CPBIAS_CTRL_MASK  GENMASK(8, 2)
+#define  CPBIAS_CTRL(x)FIELD_PREP(CPBIAS_CTRL_MASK, 
(x))
+#define  PLL_SHADOW_CTRL   BIT(9)
+
+/* display mux control register */
+#define DISPLAY_MUX0x60
+#define  MIPI_DSI_RGB666_MAP_CFG   GENMASK(7, 6)
+#define  RGB666_CONFIG1
FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 0)
+#define  RGB666_CONFIG2
FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 1)
+#define  MIPI_DSI_RGB565_MAP_CFG   

[PATCH v3 8/9] dt-bindings: display: bridge: Document Freescale i.MX93 MIPI DSI

2023-08-06 Thread Liu Ying
Freescale i.MX93 SoC embeds a Synopsys Designware MIPI DSI host
controller and a Synopsys Designware MIPI DPHY.  Some configurations
and extensions to them are controlled by i.MX93 media blk-ctrl.

Signed-off-by: Liu Ying 
Reviewed-by: Rob Herring 
---
v2->v3:
* No change.

v1->v2:
* Add Rob's R-b tag.

 .../display/bridge/fsl,imx93-mipi-dsi.yaml| 115 ++
 1 file changed, 115 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml

diff --git 
a/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml 
b/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
new file mode 100644
index ..d6e51d0cf546
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/fsl,imx93-mipi-dsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX93 specific extensions to Synopsys Designware MIPI DSI
+
+maintainers:
+  - Liu Ying 
+
+description: |
+  There is a Synopsys Designware MIPI DSI Host Controller and a Synopsys
+  Designware MIPI DPHY embedded in Freescale i.MX93 SoC.  Some configurations
+  and extensions to them are controlled by i.MX93 media blk-ctrl.
+
+allOf:
+  - $ref: snps,dw-mipi-dsi.yaml#
+
+properties:
+  compatible:
+const: fsl,imx93-mipi-dsi
+
+  clocks:
+items:
+  - description: apb clock
+  - description: pixel clock
+  - description: PHY configuration clock
+  - description: PHY reference clock
+
+  clock-names:
+items:
+  - const: pclk
+  - const: pix
+  - const: phy_cfg
+  - const: phy_ref
+
+  interrupts:
+maxItems: 1
+
+  fsl,media-blk-ctrl:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  i.MX93 media blk-ctrl, as a syscon, controls pixel component bit map
+  configurations from LCDIF display controller to the MIPI DSI host
+  controller and MIPI DPHY PLL related configurations through PLL SoC
+  interface.
+
+  power-domains:
+maxItems: 1
+
+required:
+  - compatible
+  - interrupts
+  - fsl,media-blk-ctrl
+  - power-domains
+
+unevaluatedProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+#include 
+
+dsi@4ae1 {
+compatible = "fsl,imx93-mipi-dsi";
+reg = <0x4ae1 0x1>;
+interrupts = ;
+clocks = < IMX93_CLK_MIPI_DSI_GATE>,
+ < IMX93_CLK_MEDIA_DISP_PIX>,
+ < IMX93_CLK_MIPI_PHY_CFG>,
+ < IMX93_CLK_24M>;
+clock-names = "pclk", "pix", "phy_cfg", "phy_ref";
+fsl,media-blk-ctrl = <_blk_ctrl>;
+power-domains = <_blk_ctrl IMX93_MEDIABLK_PD_MIPI_DSI>;
+#address-cells = <1>;
+#size-cells = <0>;
+
+panel@0 {
+compatible = "raydium,rm67191";
+reg = <0>;
+reset-gpios = < 6 GPIO_ACTIVE_LOW>;
+dsi-lanes = <4>;
+video-mode = <2>;
+
+port {
+panel_in: endpoint {
+remote-endpoint = <_out>;
+};
+};
+};
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+
+dsi_to_lcdif: endpoint {
+remote-endpoint = <_to_dsi>;
+};
+};
+
+port@1 {
+reg = <1>;
+
+dsi_out: endpoint {
+remote-endpoint = <_in>;
+};
+};
+};
+};
-- 
2.37.1



[PATCH v3 6/9] drm/bridge: synopsys: dw-mipi-dsi: Set minimum lane byte clock cycles for HSA and HBP

2023-08-06 Thread Liu Ying
According to Synopsys support channel, each region of HSA, HBP and HFP must
have minimum number of 10 bytes where constant 4 bytes are for HSS or HSE
and 6 bytes are for blanking packet(header + CRC).  Hence, the below table
comes in.

++--+---+
| data lanes | min lbcc | bytes |
++--+---+
| 1  |10|  1*10 |
++--+---+
| 2  |5 |  2*5  |
++--+---+
| 3  |4 |  3*4  |
++--+---+
| 4  |3 |  4*3  |
++--+---+

Implement the minimum lbcc numbers to make sure that the values programmed
into DSI_VID_HSA_TIME and DSI_VID_HBP_TIME registers meet the minimum
number requirement.  For DSI_VID_HLINE_TIME register, it seems that the
value programmed should be based on mode->htotal as-is, instead of sum up
HSA, HBP, HFP and HDISPLAY.

This helps the case where Raydium RM67191 DSI panel is connected, since
it's video timing for hsync length is only 2 pixels and without this patch
the programmed value for DSI_VID_HSA_TIME is only 2 with 4 data lanes.

Signed-off-by: Liu Ying 
Reviewed-by: Neil Armstrong 
---
v2->v3:
* Add Neil's R-b tag from v1.

v1->v2:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 332388fd86da..536306ccea5a 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -757,12 +757,19 @@ static void dw_mipi_dsi_command_mode_config(struct 
dw_mipi_dsi *dsi)
dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
 }
 
+static const u32 minimum_lbccs[] = {10, 5, 4, 3};
+
+static inline u32 dw_mipi_dsi_get_minimum_lbcc(struct dw_mipi_dsi *dsi)
+{
+   return minimum_lbccs[dsi->lanes - 1];
+}
+
 /* Get lane byte clock cycles. */
 static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi,
   const struct drm_display_mode *mode,
   u32 hcomponent)
 {
-   u32 frac, lbcc;
+   u32 frac, lbcc, minimum_lbcc;
int bpp;
 
bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
@@ -778,6 +785,11 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct 
dw_mipi_dsi *dsi,
if (frac)
lbcc++;
 
+   minimum_lbcc = dw_mipi_dsi_get_minimum_lbcc(dsi);
+
+   if (lbcc < minimum_lbcc)
+   lbcc = minimum_lbcc;
+
return lbcc;
 }
 
-- 
2.37.1



[PATCH v3 7/9] drm/bridge: synopsys: dw-mipi-dsi: Disable HSTX and LPRX timeout check

2023-08-06 Thread Liu Ying
According to Synopsys DW MIPI DSI host databook, HSTX and LPRX timeout
contention detections are measured in TO_CLK_DIVISION cycles.  However,
the current driver programs magic values to TO_CLK_DIVISION, HSTX_TO_CNT
and LPRX_TO_CNT register fields, which makes timeout error event wrongly
happen for some video modes, at least for the typical 1920x1080p@60 video
mode read from a HDMI monitor driven by ADV7535 DSI to HDMI bridge.
While at it, the current driver doesn't enable interrupt to handle or
complain about the error status, so true error just happens silently
except for display distortions by visual check.

Disable the timeout check by setting those timeout register fields to
zero for now until someone comes along with better computations for the
timeout values.  Although the databook doesn't mention what happens when
they are set to zero, it turns out the false error doesn't happen for
the 1920x1080p@60 video mode at least.

Signed-off-by: Liu Ying 
Reviewed-by: Neil Armstrong 
---
v2->v3:
* Add Neil's R-b tag from v1.

v1->v2:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 536306ccea5a..0fcadf99e783 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -684,7 +684,7 @@ static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi)
 * timeout clock division should be computed with the
 * high speed transmission counter timeout and byte lane...
 */
-   dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVISION(10) |
+   dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVISION(0) |
  TX_ESC_CLK_DIVISION(esc_clk_division));
 }
 
@@ -747,7 +747,7 @@ static void dw_mipi_dsi_command_mode_config(struct 
dw_mipi_dsi *dsi)
 * compute high speed transmission counter timeout according
 * to the timeout clock division (TO_CLK_DIVISION) and byte lane...
 */
-   dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(1000) | LPRX_TO_CNT(1000));
+   dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(0) | LPRX_TO_CNT(0));
/*
 * TODO dw drv improvements
 * the Bus-Turn-Around Timeout Counter should be computed
-- 
2.37.1



[PATCH v3 4/9] drm/bridge: synopsys: dw-mipi-dsi: Add mode fixup support

2023-08-06 Thread Liu Ying
Vendor drivers may need to fixup mode due to pixel clock tree limitation,
so introduce the ->mode_fixup() callcack to struct dw_mipi_dsi_plat_data
and call it at atomic check stage if available.

Signed-off-by: Liu Ying 
---
v1->v3:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 14 ++
 include/drm/bridge/dw_mipi_dsi.h  |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 8cd89a63b5f2..c754d55f71d1 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -571,9 +571,23 @@ static int dw_mipi_dsi_bridge_atomic_check(struct 
drm_bridge *bridge,
   struct drm_crtc_state *crtc_state,
   struct drm_connector_state 
*conn_state)
 {
+   struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
+   const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
+   bool ret;
+
bridge_state->input_bus_cfg.flags =
DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
 
+   if (pdata->mode_fixup) {
+   ret = pdata->mode_fixup(pdata->priv_data, _state->mode,
+   _state->adjusted_mode);
+   if (!ret) {
+   DRM_DEBUG_DRIVER("failed to fixup mode " DRM_MODE_FMT 
"\n",
+DRM_MODE_ARG(_state->mode));
+   return -EINVAL;
+   }
+   }
+
return 0;
 }
 
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index 246650f2814f..65d5e68065e3 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -59,6 +59,9 @@ struct dw_mipi_dsi_plat_data {
   unsigned long mode_flags,
   u32 lanes, u32 format);
 
+   bool (*mode_fixup)(void *priv_data, const struct drm_display_mode *mode,
+  struct drm_display_mode *adjusted_mode);
+
u32 *(*get_input_bus_fmts)(void *priv_data,
   struct drm_bridge *bridge,
   struct drm_bridge_state *bridge_state,
-- 
2.37.1



[PATCH v3 5/9] drm/bridge: synopsys: dw-mipi-dsi: Use pixel clock rate to calculate lbcc

2023-08-06 Thread Liu Ying
To get better accuration, use pixel clock rate to calculate lbcc instead of
lane_mbps since the pixel clock rate is in KHz while lane_mbps is in MHz.
Without this, distorted image can be seen on a HDMI monitor connected with
i.MX93 11x11 EVK through ADV7535 DSI to HDMI bridge in 1920x1080p@60 video
mode.

Signed-off-by: Liu Ying 
Reviewed-by: Neil Armstrong 
---
v2->v3:
* Add Neil's R-b tag from v1.

v1->v2:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index c754d55f71d1..332388fd86da 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -762,8 +763,15 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct 
dw_mipi_dsi *dsi,
   u32 hcomponent)
 {
u32 frac, lbcc;
+   int bpp;
 
-   lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8;
+   bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+   if (bpp < 0) {
+   dev_err(dsi->dev, "failed to get bpp\n");
+   return 0;
+   }
+
+   lbcc = div_u64((u64)hcomponent * mode->clock * bpp, dsi->lanes * 8);
 
frac = lbcc % mode->clock;
lbcc = lbcc / mode->clock;
-- 
2.37.1



[PATCH v3 3/9] drm/bridge: synopsys: dw-mipi-dsi: Force input bus flags

2023-08-06 Thread Liu Ying
The DATAEN_ACTIVE_LOW bit in DSI_DPI_CFG_POL register is set to zero,
so set the DRM_BUS_FLAG_DE_HIGH flag in input_bus_cfg.flags.  It appears
that the DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE flag also makes sense, so
set it in input_bus_cfg.flags too.  With this patch, the flags set by
drm_atomic_bridge_propagate_bus_flags() are overridden (see comment in
that function) in case any downstream bridges propagates invalid flags
to this bridge.  A real problematic case is to connect a RM67191 MIPI
DSI panel whose driver sets DRM_BUS_FLAG_DE_LOW and
DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE bus flags.

Signed-off-by: Liu Ying 
---
v1->v3:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 8580b8a97fb1..8cd89a63b5f2 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -565,6 +566,17 @@ dw_mipi_dsi_bridge_atomic_get_input_bus_fmts(struct 
drm_bridge *bridge,
return input_fmts;
 }
 
+static int dw_mipi_dsi_bridge_atomic_check(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*bridge_state,
+  struct drm_crtc_state *crtc_state,
+  struct drm_connector_state 
*conn_state)
+{
+   bridge_state->input_bus_cfg.flags =
+   DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
+
+   return 0;
+}
+
 static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
 {
u32 val;
@@ -1033,6 +1045,7 @@ static const struct drm_bridge_funcs 
dw_mipi_dsi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_bridge_destroy_state,
.atomic_get_input_bus_fmts = 
dw_mipi_dsi_bridge_atomic_get_input_bus_fmts,
+   .atomic_check   = dw_mipi_dsi_bridge_atomic_check,
.atomic_reset   = drm_atomic_helper_bridge_reset,
.atomic_enable  = dw_mipi_dsi_bridge_atomic_enable,
.atomic_post_disable= dw_mipi_dsi_bridge_post_atomic_disable,
-- 
2.37.1



[PATCH v3 2/9] drm/bridge: synopsys: dw-mipi-dsi: Add input bus format negotiation support

2023-08-06 Thread Liu Ying
Introduce ->get_input_bus_fmts() callback to struct dw_mipi_dsi_plat_data
so that vendor drivers can implement specific methods to get input bus
formats for Synopsys DW MIPI DSI.

While at it, implement a generic callback for ->atomic_get_input_bus_fmts(),
where we try to get the input bus formats through pdata->get_input_bus_fmts()
first.  If it's unavailable, fall back to the only format - MEDIA_BUS_FMT_FIXED,
which matches the default behavior if ->atomic_get_input_bus_fmts() is not
implemented as ->atomic_get_input_bus_fmts()'s kerneldoc indicates.

Signed-off-by: Liu Ying 
---
v1->v3:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 30 +++
 include/drm/bridge/dw_mipi_dsi.h  | 11 +++
 2 files changed, 41 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 57eae0fdd970..8580b8a97fb1 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -536,6 +537,34 @@ static const struct mipi_dsi_host_ops dw_mipi_dsi_host_ops 
= {
.transfer = dw_mipi_dsi_host_transfer,
 };
 
+static u32 *
+dw_mipi_dsi_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+struct drm_bridge_state 
*bridge_state,
+struct drm_crtc_state *crtc_state,
+struct drm_connector_state 
*conn_state,
+u32 output_fmt,
+unsigned int *num_input_fmts)
+{
+   struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
+   const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
+   u32 *input_fmts;
+
+   if (pdata->get_input_bus_fmts)
+   return pdata->get_input_bus_fmts(pdata->priv_data,
+bridge, bridge_state,
+crtc_state, conn_state,
+output_fmt, num_input_fmts);
+
+   /* Fall back to MEDIA_BUS_FMT_FIXED as the only input format. */
+   input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+   input_fmts[0] = MEDIA_BUS_FMT_FIXED;
+   *num_input_fmts = 1;
+
+   return input_fmts;
+}
+
 static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
 {
u32 val;
@@ -1003,6 +1032,7 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge 
*bridge,
 static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_bridge_destroy_state,
+   .atomic_get_input_bus_fmts = 
dw_mipi_dsi_bridge_atomic_get_input_bus_fmts,
.atomic_reset   = drm_atomic_helper_bridge_reset,
.atomic_enable  = dw_mipi_dsi_bridge_atomic_enable,
.atomic_post_disable= dw_mipi_dsi_bridge_post_atomic_disable,
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index f54621b17a69..246650f2814f 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -11,7 +11,10 @@
 
 #include 
 
+#include 
 #include 
+#include 
+#include 
 #include 
 
 struct drm_display_mode;
@@ -56,6 +59,14 @@ struct dw_mipi_dsi_plat_data {
   unsigned long mode_flags,
   u32 lanes, u32 format);
 
+   u32 *(*get_input_bus_fmts)(void *priv_data,
+  struct drm_bridge *bridge,
+  struct drm_bridge_state *bridge_state,
+  struct drm_crtc_state *crtc_state,
+  struct drm_connector_state *conn_state,
+  u32 output_fmt,
+  unsigned int *num_input_fmts);
+
const struct dw_mipi_dsi_phy_ops *phy_ops;
const struct dw_mipi_dsi_host_ops *host_ops;
 
-- 
2.37.1



[PATCH v3 1/9] drm/bridge: synopsys: dw-mipi-dsi: Add dw_mipi_dsi_get_bridge() helper

2023-08-06 Thread Liu Ying
Add dw_mipi_dsi_get_bridge() helper so that it can be used by vendor
drivers which implement vendor specific extensions to Synopsys DW MIPI DSI.

Signed-off-by: Liu Ying 
---
v1->v3:
* No change.

 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 6 ++
 include/drm/bridge/dw_mipi_dsi.h  | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index b2efecf7d160..57eae0fdd970 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -1207,6 +1207,12 @@ void dw_mipi_dsi_set_slave(struct dw_mipi_dsi *dsi, 
struct dw_mipi_dsi *slave)
 }
 EXPORT_SYMBOL_GPL(dw_mipi_dsi_set_slave);
 
+struct drm_bridge *dw_mipi_dsi_get_bridge(struct dw_mipi_dsi *dsi)
+{
+   return >bridge;
+}
+EXPORT_SYMBOL_GPL(dw_mipi_dsi_get_bridge);
+
 /*
  * Probe/remove API, used from platforms based on the DRM bridge API.
  */
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index 5286a53a1875..f54621b17a69 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -11,6 +11,7 @@
 
 #include 
 
+#include 
 #include 
 
 struct drm_display_mode;
@@ -68,5 +69,6 @@ void dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi);
 int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder);
 void dw_mipi_dsi_unbind(struct dw_mipi_dsi *dsi);
 void dw_mipi_dsi_set_slave(struct dw_mipi_dsi *dsi, struct dw_mipi_dsi *slave);
+struct drm_bridge *dw_mipi_dsi_get_bridge(struct dw_mipi_dsi *dsi);
 
 #endif /* __DW_MIPI_DSI__ */
-- 
2.37.1



[PATCH v3 0/9] drm/bridge: imx: Add i.MX93 MIPI DSI support

2023-08-06 Thread Liu Ying
Hi,

This series aims to add MIPI DSI support for Freescale i.MX93 SoC.

There is a Synopsys DesignWare MIPI DSI host controller and a Synopsys
Designware MIPI DPHY embedded in i.MX93.  Some configurations and
extensions to them are controlled by i.MX93 media blk-ctrl.

Add a DRM bridge for i.MX93 MIPI DSI by using existing DW MIPI DSI
bridge helpers and implementing i.MX93 MIPI DSI specific extensions.

Note that since this series touches the dw-mipi-dsi driver, tests are
needed to be done for meson, rockchip and stm.

Patch 1 ~ 7 do preparation work for adding i.MX93 MIPI DSI DRM bridge driver.

Patch 8 adds DT-binding documentation for i.MX93 MIPI DSI.

Patch 9 adds i.MX93 MIPI DSI DRM bridge.

v2->v3:
* Add Neil's R-b tags from v1 on patch 5/6/7.
* Select GENERIC_PHY to fix Kconfig warning for GENERIC_PHY_MIPI_DPHY
  dependency in patch 9.
* Cc stm and rockchip folks.

v1->v2:
* Add Rob's R-b tag on patch 8.
* Use dev_err_probe() to replace DRM_DEV_ERROR() in patch 9.  (Sam and 
Alexander)
* Use dev_*() to replace DRM_*() in patch 9.  (Sam)
* Fix build for arm architecture in patch 9.
  (Reported-by: kernel test robot )
* Improve error messages for imx93_dsi_phy_init() in patch 9.

Liu Ying (9):
  drm/bridge: synopsys: dw-mipi-dsi: Add dw_mipi_dsi_get_bridge() helper
  drm/bridge: synopsys: dw-mipi-dsi: Add input bus format negotiation
support
  drm/bridge: synopsys: dw-mipi-dsi: Force input bus flags
  drm/bridge: synopsys: dw-mipi-dsi: Add mode fixup support
  drm/bridge: synopsys: dw-mipi-dsi: Use pixel clock rate to calculate
lbcc
  drm/bridge: synopsys: dw-mipi-dsi: Set minimum lane byte clock cycles
for HSA and HBP
  drm/bridge: synopsys: dw-mipi-dsi: Disable HSTX and LPRX timeout check
  dt-bindings: display: bridge: Document Freescale i.MX93 MIPI DSI
  drm/bridge: imx: Add i.MX93 MIPI DSI support

 .../display/bridge/fsl,imx93-mipi-dsi.yaml| 115 +++
 drivers/gpu/drm/bridge/imx/Kconfig|  11 +
 drivers/gpu/drm/bridge/imx/Makefile   |   1 +
 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c   | 917 ++
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c |  91 +-
 include/drm/bridge/dw_mipi_dsi.h  |  16 +
 6 files changed, 1147 insertions(+), 4 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c

-- 
2.37.1



[PATCH v2] drm/bridge: panel: Add a device link between drm device and panel device

2023-07-17 Thread Liu Ying
Add the device link when panel bridge is attached and delete the link
when panel bridge is detached.  The drm device is the consumer while
the panel device is the supplier.  This makes sure that the drm device
suspends eariler and resumes later than the panel device, hence resolves
problems where the order is swapped, like the problematic case mentioned
in the below link.

Link: 
https://lore.kernel.org/lkml/capdykfr0xjru_udkoukq_q8rwaukyql+8fv-7s1ctmqi7u3...@mail.gmail.com/T/
Suggested-by: Ulf Hansson 
Signed-off-by: Liu Ying 
---
v1->v2:
* Fix bailout for panel_bridge_attach() in case device_link_add() fails.

 drivers/gpu/drm/bridge/panel.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 9316384b4474..a6587d233505 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -4,6 +4,8 @@
  * Copyright (C) 2017 Broadcom
  */
 
+#include 
+
 #include 
 #include 
 #include 
@@ -19,6 +21,7 @@ struct panel_bridge {
struct drm_bridge bridge;
struct drm_connector connector;
struct drm_panel *panel;
+   struct device_link *link;
u32 connector_type;
 };
 
@@ -60,6 +63,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
struct drm_connector *connector = _bridge->connector;
+   struct drm_panel *panel = panel_bridge->panel;
+   struct drm_device *drm_dev = bridge->dev;
int ret;
 
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
@@ -70,6 +75,14 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
return -ENODEV;
}
 
+   panel_bridge->link = device_link_add(drm_dev->dev, panel->dev,
+DL_FLAG_STATELESS);
+   if (!panel_bridge->link) {
+   DRM_ERROR("Failed to add device link between %s and %s\n",
+ dev_name(drm_dev->dev), dev_name(panel->dev));
+   return -EINVAL;
+   }
+
drm_connector_helper_add(connector,
 _bridge_connector_helper_funcs);
 
@@ -78,6 +91,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 panel_bridge->connector_type);
if (ret) {
DRM_ERROR("Failed to initialize connector\n");
+   device_link_del(panel_bridge->link);
return ret;
}
 
@@ -100,6 +114,8 @@ static void panel_bridge_detach(struct drm_bridge *bridge)
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
struct drm_connector *connector = _bridge->connector;
 
+   device_link_del(panel_bridge->link);
+
/*
 * Cleanup the connector if we know it was initialized.
 *
-- 
2.37.1



[PATCH] drm/bridge: panel: Add a device link between drm device and panel device

2023-07-17 Thread Liu Ying
Add the device link when panel bridge is attached and delete the link
when panel bridge is detached.  The drm device is the consumer while
the panel device is the supplier.  This makes sure that the drm device
suspends eariler and resumes later than the panel device, hence resolves
problems where the order is swapped, like the problematic case mentioned
in the below link.

Link: 
https://lore.kernel.org/lkml/capdykfr0xjru_udkoukq_q8rwaukyql+8fv-7s1ctmqi7u3...@mail.gmail.com/T/
Suggested-by: Ulf Hansson 
Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/panel.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 9316384b4474..85fc6e6dba58 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -4,6 +4,8 @@
  * Copyright (C) 2017 Broadcom
  */
 
+#include 
+
 #include 
 #include 
 #include 
@@ -19,6 +21,7 @@ struct panel_bridge {
struct drm_bridge bridge;
struct drm_connector connector;
struct drm_panel *panel;
+   struct device_link *link;
u32 connector_type;
 };
 
@@ -60,6 +63,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
struct drm_connector *connector = _bridge->connector;
+   struct drm_panel *panel = panel_bridge->panel;
+   struct drm_device *drm_dev = bridge->dev;
int ret;
 
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
@@ -92,6 +97,14 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
drm_connector_register(connector);
}
 
+   panel_bridge->link = device_link_add(drm_dev->dev, panel->dev,
+DL_FLAG_STATELESS);
+   if (!panel_bridge->link) {
+   DRM_ERROR("Failed to add device link between %s and %s\n",
+ dev_name(drm_dev->dev), dev_name(panel->dev));
+   return -EINVAL;
+   }
+
return 0;
 }
 
@@ -100,6 +113,8 @@ static void panel_bridge_detach(struct drm_bridge *bridge)
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
struct drm_connector *connector = _bridge->connector;
 
+   device_link_del(panel_bridge->link);
+
/*
 * Cleanup the connector if we know it was initialized.
 *
-- 
2.37.1



[PATCH 9/9] drm/bridge: imx: Add i.MX93 MIPI DSI support

2023-07-17 Thread Liu Ying
Freescale i.MX93 SoC embeds a Synopsys Designware MIPI DSI host
controller and a Synopsys Designware MIPI DPHY.  Some configurations
and extensions to them are controlled by i.MX93 media blk-ctrl.

Add a DRM bridge for i.MX93 MIPI DSI by using existing DW MIPI DSI
bridge helpers and implementing i.MX93 MIPI DSI specific extensions.

Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/imx/Kconfig  |  10 +
 drivers/gpu/drm/bridge/imx/Makefile |   1 +
 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c | 934 
 3 files changed, 945 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c

diff --git a/drivers/gpu/drm/bridge/imx/Kconfig 
b/drivers/gpu/drm/bridge/imx/Kconfig
index 9fae28db6aa7..5182298c7182 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -49,4 +49,14 @@ config DRM_IMX8QXP_PIXEL_LINK_TO_DPI
  Choose this to enable pixel link to display pixel interface(PXL2DPI)
  found in Freescale i.MX8qxp processor.
 
+config DRM_IMX93_MIPI_DSI
+   tristate "Freescale i.MX93 specific extensions for Synopsys DW MIPI DSI"
+   depends on OF
+   depends on COMMON_CLK
+   select DRM_DW_MIPI_DSI
+   select GENERIC_PHY_MIPI_DPHY
+   help
+ Choose this to enable MIPI DSI controller found in Freescale i.MX93
+ processor.
+
 endif # ARCH_MXC || COMPILE_TEST
diff --git a/drivers/gpu/drm/bridge/imx/Makefile 
b/drivers/gpu/drm/bridge/imx/Makefile
index 8e2ebf3399a1..2b0c2e44aa1b 100644
--- a/drivers/gpu/drm/bridge/imx/Makefile
+++ b/drivers/gpu/drm/bridge/imx/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_DRM_IMX8QXP_LDB) += imx8qxp-ldb.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o
+obj-$(CONFIG_DRM_IMX93_MIPI_DSI) += imx93-mipi-dsi.o
diff --git a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c 
b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
new file mode 100644
index ..77f59e3407a0
--- /dev/null
+++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
@@ -0,0 +1,934 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2022,2023 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* DPHY PLL configuration registers */
+#define DSI_REG0x4c
+#define  CFGCLKFREQRANGE_MASK  GENMASK(5, 0)
+#define  CFGCLKFREQRANGE(x)FIELD_PREP(CFGCLKFREQRANGE_MASK, (x))
+#define  CLKSEL_MASK   GENMASK(7, 6)
+#define  CLKSEL_STOP   FIELD_PREP(CLKSEL_MASK, 0)
+#define  CLKSEL_GENFIELD_PREP(CLKSEL_MASK, 1)
+#define  CLKSEL_EXTFIELD_PREP(CLKSEL_MASK, 2)
+#define  HSFREQRANGE_MASK  GENMASK(14, 8)
+#define  HSFREQRANGE(x)FIELD_PREP(HSFREQRANGE_MASK, 
(x))
+#define  UPDATE_PLLBIT(17)
+#define  SHADOW_CLRBIT(18)
+#define  CLK_EXT   BIT(19)
+
+#define DSI_WRITE_REG0 0x50
+#define  M_MASKGENMASK(9, 0)
+#define  M(x)  FIELD_PREP(M_MASK, ((x) - 2))
+#define  N_MASKGENMASK(13, 10)
+#define  N(x)  FIELD_PREP(N_MASK, ((x) - 1))
+#define  VCO_CTRL_MASK GENMASK(19, 14)
+#define  VCO_CTRL(x)   FIELD_PREP(VCO_CTRL_MASK, (x))
+#define  PROP_CTRL_MASKGENMASK(25, 20)
+#define  PROP_CTRL(x)  FIELD_PREP(PROP_CTRL_MASK, (x))
+#define  INT_CTRL_MASK GENMASK(31, 26)
+#define  INT_CTRL(x)   FIELD_PREP(INT_CTRL_MASK, (x))
+
+#define DSI_WRITE_REG1 0x54
+#define  GMP_CTRL_MASK GENMASK(1, 0)
+#define  GMP_CTRL(x)   FIELD_PREP(GMP_CTRL_MASK, (x))
+#define  CPBIAS_CTRL_MASK  GENMASK(8, 2)
+#define  CPBIAS_CTRL(x)FIELD_PREP(CPBIAS_CTRL_MASK, 
(x))
+#define  PLL_SHADOW_CTRL   BIT(9)
+
+/* display mux control register */
+#define DISPLAY_MUX0x60
+#define  MIPI_DSI_RGB666_MAP_CFG   GENMASK(7, 6)
+#define  RGB666_CONFIG1
FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 0)
+#define  RGB666_CONFIG2
FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 1)
+#define  MIPI_DSI_RGB565_MAP_CFG   GENMASK(5, 4)
+#define  RGB565_CONFIG1
FIELD_PREP(MIPI_DSI_RGB565_MAP_CFG, 0)
+#define  RGB565_CONFIG2
FIELD_PREP(MIPI_DSI_RGB565_MAP_CFG, 1)
+#define  RGB565_CONFIG3
FIELD_PREP(MIPI_DSI_RGB565_MAP_CFG, 2)
+#define  LCDIF_CROSS_LINE_PATTERN  GENMASK(3, 0)
+#define  RGB888

[PATCH 8/9] dt-bindings: display: bridge: Document Freescale i.MX93 MIPI DSI

2023-07-17 Thread Liu Ying
Freescale i.MX93 SoC embeds a Synopsys Designware MIPI DSI host
controller and a Synopsys Designware MIPI DPHY.  Some configurations
and extensions to them are controlled by i.MX93 media blk-ctrl.

Signed-off-by: Liu Ying 
---
 .../display/bridge/fsl,imx93-mipi-dsi.yaml| 115 ++
 1 file changed, 115 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml

diff --git 
a/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml 
b/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
new file mode 100644
index ..d6e51d0cf546
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/fsl,imx93-mipi-dsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX93 specific extensions to Synopsys Designware MIPI DSI
+
+maintainers:
+  - Liu Ying 
+
+description: |
+  There is a Synopsys Designware MIPI DSI Host Controller and a Synopsys
+  Designware MIPI DPHY embedded in Freescale i.MX93 SoC.  Some configurations
+  and extensions to them are controlled by i.MX93 media blk-ctrl.
+
+allOf:
+  - $ref: snps,dw-mipi-dsi.yaml#
+
+properties:
+  compatible:
+const: fsl,imx93-mipi-dsi
+
+  clocks:
+items:
+  - description: apb clock
+  - description: pixel clock
+  - description: PHY configuration clock
+  - description: PHY reference clock
+
+  clock-names:
+items:
+  - const: pclk
+  - const: pix
+  - const: phy_cfg
+  - const: phy_ref
+
+  interrupts:
+maxItems: 1
+
+  fsl,media-blk-ctrl:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  i.MX93 media blk-ctrl, as a syscon, controls pixel component bit map
+  configurations from LCDIF display controller to the MIPI DSI host
+  controller and MIPI DPHY PLL related configurations through PLL SoC
+  interface.
+
+  power-domains:
+maxItems: 1
+
+required:
+  - compatible
+  - interrupts
+  - fsl,media-blk-ctrl
+  - power-domains
+
+unevaluatedProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+#include 
+
+dsi@4ae1 {
+compatible = "fsl,imx93-mipi-dsi";
+reg = <0x4ae1 0x1>;
+interrupts = ;
+clocks = < IMX93_CLK_MIPI_DSI_GATE>,
+ < IMX93_CLK_MEDIA_DISP_PIX>,
+ < IMX93_CLK_MIPI_PHY_CFG>,
+ < IMX93_CLK_24M>;
+clock-names = "pclk", "pix", "phy_cfg", "phy_ref";
+fsl,media-blk-ctrl = <_blk_ctrl>;
+power-domains = <_blk_ctrl IMX93_MEDIABLK_PD_MIPI_DSI>;
+#address-cells = <1>;
+#size-cells = <0>;
+
+panel@0 {
+compatible = "raydium,rm67191";
+reg = <0>;
+reset-gpios = < 6 GPIO_ACTIVE_LOW>;
+dsi-lanes = <4>;
+video-mode = <2>;
+
+port {
+panel_in: endpoint {
+remote-endpoint = <_out>;
+};
+};
+};
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+
+dsi_to_lcdif: endpoint {
+remote-endpoint = <_to_dsi>;
+};
+};
+
+port@1 {
+reg = <1>;
+
+dsi_out: endpoint {
+remote-endpoint = <_in>;
+};
+};
+};
+};
-- 
2.37.1



[PATCH 7/9] drm/bridge: synopsys: dw-mipi-dsi: Disable HSTX and LPRX timeout check

2023-07-17 Thread Liu Ying
According to Synopsys DW MIPI DSI host databook, HSTX and LPRX timeout
contention detections are measured in TO_CLK_DIVISION cycles.  However,
the current driver programs magic values to TO_CLK_DIVISION, HSTX_TO_CNT
and LPRX_TO_CNT register fields, which makes timeout error event wrongly
happen for some video modes, at least for the typical 1920x1080p@60 video
mode read from a HDMI monitor driven by ADV7535 DSI to HDMI bridge.
While at it, the current driver doesn't enable interrupt to handle or
complain about the error status, so true error just happens silently
except for display distortions by visual check.

Disable the timeout check by setting those timeout register fields to
zero for now until someone comes along with better computations for the
timeout values.  Although the databook doesn't mention what happens when
they are set to zero, it turns out the false error doesn't happen for
the 1920x1080p@60 video mode at least.

Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 536306ccea5a..0fcadf99e783 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -684,7 +684,7 @@ static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi)
 * timeout clock division should be computed with the
 * high speed transmission counter timeout and byte lane...
 */
-   dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVISION(10) |
+   dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVISION(0) |
  TX_ESC_CLK_DIVISION(esc_clk_division));
 }
 
@@ -747,7 +747,7 @@ static void dw_mipi_dsi_command_mode_config(struct 
dw_mipi_dsi *dsi)
 * compute high speed transmission counter timeout according
 * to the timeout clock division (TO_CLK_DIVISION) and byte lane...
 */
-   dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(1000) | LPRX_TO_CNT(1000));
+   dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(0) | LPRX_TO_CNT(0));
/*
 * TODO dw drv improvements
 * the Bus-Turn-Around Timeout Counter should be computed
-- 
2.37.1



[PATCH 6/9] drm/bridge: synopsys: dw-mipi-dsi: Set minimum lane byte clock cycles for HSA and HBP

2023-07-17 Thread Liu Ying
According to Synopsys support channel, each region of HSA, HBP and HFP must
have minimum number of 10 bytes where constant 4 bytes are for HSS or HSE
and 6 bytes are for blanking packet(header + CRC).  Hence, the below table
comes in.

++--+---+
| data lanes | min lbcc | bytes |
++--+---+
| 1  |10|  1*10 |
++--+---+
| 2  |5 |  2*5  |
++--+---+
| 3  |4 |  3*4  |
++--+---+
| 4  |3 |  4*3  |
++--+---+

Implement the minimum lbcc numbers to make sure that the values programmed
into DSI_VID_HSA_TIME and DSI_VID_HBP_TIME registers meet the minimum
number requirement.  For DSI_VID_HLINE_TIME register, it seems that the
value programmed should be based on mode->htotal as-is, instead of sum up
HSA, HBP, HFP and HDISPLAY.

This helps the case where Raydium RM67191 DSI panel is connected, since
it's video timing for hsync length is only 2 pixels and without this patch
the programmed value for DSI_VID_HSA_TIME is only 2 with 4 data lanes.

Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 332388fd86da..536306ccea5a 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -757,12 +757,19 @@ static void dw_mipi_dsi_command_mode_config(struct 
dw_mipi_dsi *dsi)
dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
 }
 
+static const u32 minimum_lbccs[] = {10, 5, 4, 3};
+
+static inline u32 dw_mipi_dsi_get_minimum_lbcc(struct dw_mipi_dsi *dsi)
+{
+   return minimum_lbccs[dsi->lanes - 1];
+}
+
 /* Get lane byte clock cycles. */
 static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi,
   const struct drm_display_mode *mode,
   u32 hcomponent)
 {
-   u32 frac, lbcc;
+   u32 frac, lbcc, minimum_lbcc;
int bpp;
 
bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
@@ -778,6 +785,11 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct 
dw_mipi_dsi *dsi,
if (frac)
lbcc++;
 
+   minimum_lbcc = dw_mipi_dsi_get_minimum_lbcc(dsi);
+
+   if (lbcc < minimum_lbcc)
+   lbcc = minimum_lbcc;
+
return lbcc;
 }
 
-- 
2.37.1



[PATCH 5/9] drm/bridge: synopsys: dw-mipi-dsi: Use pixel clock rate to calculate lbcc

2023-07-17 Thread Liu Ying
To get better accuration, use pixel clock rate to calculate lbcc instead of
lane_mbps since the pixel clock rate is in KHz while lane_mbps is in MHz.
Without this, distorted image can be seen on a HDMI monitor connected with
i.MX93 11x11 EVK through ADV7535 DSI to HDMI bridge in 1920x1080p@60 video
mode.

Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index c754d55f71d1..332388fd86da 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -762,8 +763,15 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct 
dw_mipi_dsi *dsi,
   u32 hcomponent)
 {
u32 frac, lbcc;
+   int bpp;
 
-   lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8;
+   bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+   if (bpp < 0) {
+   dev_err(dsi->dev, "failed to get bpp\n");
+   return 0;
+   }
+
+   lbcc = div_u64((u64)hcomponent * mode->clock * bpp, dsi->lanes * 8);
 
frac = lbcc % mode->clock;
lbcc = lbcc / mode->clock;
-- 
2.37.1



[PATCH 3/9] drm/bridge: synopsys: dw-mipi-dsi: Force input bus flags

2023-07-17 Thread Liu Ying
The DATAEN_ACTIVE_LOW bit in DSI_DPI_CFG_POL register is set to zero,
so set the DRM_BUS_FLAG_DE_HIGH flag in input_bus_cfg.flags.  It appears
that the DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE flag also makes sense, so
set it in input_bus_cfg.flags too.  With this patch, the flags set by
drm_atomic_bridge_propagate_bus_flags() are overridden (see comment in
that function) in case any downstream bridges propagates invalid flags
to this bridge.  A real problematic case is to connect a RM67191 MIPI
DSI panel whose driver sets DRM_BUS_FLAG_DE_LOW and
DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE bus flags.

Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 8580b8a97fb1..8cd89a63b5f2 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -565,6 +566,17 @@ dw_mipi_dsi_bridge_atomic_get_input_bus_fmts(struct 
drm_bridge *bridge,
return input_fmts;
 }
 
+static int dw_mipi_dsi_bridge_atomic_check(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*bridge_state,
+  struct drm_crtc_state *crtc_state,
+  struct drm_connector_state 
*conn_state)
+{
+   bridge_state->input_bus_cfg.flags =
+   DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
+
+   return 0;
+}
+
 static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
 {
u32 val;
@@ -1033,6 +1045,7 @@ static const struct drm_bridge_funcs 
dw_mipi_dsi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_bridge_destroy_state,
.atomic_get_input_bus_fmts = 
dw_mipi_dsi_bridge_atomic_get_input_bus_fmts,
+   .atomic_check   = dw_mipi_dsi_bridge_atomic_check,
.atomic_reset   = drm_atomic_helper_bridge_reset,
.atomic_enable  = dw_mipi_dsi_bridge_atomic_enable,
.atomic_post_disable= dw_mipi_dsi_bridge_post_atomic_disable,
-- 
2.37.1



[PATCH 4/9] drm/bridge: synopsys: dw-mipi-dsi: Add mode fixup support

2023-07-17 Thread Liu Ying
Vendor drivers may need to fixup mode due to pixel clock tree limitation,
so introduce the ->mode_fixup() callcack to struct dw_mipi_dsi_plat_data
and call it at atomic check stage if available.

Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 14 ++
 include/drm/bridge/dw_mipi_dsi.h  |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 8cd89a63b5f2..c754d55f71d1 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -571,9 +571,23 @@ static int dw_mipi_dsi_bridge_atomic_check(struct 
drm_bridge *bridge,
   struct drm_crtc_state *crtc_state,
   struct drm_connector_state 
*conn_state)
 {
+   struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
+   const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
+   bool ret;
+
bridge_state->input_bus_cfg.flags =
DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
 
+   if (pdata->mode_fixup) {
+   ret = pdata->mode_fixup(pdata->priv_data, _state->mode,
+   _state->adjusted_mode);
+   if (!ret) {
+   DRM_DEBUG_DRIVER("failed to fixup mode " DRM_MODE_FMT 
"\n",
+DRM_MODE_ARG(_state->mode));
+   return -EINVAL;
+   }
+   }
+
return 0;
 }
 
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index 246650f2814f..65d5e68065e3 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -59,6 +59,9 @@ struct dw_mipi_dsi_plat_data {
   unsigned long mode_flags,
   u32 lanes, u32 format);
 
+   bool (*mode_fixup)(void *priv_data, const struct drm_display_mode *mode,
+  struct drm_display_mode *adjusted_mode);
+
u32 *(*get_input_bus_fmts)(void *priv_data,
   struct drm_bridge *bridge,
   struct drm_bridge_state *bridge_state,
-- 
2.37.1



[PATCH 2/9] drm/bridge: synopsys: dw-mipi-dsi: Add input bus format negotiation support

2023-07-17 Thread Liu Ying
Introduce ->get_input_bus_fmts() callback to struct dw_mipi_dsi_plat_data
so that vendor drivers can implement specific methods to get input bus
formats for Synopsys DW MIPI DSI.

While at it, implement a generic callback for ->atomic_get_input_bus_fmts(),
where we try to get the input bus formats through pdata->get_input_bus_fmts()
first.  If it's unavailable, fall back to the only format - MEDIA_BUS_FMT_FIXED,
which matches the default behavior if ->atomic_get_input_bus_fmts() is not
implemented as ->atomic_get_input_bus_fmts()'s kerneldoc indicates.

Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 30 +++
 include/drm/bridge/dw_mipi_dsi.h  | 11 +++
 2 files changed, 41 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 57eae0fdd970..8580b8a97fb1 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -536,6 +537,34 @@ static const struct mipi_dsi_host_ops dw_mipi_dsi_host_ops 
= {
.transfer = dw_mipi_dsi_host_transfer,
 };
 
+static u32 *
+dw_mipi_dsi_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+struct drm_bridge_state 
*bridge_state,
+struct drm_crtc_state *crtc_state,
+struct drm_connector_state 
*conn_state,
+u32 output_fmt,
+unsigned int *num_input_fmts)
+{
+   struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
+   const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
+   u32 *input_fmts;
+
+   if (pdata->get_input_bus_fmts)
+   return pdata->get_input_bus_fmts(pdata->priv_data,
+bridge, bridge_state,
+crtc_state, conn_state,
+output_fmt, num_input_fmts);
+
+   /* Fall back to MEDIA_BUS_FMT_FIXED as the only input format. */
+   input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+   input_fmts[0] = MEDIA_BUS_FMT_FIXED;
+   *num_input_fmts = 1;
+
+   return input_fmts;
+}
+
 static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
 {
u32 val;
@@ -1003,6 +1032,7 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge 
*bridge,
 static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state   = drm_atomic_helper_bridge_destroy_state,
+   .atomic_get_input_bus_fmts = 
dw_mipi_dsi_bridge_atomic_get_input_bus_fmts,
.atomic_reset   = drm_atomic_helper_bridge_reset,
.atomic_enable  = dw_mipi_dsi_bridge_atomic_enable,
.atomic_post_disable= dw_mipi_dsi_bridge_post_atomic_disable,
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index f54621b17a69..246650f2814f 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -11,7 +11,10 @@
 
 #include 
 
+#include 
 #include 
+#include 
+#include 
 #include 
 
 struct drm_display_mode;
@@ -56,6 +59,14 @@ struct dw_mipi_dsi_plat_data {
   unsigned long mode_flags,
   u32 lanes, u32 format);
 
+   u32 *(*get_input_bus_fmts)(void *priv_data,
+  struct drm_bridge *bridge,
+  struct drm_bridge_state *bridge_state,
+  struct drm_crtc_state *crtc_state,
+  struct drm_connector_state *conn_state,
+  u32 output_fmt,
+  unsigned int *num_input_fmts);
+
const struct dw_mipi_dsi_phy_ops *phy_ops;
const struct dw_mipi_dsi_host_ops *host_ops;
 
-- 
2.37.1



[PATCH 1/9] drm/bridge: synopsys: dw-mipi-dsi: Add dw_mipi_dsi_get_bridge() helper

2023-07-17 Thread Liu Ying
Add dw_mipi_dsi_get_bridge() helper so that it can be used by vendor
drivers which implement vendor specific extensions to Synopsys DW MIPI DSI.

Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 6 ++
 include/drm/bridge/dw_mipi_dsi.h  | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index b2efecf7d160..57eae0fdd970 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -1207,6 +1207,12 @@ void dw_mipi_dsi_set_slave(struct dw_mipi_dsi *dsi, 
struct dw_mipi_dsi *slave)
 }
 EXPORT_SYMBOL_GPL(dw_mipi_dsi_set_slave);
 
+struct drm_bridge *dw_mipi_dsi_get_bridge(struct dw_mipi_dsi *dsi)
+{
+   return >bridge;
+}
+EXPORT_SYMBOL_GPL(dw_mipi_dsi_get_bridge);
+
 /*
  * Probe/remove API, used from platforms based on the DRM bridge API.
  */
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index 5286a53a1875..f54621b17a69 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -11,6 +11,7 @@
 
 #include 
 
+#include 
 #include 
 
 struct drm_display_mode;
@@ -68,5 +69,6 @@ void dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi);
 int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder);
 void dw_mipi_dsi_unbind(struct dw_mipi_dsi *dsi);
 void dw_mipi_dsi_set_slave(struct dw_mipi_dsi *dsi, struct dw_mipi_dsi *slave);
+struct drm_bridge *dw_mipi_dsi_get_bridge(struct dw_mipi_dsi *dsi);
 
 #endif /* __DW_MIPI_DSI__ */
-- 
2.37.1



[PATCH 0/9] drm/bridge: imx: Add i.MX93 MIPI DSI support

2023-07-17 Thread Liu Ying
Hi,

This series aims to add MIPI DSI support for Freescale i.MX93 SoC.

There is a Synopsys DesignWare MIPI DSI host controller and a Synopsys
Designware MIPI DPHY embedded in i.MX93.  Some configurations and
extensions to them are controlled by i.MX93 media blk-ctrl.

Add a DRM bridge for i.MX93 MIPI DSI by using existing DW MIPI DSI
bridge helpers and implementing i.MX93 MIPI DSI specific extensions.

Note that since this series touches the dw-mipi-dsi driver, tests are
needed to be done for meson, rockchip and stm.

Patch 1 ~ 7 do preparation work for adding i.MX93 MIPI DSI DRM bridge driver.

Patch 8 adds DT-binding documentation for i.MX93 MIPI DSI.

Patch 9 adds i.MX93 MIPI DSI DRM bridge.

Liu Ying (9):
  drm/bridge: synopsys: dw-mipi-dsi: Add dw_mipi_dsi_get_bridge() helper
  drm/bridge: synopsys: dw-mipi-dsi: Add input bus format negotiation
support
  drm/bridge: synopsys: dw-mipi-dsi: Force input bus flags
  drm/bridge: synopsys: dw-mipi-dsi: Add mode fixup support
  drm/bridge: synopsys: dw-mipi-dsi: Use pixel clock rate to calculate
lbcc
  drm/bridge: synopsys: dw-mipi-dsi: Set minimum lane byte clock cycles
for HSA and HBP
  drm/bridge: synopsys: dw-mipi-dsi: Disable HSTX and LPRX timeout check
  dt-bindings: display: bridge: Document Freescale i.MX93 MIPI DSI
  drm/bridge: imx: Add i.MX93 MIPI DSI support

 .../display/bridge/fsl,imx93-mipi-dsi.yaml| 115 +++
 drivers/gpu/drm/bridge/imx/Kconfig|  10 +
 drivers/gpu/drm/bridge/imx/Makefile   |   1 +
 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c   | 934 ++
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c |  91 +-
 include/drm/bridge/dw_mipi_dsi.h  |  16 +
 6 files changed, 1163 insertions(+), 4 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/fsl,imx93-mipi-dsi.yaml
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c

-- 
2.37.1



[PATCH v2] drm/mxsfb: Disable overlay plane in mxsfb_plane_overlay_atomic_disable()

2023-06-12 Thread Liu Ying
When disabling overlay plane in mxsfb_plane_overlay_atomic_update(),
overlay plane's framebuffer pointer is NULL.  So, dereferencing it would
cause a kernel Oops(NULL pointer dereferencing).  Fix the issue by
disabling overlay plane in mxsfb_plane_overlay_atomic_disable() instead.

Fixes: cb285a5348e7 ("drm: mxsfb: Replace mxsfb_get_fb_paddr() with 
drm_fb_cma_get_gem_addr()")
Cc: sta...@vger.kernel.org # 5.19+
Signed-off-by: Liu Ying 
---
v1->v2:
* Cc stable. (Marek)

 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c 
b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 3bcc9c0f2019..7ed2516b6de0 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -611,6 +611,14 @@ static void mxsfb_plane_overlay_atomic_update(struct 
drm_plane *plane,
writel(ctrl, mxsfb->base + LCDC_AS_CTRL);
 }
 
+static void mxsfb_plane_overlay_atomic_disable(struct drm_plane *plane,
+  struct drm_atomic_state *state)
+{
+   struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
+
+   writel(0, mxsfb->base + LCDC_AS_CTRL);
+}
+
 static bool mxsfb_format_mod_supported(struct drm_plane *plane,
   uint32_t format,
   uint64_t modifier)
@@ -626,6 +634,7 @@ static const struct drm_plane_helper_funcs 
mxsfb_plane_primary_helper_funcs = {
 static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
.atomic_check = mxsfb_plane_atomic_check,
.atomic_update = mxsfb_plane_overlay_atomic_update,
+   .atomic_disable = mxsfb_plane_overlay_atomic_disable,
 };
 
 static const struct drm_plane_funcs mxsfb_plane_funcs = {
-- 
2.37.1



[PATCH] drm/mxsfb: Disable overlay plane in mxsfb_plane_overlay_atomic_disable()

2023-06-12 Thread Liu Ying
When disabling overlay plane in mxsfb_plane_overlay_atomic_update(),
overlay plane's framebuffer pointer is NULL.  So, dereferencing it would
cause a kernel Oops(NULL pointer dereferencing).  Fix the issue by
disabling overlay plane in mxsfb_plane_overlay_atomic_disable() instead.

Fixes: cb285a5348e7 ("drm: mxsfb: Replace mxsfb_get_fb_paddr() with 
drm_fb_cma_get_gem_addr()")
Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c 
b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 3bcc9c0f2019..7ed2516b6de0 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -611,6 +611,14 @@ static void mxsfb_plane_overlay_atomic_update(struct 
drm_plane *plane,
writel(ctrl, mxsfb->base + LCDC_AS_CTRL);
 }
 
+static void mxsfb_plane_overlay_atomic_disable(struct drm_plane *plane,
+  struct drm_atomic_state *state)
+{
+   struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
+
+   writel(0, mxsfb->base + LCDC_AS_CTRL);
+}
+
 static bool mxsfb_format_mod_supported(struct drm_plane *plane,
   uint32_t format,
   uint64_t modifier)
@@ -626,6 +634,7 @@ static const struct drm_plane_helper_funcs 
mxsfb_plane_primary_helper_funcs = {
 static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
.atomic_check = mxsfb_plane_atomic_check,
.atomic_update = mxsfb_plane_overlay_atomic_update,
+   .atomic_disable = mxsfb_plane_overlay_atomic_disable,
 };
 
 static const struct drm_plane_funcs mxsfb_plane_funcs = {
-- 
2.37.1



[PATCH v3 2/2] drm/bridge: imx: Add i.MX93 parallel display format configuration support

2023-06-05 Thread Liu Ying
NXP i.MX93 mediamix blk-ctrl contains one DISPLAY_MUX register which
configures parallel display format by using the "PARALLEL_DISP_FORMAT"
field. Add a DRM bridge driver to support the display format configuration.

Signed-off-by: Liu Ying 
---
v2->v3:
* No change.

v1->v2:
* Set *num_input_fmts to zero in case
  imx93_pdfc_bridge_atomic_get_input_bus_fmts() returns NULL.
* Replace .remove callback with .remove_new callback in
  imx93_pdfc_bridge_driver.

 drivers/gpu/drm/bridge/imx/Kconfig  |   8 +
 drivers/gpu/drm/bridge/imx/Makefile |   1 +
 drivers/gpu/drm/bridge/imx/imx93-pdfc.c | 209 
 3 files changed, 218 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-pdfc.c

diff --git a/drivers/gpu/drm/bridge/imx/Kconfig 
b/drivers/gpu/drm/bridge/imx/Kconfig
index 608f47f41bcd..adbd75a924d1 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -44,4 +44,12 @@ config DRM_IMX8QXP_PIXEL_LINK_TO_DPI
  Choose this to enable pixel link to display pixel interface(PXL2DPI)
  found in Freescale i.MX8qxp processor.
 
+config DRM_IMX93_PARALLEL_DISP_FMT_CONFIG
+   tristate "NXP i.MX93 parallel display format configuration"
+   depends on OF
+   select DRM_KMS_HELPER
+   help
+ Choose this to enable parallel display format configuration
+ found in NXP i.MX93 processor.
+
 endif # ARCH_MXC || COMPILE_TEST
diff --git a/drivers/gpu/drm/bridge/imx/Makefile 
b/drivers/gpu/drm/bridge/imx/Makefile
index aa90ec8d5433..e88821733770 100644
--- a/drivers/gpu/drm/bridge/imx/Makefile
+++ b/drivers/gpu/drm/bridge/imx/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_DRM_IMX8QXP_LDB) += imx8qxp-ldb.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o
+obj-$(CONFIG_DRM_IMX93_PARALLEL_DISP_FMT_CONFIG) += imx93-pdfc.o
diff --git a/drivers/gpu/drm/bridge/imx/imx93-pdfc.c 
b/drivers/gpu/drm/bridge/imx/imx93-pdfc.c
new file mode 100644
index ..61e01b503be5
--- /dev/null
+++ b/drivers/gpu/drm/bridge/imx/imx93-pdfc.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2022,2023 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#define DRIVER_NAME"imx93_pdfc"
+
+#define DISPLAY_MUX0x60
+#define  PARALLEL_DISP_FORMAT  0x700
+
+enum imx93_pdfc_format {
+   RGB888_TO_RGB888 = 0x0,
+   RGB888_TO_RGB666 = 0x1 << 8,
+   RGB565_TO_RGB565 = 0x2 << 8,
+};
+
+struct imx93_pdfc {
+   struct drm_bridge bridge;
+   struct drm_bridge *next_bridge;
+   struct device *dev;
+   struct regmap *regmap;
+   u32 format;
+};
+
+static int imx93_pdfc_bridge_attach(struct drm_bridge *bridge,
+   enum drm_bridge_attach_flags flags)
+{
+   struct imx93_pdfc *pdfc = bridge->driver_private;
+
+   return drm_bridge_attach(bridge->encoder, pdfc->next_bridge, bridge, 
flags);
+}
+
+static void
+imx93_pdfc_bridge_atomic_enable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
+{
+   struct imx93_pdfc *pdfc = bridge->driver_private;
+
+   regmap_update_bits(pdfc->regmap, DISPLAY_MUX, PARALLEL_DISP_FORMAT,
+  pdfc->format);
+}
+
+static const u32 imx93_pdfc_bus_output_fmts[] = {
+   MEDIA_BUS_FMT_RGB888_1X24,
+   MEDIA_BUS_FMT_RGB666_1X18,
+   MEDIA_BUS_FMT_RGB565_1X16,
+   MEDIA_BUS_FMT_FIXED
+};
+
+static bool imx93_pdfc_bus_output_fmt_supported(u32 fmt)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(imx93_pdfc_bus_output_fmts); i++) {
+   if (imx93_pdfc_bus_output_fmts[i] == fmt)
+   return true;
+   }
+
+   return false;
+}
+
+static u32 *
+imx93_pdfc_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*bridge_state,
+   struct drm_crtc_state *crtc_state,
+   struct drm_connector_state 
*conn_state,
+   u32 output_fmt,
+   unsigned int *num_input_fmts)
+{
+   u32 *input_fmts;
+
+   *num_input_fmts = 0;
+
+   if (!imx93_pdfc_bus_output_fmt_supported(output_fmt))
+   return NULL;
+
+   input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+
+   switch (output_fmt) {
+   case MEDIA_BUS_FMT_RGB888_1X24:
+   case MEDIA_BUS_FMT_RGB565_1X16:
+   input_fmts[0] = output_fmt;
+   break;
+   case MEDIA_BUS_FMT_RGB666_1X18:
+   case MEDIA_BUS

[PATCH v3 1/2] dt-bindings: soc: imx93-media-blk-ctrl: Add PDFC subnode to schema and example

2023-06-05 Thread Liu Ying
i.MX93 SoC mediamix blk-ctrl contains one DISPLAY_MUX register which
configures parallel display format by using the "PARALLEL_DISP_FORMAT"
field. Document the Parallel Display Format Configuration(PDFC) subnode
and add the subnode to example.

Signed-off-by: Liu Ying 
---
v2->v3:
* Newly introduced to replace the standalone dt-binding in v1 and v2. (Rob)

 .../soc/imx/fsl,imx93-media-blk-ctrl.yaml | 68 +++
 1 file changed, 68 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml 
b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
index b3554e7f9e76..3f550c30d93d 100644
--- a/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
+++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml
@@ -24,6 +24,12 @@ properties:
   reg:
 maxItems: 1
 
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 1
+
   '#power-domain-cells':
 const: 1
 
@@ -46,9 +52,43 @@ properties:
   - const: csi
   - const: dsi
 
+  bridge@60:
+type: object
+additionalProperties: false
+
+properties:
+  compatible:
+const: nxp,imx93-pdfc
+
+  reg:
+maxItems: 1
+
+  ports:
+$ref: /schemas/graph.yaml#/properties/ports
+
+properties:
+  port@0:
+$ref: /schemas/graph.yaml#/properties/port
+description: Input port node to receive pixel data.
+
+  port@1:
+$ref: /schemas/graph.yaml#/properties/port
+description: Output port node to downstream pixel data receivers.
+
+required:
+  - port@0
+  - port@1
+
+required:
+  - compatible
+  - reg
+  - ports
+
 required:
   - compatible
   - reg
+  - '#address-cells'
+  - '#size-cells'
   - power-domains
   - clocks
   - clock-names
@@ -76,5 +116,33 @@ examples:
< IMX93_CLK_MIPI_DSI_GATE>;
clock-names = "apb", "axi", "nic", "disp", "cam",
  "pxp", "lcdif", "isi", "csi", "dsi";
+  #address-cells = <1>;
+  #size-cells = <1>;
   #power-domain-cells = <1>;
+
+  bridge@60 {
+compatible = "nxp,imx93-pdfc";
+reg = <0x60 0x4>;
+
+ports {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  port@0 {
+reg = <0>;
+
+pdfc_from_lcdif: endpoint {
+  remote-endpoint = <_to_pdfc>;
+};
+  };
+
+  port@1 {
+reg = <1>;
+
+pdfc_to_panel: endpoint {
+  remote-endpoint = <_from_pdfc>;
+};
+  };
+};
+  };
 };
-- 
2.37.1



[PATCH v3 0/2] drm/bridge: imx: Add i.MX93 parallel display format configuration support

2023-06-05 Thread Liu Ying
Hi,

This patch set aims to add NXP i.MX93 parallel display format configuration
DRM bridge driver support. i.MX93 mediamix blk-ctrl contains one
DISPLAY_MUX register which configures parallel display format by using
the "PARALLEL_DISP_FORMAT" field. i.MX93 LCDIF display controller's
parallel output connects with this piece of small logic to configure
parallel display format.

Patch 1/2 adds NXP i.MX93 parallel display format configuration subnode
in i.MX93 mediamix blk-ctrl dt-binding.

Patch 2/2 adds NXP i.MX93 parallel display format configuration DRM bridge
driver support.

v2->v3:
* Define i.MX93 parallel display format configuration subnode in
  i.MX93 mediamix blk-ctrl dt-binding. (Rob)

v1->v2:
* Set *num_input_fmts to zero in case
  imx93_pdfc_bridge_atomic_get_input_bus_fmts() returns NULL in patch 2/2.
* Replace .remove callback with .remove_new callback in
  imx93_pdfc_bridge_driver in patch 2/2.

Liu Ying (2):
  dt-bindings: soc: imx93-media-blk-ctrl: Add PDFC subnode to schema and
example
  drm/bridge: imx: Add i.MX93 parallel display format configuration
support

 .../soc/imx/fsl,imx93-media-blk-ctrl.yaml |  68 ++
 drivers/gpu/drm/bridge/imx/Kconfig|   8 +
 drivers/gpu/drm/bridge/imx/Makefile   |   1 +
 drivers/gpu/drm/bridge/imx/imx93-pdfc.c   | 209 ++
 4 files changed, 286 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-pdfc.c

-- 
2.37.1



[PATCH v2 2/2] drm/bridge: imx: Add i.MX93 parallel display format configuration support

2023-05-31 Thread Liu Ying
NXP i.MX93 mediamix blk-ctrl contains one DISPLAY_MUX register which
configures parallel display format by using the "PARALLEL_DISP_FORMAT"
field. Add a DRM bridge driver to support the display format configuration.

Signed-off-by: Liu Ying 
---
v1->v2:
* Set *num_input_fmts to zero in case
  imx93_pdfc_bridge_atomic_get_input_bus_fmts() returns NULL.
* Replace .remove callback with .remove_new callback in
  imx93_pdfc_bridge_driver.

 drivers/gpu/drm/bridge/imx/Kconfig  |   8 +
 drivers/gpu/drm/bridge/imx/Makefile |   1 +
 drivers/gpu/drm/bridge/imx/imx93-pdfc.c | 209 
 3 files changed, 218 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-pdfc.c

diff --git a/drivers/gpu/drm/bridge/imx/Kconfig 
b/drivers/gpu/drm/bridge/imx/Kconfig
index 608f47f41bcd..adbd75a924d1 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -44,4 +44,12 @@ config DRM_IMX8QXP_PIXEL_LINK_TO_DPI
  Choose this to enable pixel link to display pixel interface(PXL2DPI)
  found in Freescale i.MX8qxp processor.
 
+config DRM_IMX93_PARALLEL_DISP_FMT_CONFIG
+   tristate "NXP i.MX93 parallel display format configuration"
+   depends on OF
+   select DRM_KMS_HELPER
+   help
+ Choose this to enable parallel display format configuration
+ found in NXP i.MX93 processor.
+
 endif # ARCH_MXC || COMPILE_TEST
diff --git a/drivers/gpu/drm/bridge/imx/Makefile 
b/drivers/gpu/drm/bridge/imx/Makefile
index aa90ec8d5433..e88821733770 100644
--- a/drivers/gpu/drm/bridge/imx/Makefile
+++ b/drivers/gpu/drm/bridge/imx/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_DRM_IMX8QXP_LDB) += imx8qxp-ldb.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o
 obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o
+obj-$(CONFIG_DRM_IMX93_PARALLEL_DISP_FMT_CONFIG) += imx93-pdfc.o
diff --git a/drivers/gpu/drm/bridge/imx/imx93-pdfc.c 
b/drivers/gpu/drm/bridge/imx/imx93-pdfc.c
new file mode 100644
index ..61e01b503be5
--- /dev/null
+++ b/drivers/gpu/drm/bridge/imx/imx93-pdfc.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2022,2023 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#define DRIVER_NAME"imx93_pdfc"
+
+#define DISPLAY_MUX0x60
+#define  PARALLEL_DISP_FORMAT  0x700
+
+enum imx93_pdfc_format {
+   RGB888_TO_RGB888 = 0x0,
+   RGB888_TO_RGB666 = 0x1 << 8,
+   RGB565_TO_RGB565 = 0x2 << 8,
+};
+
+struct imx93_pdfc {
+   struct drm_bridge bridge;
+   struct drm_bridge *next_bridge;
+   struct device *dev;
+   struct regmap *regmap;
+   u32 format;
+};
+
+static int imx93_pdfc_bridge_attach(struct drm_bridge *bridge,
+   enum drm_bridge_attach_flags flags)
+{
+   struct imx93_pdfc *pdfc = bridge->driver_private;
+
+   return drm_bridge_attach(bridge->encoder, pdfc->next_bridge, bridge, 
flags);
+}
+
+static void
+imx93_pdfc_bridge_atomic_enable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
+{
+   struct imx93_pdfc *pdfc = bridge->driver_private;
+
+   regmap_update_bits(pdfc->regmap, DISPLAY_MUX, PARALLEL_DISP_FORMAT,
+  pdfc->format);
+}
+
+static const u32 imx93_pdfc_bus_output_fmts[] = {
+   MEDIA_BUS_FMT_RGB888_1X24,
+   MEDIA_BUS_FMT_RGB666_1X18,
+   MEDIA_BUS_FMT_RGB565_1X16,
+   MEDIA_BUS_FMT_FIXED
+};
+
+static bool imx93_pdfc_bus_output_fmt_supported(u32 fmt)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(imx93_pdfc_bus_output_fmts); i++) {
+   if (imx93_pdfc_bus_output_fmts[i] == fmt)
+   return true;
+   }
+
+   return false;
+}
+
+static u32 *
+imx93_pdfc_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*bridge_state,
+   struct drm_crtc_state *crtc_state,
+   struct drm_connector_state 
*conn_state,
+   u32 output_fmt,
+   unsigned int *num_input_fmts)
+{
+   u32 *input_fmts;
+
+   *num_input_fmts = 0;
+
+   if (!imx93_pdfc_bus_output_fmt_supported(output_fmt))
+   return NULL;
+
+   input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+
+   switch (output_fmt) {
+   case MEDIA_BUS_FMT_RGB888_1X24:
+   case MEDIA_BUS_FMT_RGB565_1X16:
+   input_fmts[0] = output_fmt;
+   break;
+   case MEDIA_BUS_FMT_RGB666_1X18:
+   case MEDIA_BUS_FMT_FIXED:
+ 

[PATCH v2 1/2] dt-bindings: display: bridge: Add NXP i.MX93 parallel display format configuration

2023-05-31 Thread Liu Ying
NXP i.MX93 mediamix blk-ctrl contains one DISPLAY_MUX register which
configures parallel display format by using the "PARALLEL_DISP_FORMAT"
field. Add device tree bindings for the display format configuration.

Signed-off-by: Liu Ying 
---
v1->v2:
* No change.

 .../display/bridge/nxp,imx93-pdfc.yaml| 78 +++
 1 file changed, 78 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/nxp,imx93-pdfc.yaml

diff --git 
a/Documentation/devicetree/bindings/display/bridge/nxp,imx93-pdfc.yaml 
b/Documentation/devicetree/bindings/display/bridge/nxp,imx93-pdfc.yaml
new file mode 100644
index ..a84bfb46b01d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/nxp,imx93-pdfc.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/nxp,imx93-pdfc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX93 Parallel Display Format Configuration
+
+maintainers:
+  - Liu Ying 
+
+description: |
+  The i.MX93 mediamix blk-ctrl contains one DISPLAY_MUX register which
+  configures parallel display format by using the "PARALLEL_DISP_FORMAT"
+  field.
+
+properties:
+  compatible:
+const: nxp,imx93-pdfc
+
+  reg:
+maxItems: 1
+
+  ports:
+$ref: /schemas/graph.yaml#/properties/ports
+
+properties:
+  port@0:
+$ref: /schemas/graph.yaml#/properties/port
+description: Input port node to receive pixel data.
+
+  port@1:
+$ref: /schemas/graph.yaml#/properties/port
+description: Output port node to downstream pixel data receivers.
+
+required:
+  - port@0
+  - port@1
+
+required:
+  - compatible
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+
+blk-ctrl {
+#address-cells = <1>;
+#size-cells = <1>;
+
+bridge@60 {
+compatible = "nxp,imx93-pdfc";
+reg = <0x60 0x4>;
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+
+pdfc_from_lcdif: endpoint {
+remote-endpoint = <_to_pdfc>;
+};
+};
+
+port@1 {
+reg = <1>;
+
+pdfc_to_panel: endpoint {
+remote-endpoint = <_from_pdfc>;
+};
+};
+};
+};
+};
-- 
2.37.1



[PATCH v2 0/2] drm/bridge: imx: Add i.MX93 parallel display format configuration support

2023-05-31 Thread Liu Ying
Hi,

This patch set aims to add NXP i.MX93 parallel display format configuration
DRM bridge driver support. i.MX93 mediamix blk-ctrl contains one
DISPLAY_MUX register which configures parallel display format by using
the "PARALLEL_DISP_FORMAT" field. i.MX93 LCDIF display controller's
parallel output connects with this piece of small logic to configure
parallel display format.

Patch 1/2 adds NXP i.MX93 parallel display format configuration dt-bindings.

Patch 2/2 adds NXP i.MX93 parallel display format configuration DRM bridge
driver support.

v1->v2:
* Set *num_input_fmts to zero in case
  imx93_pdfc_bridge_atomic_get_input_bus_fmts() returns NULL in patch 2/2.
* Replace .remove callback with .remove_new callback in
  imx93_pdfc_bridge_driver in patch 2/2.

Liu Ying (2):
  dt-bindings: display: bridge: Add NXP i.MX93 parallel display format
configuration
  drm/bridge: imx: Add i.MX93 parallel display format configuration
support

 .../display/bridge/nxp,imx93-pdfc.yaml|  78 +++
 drivers/gpu/drm/bridge/imx/Kconfig|   8 +
 drivers/gpu/drm/bridge/imx/Makefile   |   1 +
 drivers/gpu/drm/bridge/imx/imx93-pdfc.c   | 209 ++
 4 files changed, 296 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/bridge/nxp,imx93-pdfc.yaml
 create mode 100644 drivers/gpu/drm/bridge/imx/imx93-pdfc.c

-- 
2.37.1



[PATCH v6 6/6] drm: lcdif: Add i.MX93 LCDIF compatible string

2023-05-10 Thread Liu Ying
With all previous preparations done to make it possible for the
single LCDIF embedded in i.MX93 SoC to drive multiple displays
simultaneously, add i.MX93 LCDIF compatible string as the last
step of adding i.MX93 LCDIF support.

Tested-by: Alexander Stein 
Reviewed-by: Alexander Stein 
Reviewed-by: Marek Vasut 
Signed-off-by: Liu Ying 
---
v5->v6:
* Add Marek's R-b tag.

v4->v5:
* Add Alexander's T-b tag.

v3->v4:
* Add Alexander's R-b tag.

v2->v3:
* Fix a trivial typo in commit message.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)

 drivers/gpu/drm/mxsfb/lcdif_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index dc85498b81cd..c9d8cbb21407 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -251,6 +251,7 @@ static const struct drm_driver lcdif_driver = {
 
 static const struct of_device_id lcdif_dt_ids[] = {
{ .compatible = "fsl,imx8mp-lcdif" },
+   { .compatible = "fsl,imx93-lcdif" },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, lcdif_dt_ids);
-- 
2.37.1



[PATCH v6 5/6] drm: lcdif: Add multiple encoders and first bridges support

2023-05-10 Thread Liu Ying
The single LCDIF embedded in i.MX93 SoC may drive multiple displays
simultaneously.  Look at LCDIF output port's remote port parents to
find all enabled first bridges.  Add an encoder for each found bridge
and attach the bridge to the encoder.  This is a preparation for
adding i.MX93 LCDIF support.

Tested-by: Alexander Stein 
Acked-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v5->v6:
* Drop MAX_DISPLAYS macro. (Marek)
* Drop the encoder member in struct lcdif_drm_private.
* Drop endpoint id check.
* Allocate encoders by calling devm_kzalloc().

v4->v5:
* Rebase upon v6.4-rc1 and resolve a trivial conflict.
* Add Alexander's A-b and T-b tags.

v3->v4:
* Improve warning message when ignoring invalid LCDIF OF endpoint ids.
  (Alexander)

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
* Drop unneeded 'bridges' member from lcdif_drm_private structure.

 drivers/gpu/drm/mxsfb/lcdif_drv.c | 70 +++
 drivers/gpu/drm/mxsfb/lcdif_drv.h |  2 -
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 21 ++
 3 files changed, 65 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index e816f87828fb..dc85498b81cd 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -9,13 +9,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -38,19 +41,70 @@ static const struct drm_mode_config_helper_funcs 
lcdif_mode_config_helpers = {
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 };
 
+static const struct drm_encoder_funcs lcdif_encoder_funcs = {
+   .destroy = drm_encoder_cleanup,
+};
+
 static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif)
 {
-   struct drm_device *drm = lcdif->drm;
+   struct device *dev = lcdif->drm->dev;
+   struct device_node *ep;
struct drm_bridge *bridge;
int ret;
 
-   bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0, 0);
-   if (IS_ERR(bridge))
-   return PTR_ERR(bridge);
-
-   ret = drm_bridge_attach(>encoder, bridge, NULL, 0);
-   if (ret)
-   return dev_err_probe(drm->dev, ret, "Failed to attach 
bridge\n");
+   for_each_endpoint_of_node(dev->of_node, ep) {
+   struct device_node *remote;
+   struct of_endpoint of_ep;
+   struct drm_encoder *encoder;
+
+   remote = of_graph_get_remote_port_parent(ep);
+   if (!of_device_is_available(remote)) {
+   of_node_put(remote);
+   continue;
+   }
+   of_node_put(remote);
+
+   ret = of_graph_parse_endpoint(ep, _ep);
+   if (ret < 0) {
+   dev_err(dev, "Failed to parse endpoint %pOF\n", ep);
+   of_node_put(ep);
+   return ret;
+   }
+
+   bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, of_ep.id);
+   if (IS_ERR(bridge)) {
+   of_node_put(ep);
+   return dev_err_probe(dev, PTR_ERR(bridge),
+"Failed to get bridge for 
endpoint%u\n",
+of_ep.id);
+   }
+
+   encoder = devm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL);
+   if (!encoder) {
+   dev_err(dev, "Failed to allocate encoder for 
endpoint%u\n",
+   of_ep.id);
+   of_node_put(ep);
+   return -ENOMEM;
+   }
+
+   encoder->possible_crtcs = drm_crtc_mask(>crtc);
+   ret = drm_encoder_init(lcdif->drm, encoder, 
_encoder_funcs,
+  DRM_MODE_ENCODER_NONE, NULL);
+   if (ret) {
+   dev_err(dev, "Failed to initialize encoder for 
endpoint%u: %d\n",
+   of_ep.id, ret);
+   of_node_put(ep);
+   return ret;
+   }
+
+   ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+   if (ret) {
+   of_node_put(ep);
+   return dev_err_probe(dev, ret,
+"Failed to attach bridge for 
endpoint%u\n",
+of_ep.id);
+   }
+   }
 
return 0;
 }
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h 
b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index aa6d099a1897..61483a4e058d 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_d

[PATCH v6 4/6] drm: lcdif: Check consistent bus format and flags across first bridges

2023-05-10 Thread Liu Ying
The single LCDIF embedded in i.MX93 SoC may drive multiple displays
simultaneously.  Check bus format and flags across first bridges in
->atomic_check() to ensure they are consistent.  This is a preparation
for adding i.MX93 LCDIF support.

Acked-by: Alexander Stein 
Tested-by: Alexander Stein 
Reviewed-by: Marek Vasut 
Signed-off-by: Liu Ying 
---
v5->v6:
* Add Marek's R-b.
* A slight change brought from the update in patch 2/6 to keep default
  MEDIA_BUS_FMT_RGB888_1X24 bus format.

v4->v5:
* Add Alexander's A-b and T-b tags.

v3->v4:
* No change.

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Drop a comment about bridge input bus format from lcdif_crtc_atomic_check().

 drivers/gpu/drm/mxsfb/lcdif_drv.c |  2 -
 drivers/gpu/drm/mxsfb/lcdif_drv.h |  1 -
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 82 ++-
 3 files changed, 58 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index 6fb5b469ee5a..e816f87828fb 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -52,8 +52,6 @@ static int lcdif_attach_bridge(struct lcdif_drm_private 
*lcdif)
if (ret)
return dev_err_probe(drm->dev, ret, "Failed to attach 
bridge\n");
 
-   lcdif->bridge = bridge;
-
return 0;
 }
 
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h 
b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index 6cdba6e20c02..aa6d099a1897 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
@@ -31,7 +31,6 @@ struct lcdif_drm_private {
} planes;
struct drm_crtc crtc;
struct drm_encoder  encoder;
-   struct drm_bridge   *bridge;
 };
 
 static inline struct lcdif_drm_private *
diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index fab2253e4786..e13382beb53e 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -424,15 +425,19 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
   struct drm_atomic_state *state)
 {
struct drm_device *drm = crtc->dev;
-   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
  crtc);
struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
bool has_primary = crtc_state->plane_mask &
   drm_plane_mask(crtc->primary);
+   struct drm_connector_state *connector_state;
+   struct drm_connector *connector;
+   struct drm_encoder *encoder;
struct drm_bridge_state *bridge_state;
-   struct drm_bridge *bridge = lcdif->bridge;
-   int ret;
+   struct drm_bridge *bridge;
+   u32 bus_format, bus_flags;
+   bool format_set = false, flags_set = false;
+   int ret, i;
 
/* The primary plane has to be enabled when the CRTC is active. */
if (crtc_state->active && !has_primary)
@@ -442,29 +447,58 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
if (ret)
return ret;
 
-   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
-   if (!bridge_state)
-   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_FIXED;
-   else
-   lcdif_crtc_state->bus_format = 
bridge_state->input_bus_cfg.format;
-
-   if (lcdif_crtc_state->bus_format == MEDIA_BUS_FMT_FIXED) {
-   dev_warn_once(drm->dev,
- "Bridge does not provide bus format, assuming 
MEDIA_BUS_FMT_RGB888_1X24.\n"
- "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
-   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
-   } else if (!lcdif_crtc_state->bus_format) {
-   /* If all else fails, default to RGB888_1X24 */
-   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   /* Try to find consistent bus format and flags across first bridges. */
+   for_each_new_connector_in_state(state, connector, connector_state, i) {
+   if (!connector_state->crtc)
+   continue;
+
+   encoder = connector_state->best_encoder;
+
+   bridge = drm_bridge_chain_get_first_bridge(encoder);
+   if (!bridge)
+   continue;
+
+   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+   if (!bridge_state)
+   bus_format = MEDIA_BUS_FMT_FIXED;
+   else
+

[PATCH v6 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()

2023-05-10 Thread Liu Ying
Instead of determining LCDIF output bus format and bus flags in
->atomic_enable(), do that in ->atomic_check().  This is a
preparation for the upcoming patch to check consistent bus format
and bus flags across all first downstream bridges in ->atomic_check().
New lcdif_crtc_state structure is introduced to cache bus format
and bus flags states in ->atomic_check() so that they can be read
in ->atomic_enable().

Tested-by: Alexander Stein 
Reviewed-by: Alexander Stein 
Reviewed-by: Marek Vasut 
Signed-off-by: Liu Ying 
---
v5->v6:
* Add Marek's R-b tag.
* A slight change brought from the update in patch 2/6 to keep default
  MEDIA_BUS_FMT_RGB888_1X24 bus format.

v4->v5:
* Add Alexander's R-b and T-b tags.

v3->v4:
* Use 'new_{c,p}state' instead of 'new_{crtc,plane}_state'. (Alexander)
* Simplify lcdif_crtc_reset() by calling lcdif_crtc_atomic_destroy_state().
  (Alexander)
* Add '!crtc->state' check in lcdif_crtc_atomic_duplicate_state(). (Alexander)

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Add comment on the 'base' member of lcdif_crtc_state structure to
  note it should always be the first member. (Lothar)

 drivers/gpu/drm/mxsfb/lcdif_kms.c | 140 ++
 1 file changed, 102 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index ba00a155d9b6..fab2253e4786 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -30,6 +30,18 @@
 #include "lcdif_drv.h"
 #include "lcdif_regs.h"
 
+struct lcdif_crtc_state {
+   struct drm_crtc_state   base;   /* always be the first member */
+   u32 bus_format;
+   u32 bus_flags;
+};
+
+static inline struct lcdif_crtc_state *
+to_lcdif_crtc_state(struct drm_crtc_state *s)
+{
+   return container_of(s, struct lcdif_crtc_state, base);
+}
+
 /* 
-
  * CRTC
  */
@@ -385,48 +397,75 @@ static void lcdif_reset_block(struct lcdif_drm_private 
*lcdif)
readl(lcdif->base + LCDC_V8_CTRL);
 }
 
-static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
-struct drm_plane_state *plane_state,
-struct drm_bridge_state *bridge_state,
-const u32 bus_format)
+static void lcdif_crtc_mode_set_nofb(struct drm_crtc_state *crtc_state,
+struct drm_plane_state *plane_state)
 {
-   struct drm_device *drm = lcdif->crtc.dev;
-   struct drm_display_mode *m = >crtc.state->adjusted_mode;
-   u32 bus_flags = 0;
-
-   if (lcdif->bridge->timings)
-   bus_flags = lcdif->bridge->timings->input_bus_flags;
-   else if (bridge_state)
-   bus_flags = bridge_state->input_bus_cfg.flags;
+   struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
+   struct drm_device *drm = crtc_state->crtc->dev;
+   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
+   struct drm_display_mode *m = _state->adjusted_mode;
 
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
 m->crtc_clock,
 (int)(clk_get_rate(lcdif->clk) / 1000));
DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
-bus_flags);
+lcdif_crtc_state->bus_flags);
DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
 
/* Mandatory eLCDIF reset as per the Reference Manual */
lcdif_reset_block(lcdif);
 
-   lcdif_set_formats(lcdif, plane_state, bus_format);
+   lcdif_set_formats(lcdif, plane_state, lcdif_crtc_state->bus_format);
 
-   lcdif_set_mode(lcdif, bus_flags);
+   lcdif_set_mode(lcdif, lcdif_crtc_state->bus_flags);
 }
 
 static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
   struct drm_atomic_state *state)
 {
+   struct drm_device *drm = crtc->dev;
+   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
  crtc);
+   struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
bool has_primary = crtc_state->plane_mask &
   drm_plane_mask(crtc->primary);
+   struct drm_bridge_state *bridge_state;
+   struct drm_bridge *bridge = lcdif->bridge;
+   int ret;
 
/* The primary plane has to be enabled when the CRTC is active. */
if (crtc_state->active && !has_p

[PATCH v6 2/6] drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge

2023-05-10 Thread Liu Ying
A valid bridge is already found in lcdif_attach_bridge() and set
to lcdif->bridge, so lcdif->bridge cannot be a NULL pointer. Drop
the unnecessary NULL pointer check in KMS stage.

Tested-by: Alexander Stein 
Reviewed-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v5->v6:
* Keep default MEDIA_BUS_FMT_RGB888_1X24 bus format in case
  bridge_state->input_bus_cfg.format is zero. (Marek)

v4->v5:
* Add Alexander's T-b tag.

v3->v4:
* Add Alexander's R-b tag.

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)

 drivers/gpu/drm/mxsfb/lcdif_kms.c | 36 +--
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index 262bc43b1079..ba00a155d9b6 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -394,7 +394,7 @@ static void lcdif_crtc_mode_set_nofb(struct 
lcdif_drm_private *lcdif,
struct drm_display_mode *m = >crtc.state->adjusted_mode;
u32 bus_flags = 0;
 
-   if (lcdif->bridge && lcdif->bridge->timings)
+   if (lcdif->bridge->timings)
bus_flags = lcdif->bridge->timings->input_bus_flags;
else if (bridge_state)
bus_flags = bridge_state->input_bus_cfg.flags;
@@ -463,30 +463,24 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc 
*crtc,
struct drm_display_mode *m = >crtc.state->adjusted_mode;
struct drm_bridge_state *bridge_state = NULL;
struct drm_device *drm = lcdif->drm;
-   u32 bus_format = 0;
+   u32 bus_format;
dma_addr_t paddr;
 
-   /* If there is a bridge attached to the LCDIF, use its bus format */
-   if (lcdif->bridge) {
-   bridge_state =
-   drm_atomic_get_new_bridge_state(state,
-   lcdif->bridge);
-   if (!bridge_state)
-   bus_format = MEDIA_BUS_FMT_FIXED;
-   else
-   bus_format = bridge_state->input_bus_cfg.format;
-
-   if (bus_format == MEDIA_BUS_FMT_FIXED) {
-   dev_warn_once(drm->dev,
- "Bridge does not provide bus format, 
assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
- "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
-   bus_format = MEDIA_BUS_FMT_RGB888_1X24;
-   }
-   }
+   bridge_state = drm_atomic_get_new_bridge_state(state, lcdif->bridge);
+   if (!bridge_state)
+   bus_format = MEDIA_BUS_FMT_FIXED;
+   else
+   bus_format = bridge_state->input_bus_cfg.format;
 
-   /* If all else fails, default to RGB888_1X24 */
-   if (!bus_format)
+   if (bus_format == MEDIA_BUS_FMT_FIXED) {
+   dev_warn_once(drm->dev,
+ "Bridge does not provide bus format, assuming 
MEDIA_BUS_FMT_RGB888_1X24.\n"
+ "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   } else if (!bus_format) {
+   /* If all else fails, default to RGB888_1X24 */
+   bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   }
 
clk_set_rate(lcdif->clk, m->crtc_clock * 1000);
 
-- 
2.37.1



[PATCH v6 1/6] dt-bindings: lcdif: Add i.MX93 LCDIF support

2023-05-10 Thread Liu Ying
There is one LCDIF embedded in i.MX93 SoC to connect with
MIPI DSI controller through LCDIF cross line pattern(controlled
by mediamix blk-ctrl) or connect with LVDS display bridge(LDB)
directly or connect with a parallel display through parallel
display format(also controlled by mediamix blk-ctrl).  i.MX93
LCDIF IP is essentially the same to i.MX8MP LCDIF IP.  Add device
tree binding for i.MX93 LCDIF.

Acked-by: Krzysztof Kozlowski 
Reviewed-by: Marek Vasut 
Reviewed-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v5->v6:
* No change.

v4->v5:
* No change.

v3->v4:
* Add Alexander's R-b tag.

v2->v3:
* No change.

v1->v2:
* Add Krzysztof's A-b and Marek's R-b tags.

 Documentation/devicetree/bindings/display/fsl,lcdif.yaml | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml 
b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
index 75b4efd70ba8..fc11ab5fc465 100644
--- a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
+++ b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
@@ -21,6 +21,7 @@ properties:
   - fsl,imx28-lcdif
   - fsl,imx6sx-lcdif
   - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
   - items:
   - enum:
   - fsl,imx6sl-lcdif
@@ -88,7 +89,9 @@ allOf:
   properties:
 compatible:
   contains:
-const: fsl,imx8mp-lcdif
+enum:
+  - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
 then:
   properties:
 clocks:
@@ -107,6 +110,7 @@ allOf:
   enum:
 - fsl,imx6sx-lcdif
 - fsl,imx8mp-lcdif
+- fsl,imx93-lcdif
 then:
   properties:
 clocks:
@@ -123,6 +127,7 @@ allOf:
   - fsl,imx8mm-lcdif
   - fsl,imx8mn-lcdif
   - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
 then:
   required:
 - power-domains
-- 
2.37.1



[PATCH v6 0/6] drm: lcdif: Add i.MX93 LCDIF support

2023-05-10 Thread Liu Ying
Hi,

This patch set aims to add i.MX93 LCDIF display controller support
in the existing LCDIF DRM driver.  The LCDIF embedded in i.MX93 SoC
is essentially the same to those embedded in i.MX8mp SoC.  Through
internal bridges, i.MX93 LCDIF may drive a MIPI DSI display or a LVDS
display or a parallel display.

Patch 1/6 adds device tree binding support for i.MX93 LCDIF in the
existing fsl,lcdif.yaml.

Patch 2/6 drops lcdif->bridge NULL pointer check as a cleanup patch.

Patch 3/6~5/6 prepare for adding i.MX93 LCDIF support step by step.

Patch 6/6 adds i.MX93 LCDIF compatible string as the last step of
adding i.MX93 LCDIF support.

v5->v6:
* Collect Marek's R-b tags on patch 3/6, 4/6 and 6/6.
* Keep default MEDIA_BUS_FMT_RGB888_1X24 bus format in patch 2/6 in case
  bridge_state->input_bus_cfg.format is zero. (Marek)
* Drop MAX_DISPLAYS macro in patch 5/6. (Marek)
* Drop the encoder member in struct lcdif_drm_private in patch 5/6.
* Drop endpoint id check in patch 5/6.
* Allocate encoders by calling devm_kzalloc() in patch 5/6.

v4->v5:
* Rebase this patch set upon v6.4-rc1 and resolve a trivial conflict for
  patch 5/6.
* Collect Alexander's R-b tag on patch 3/6, A-b tags on patch 4/6 and 5/6,
  T-b tags on patch 2/6~6/6.

v3->v4:
* Improve warning message when ignoring invalid LCDIF OF endpoint ids in
  patch 5/6. (Alexander)
* Use 'new_{c,p}state' instead of 'new_{crtc,plane}_state' in patch 3/6.
  (Alexander)
* Simplify lcdif_crtc_reset() by calling lcdif_crtc_atomic_destroy_state()
  in patch 3/6. (Alexander)
* Add '!crtc->state' check in lcdif_crtc_atomic_duplicate_state() in patch 3/6.
  (Alexander)
* Collect Alexander's R-b tags on patch 1/6, 2/6 and 6/6.

v2->v3:
* Fix a trivial typo in patch 6/6's commit message.

v1->v2:
* Add Krzysztof's A-b and Marek's R-b tags on patch 1/6.
* Split patch 2/2 in v1 into patch 2/6~6/6 in v2. (Marek, Alexander)
* Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
* Add comment on the 'base' member of lcdif_crtc_state structure to
  note it should always be the first member. (Lothar)
* Drop unneeded 'bridges' member from lcdif_drm_private structure.
* Drop a comment about bridge input bus format from lcdif_crtc_atomic_check().


Liu Ying (6):
  dt-bindings: lcdif: Add i.MX93 LCDIF support
  drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge
  drm: lcdif: Determine bus format and flags in ->atomic_check()
  drm: lcdif: Check consistent bus format and flags across first bridges
  drm: lcdif: Add multiple encoders and first bridges support
  drm: lcdif: Add i.MX93 LCDIF compatible string

 .../bindings/display/fsl,lcdif.yaml   |   7 +-
 drivers/gpu/drm/mxsfb/lcdif_drv.c |  73 ++-
 drivers/gpu/drm/mxsfb/lcdif_drv.h |   3 -
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 201 --
 4 files changed, 208 insertions(+), 76 deletions(-)

-- 
2.37.1



[PATCH v2 2/2] drm/panel: panel-simple: Add BOE EV121WXM-N10-1850 panel support

2023-05-08 Thread Liu Ying
Add BOE EV121WXM-N10-1850 12.1" WXGA (1280x800) TFT LCD panel support.
The panel has a LVDS display interface.

The panel's product specification can be found at:
http://www.onetech.com.tw/files/EV121WXM-N10-1850ProductSpecification_20180801.pdf

Signed-off-by: Liu Ying 
---
v1->v2:
* Use struct display_timing to tell minimum and maximum pixel clock rates.
* Set bus_flags to DRM_BUS_FLAG_DE_HIGH in struct panel_desc.

 drivers/gpu/drm/panel/panel-simple.c | 34 
 1 file changed, 34 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 065f378bba9d..b1590a7e2cda 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1211,6 +1211,37 @@ static const struct panel_desc bananapi_s070wv20_ct16 = {
},
 };
 
+static const struct display_timing boe_ev121wxm_n10_1850_timing = {
+   .pixelclock = { 69922000, 7100, 72293000 },
+   .hactive = { 1280, 1280, 1280 },
+   .hfront_porch = { 48, 48, 48 },
+   .hback_porch = { 80, 80, 80 },
+   .hsync_len = { 32, 32, 32 },
+   .vactive = { 800, 800, 800 },
+   .vfront_porch = { 3, 3, 3 },
+   .vback_porch = { 14, 14, 14 },
+   .vsync_len = { 6, 6, 6 },
+};
+
+static const struct panel_desc boe_ev121wxm_n10_1850 = {
+   .timings = _ev121wxm_n10_1850_timing,
+   .num_timings = 1,
+   .bpc = 8,
+   .size = {
+   .width = 261,
+   .height = 163,
+   },
+   .delay = {
+   .prepare = 9,
+   .enable = 300,
+   .unprepare = 300,
+   .disable = 560,
+   },
+   .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+   .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+   .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct drm_display_mode boe_hv070wsa_mode = {
.clock = 42105,
.hdisplay = 1024,
@@ -3984,6 +4015,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "bananapi,s070wv20-ct16",
.data = _s070wv20_ct16,
+   }, {
+   .compatible = "boe,ev121wxm-n10-1850",
+   .data = _ev121wxm_n10_1850,
}, {
.compatible = "boe,hv070wsa-100",
.data = _hv070wsa
-- 
2.37.1



[PATCH v2 0/2] drm/panel: panel-simple: Add BOE EV121WXM-N10-1850 panel support

2023-05-08 Thread Liu Ying
Hi,

This patch series aims to add BOE EV121WXM-N10-1850 panel support
in the DRM simple panel driver.

Patch 1/2 adds dt-bindings support for the panel.
Patch 2/2 adds the panel support in the DRM simple panel driver.

v1->v2:
* Add Krzysztof's A-b tag on patch 1/2.
* Use struct display_timing in patch 2/2 to tell minimum and maximum
  pixel clock rates.
* Set bus_flags to DRM_BUS_FLAG_DE_HIGH in struct panel_desc in patch 2/2.

Liu Ying (2):
  dt-bindings: display: simple: Add BOE EV121WXM-N10-1850 panel
  drm/panel: panel-simple: Add BOE EV121WXM-N10-1850 panel support

 .../bindings/display/panel/panel-simple.yaml  |  2 ++
 drivers/gpu/drm/panel/panel-simple.c  | 34 +++
 2 files changed, 36 insertions(+)

-- 
2.37.1



[PATCH v2 1/2] dt-bindings: display: simple: Add BOE EV121WXM-N10-1850 panel

2023-05-08 Thread Liu Ying
Add BOE EV121WXM-N10-1850 12.1" WXGA (1280x800) TFT LCD panel
compatible string.  The panel has a LVDS display interface.

The panel's product specification can be found at:
http://www.onetech.com.tw/files/EV121WXM-N10-1850ProductSpecification_20180801.pdf

Acked-by: Krzysztof Kozlowski 
Signed-off-by: Liu Ying 
---
v1->v2:
* Add Krzysztof's A-b tag.

 .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
index 01560fe226dd..b9dbc5bb065d 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
@@ -77,6 +77,8 @@ properties:
   - auo,t215hvn01
 # Shanghai AVIC Optoelectronics 7" 1024x600 color TFT-LCD panel
   - avic,tm070ddh03
+# BOE EV121WXM-N10-1850 12.1" WXGA (1280x800) TFT LCD panel
+  - boe,ev121wxm-n10-1850
 # BOE HV070WSA-100 7.01" WSVGA TFT LCD panel
   - boe,hv070wsa-100
 # BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel
-- 
2.37.1



[PATCH v5 6/6] drm: lcdif: Add i.MX93 LCDIF compatible string

2023-05-07 Thread Liu Ying
With all previous preparations done to make it possible for the
single LCDIF embedded in i.MX93 SoC to drive multiple displays
simultaneously, add i.MX93 LCDIF compatible string as the last
step of adding i.MX93 LCDIF support.

Tested-by: Alexander Stein 
Reviewed-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v4->v5:
* Add Alexander's T-b tag.

v3->v4:
* Add Alexander's R-b tag.

v2->v3:
* Fix a trivial typo in commit message.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)

 drivers/gpu/drm/mxsfb/lcdif_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index cf27b63b1899..d1bd0f51f451 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -249,6 +249,7 @@ static const struct drm_driver lcdif_driver = {
 
 static const struct of_device_id lcdif_dt_ids[] = {
{ .compatible = "fsl,imx8mp-lcdif" },
+   { .compatible = "fsl,imx93-lcdif" },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, lcdif_dt_ids);
-- 
2.37.1



[PATCH v5 5/6] drm: lcdif: Add multiple encoders and first bridges support

2023-05-07 Thread Liu Ying
The single LCDIF embedded in i.MX93 SoC may drive multiple displays
simultaneously.  Look at LCDIF output port's remote port parents to
find all enabled first bridges.  Add an encoder for each found bridge
and attach the bridge to the encoder.  This is a preparation for
adding i.MX93 LCDIF support.

Tested-by: Alexander Stein 
Acked-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v4->v5:
* Rebase upon v6.4-rc1 and resolve a trivial conflict.
* Add Alexander's A-b and T-b tags.

v3->v4:
* Improve warning message when ignoring invalid LCDIF OF endpoint ids.
  (Alexander)

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
* Drop unneeded 'bridges' member from lcdif_drm_private structure.

 drivers/gpu/drm/mxsfb/lcdif_drv.c | 68 +++
 drivers/gpu/drm/mxsfb/lcdif_drv.h |  4 +-
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 21 ++
 3 files changed, 66 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index e816f87828fb..cf27b63b1899 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -9,13 +9,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -38,19 +41,68 @@ static const struct drm_mode_config_helper_funcs 
lcdif_mode_config_helpers = {
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 };
 
+static const struct drm_encoder_funcs lcdif_encoder_funcs = {
+   .destroy = drm_encoder_cleanup,
+};
+
 static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif)
 {
-   struct drm_device *drm = lcdif->drm;
+   struct device *dev = lcdif->drm->dev;
+   struct device_node *ep;
struct drm_bridge *bridge;
int ret;
 
-   bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0, 0);
-   if (IS_ERR(bridge))
-   return PTR_ERR(bridge);
-
-   ret = drm_bridge_attach(>encoder, bridge, NULL, 0);
-   if (ret)
-   return dev_err_probe(drm->dev, ret, "Failed to attach 
bridge\n");
+   for_each_endpoint_of_node(dev->of_node, ep) {
+   struct device_node *remote;
+   struct of_endpoint of_ep;
+   struct drm_encoder *encoder;
+
+   remote = of_graph_get_remote_port_parent(ep);
+   if (!of_device_is_available(remote)) {
+   of_node_put(remote);
+   continue;
+   }
+   of_node_put(remote);
+
+   ret = of_graph_parse_endpoint(ep, _ep);
+   if (ret < 0) {
+   dev_err(dev, "Failed to parse endpoint %pOF\n", ep);
+   of_node_put(ep);
+   return ret;
+   }
+
+   if (of_ep.id >= MAX_DISPLAYS) {
+   dev_warn(dev, "ingoring invalid endpoint id %u\n", 
of_ep.id);
+   continue;
+   }
+
+   bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, of_ep.id);
+   if (IS_ERR(bridge)) {
+   of_node_put(ep);
+   return dev_err_probe(dev, PTR_ERR(bridge),
+"Failed to get bridge for 
endpoint%u\n",
+of_ep.id);
+   }
+
+   encoder = >encoders[of_ep.id];
+   encoder->possible_crtcs = drm_crtc_mask(>crtc);
+   ret = drm_encoder_init(lcdif->drm, encoder, 
_encoder_funcs,
+  DRM_MODE_ENCODER_NONE, NULL);
+   if (ret) {
+   dev_err(dev, "Failed to initialize encoder for 
endpoint%u: %d\n",
+   of_ep.id, ret);
+   of_node_put(ep);
+   return ret;
+   }
+
+   ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+   if (ret) {
+   of_node_put(ep);
+   return dev_err_probe(dev, ret,
+"Failed to attach bridge for 
endpoint%u\n",
+of_ep.id);
+   }
+   }
 
return 0;
 }
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h 
b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index aa6d099a1897..c7400bd9bbd9 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
@@ -14,6 +14,8 @@
 #include 
 #include 
 
+#define MAX_DISPLAYS   3
+
 struct clk;
 
 struct lcdif_drm_private {
@@ -30,7 +32,7 @@ struct lcdif_drm_private {
/* i.MXRT does support overlay planes, add them here. */
} planes;
 

[PATCH v5 4/6] drm: lcdif: Check consistent bus format and flags across first bridges

2023-05-07 Thread Liu Ying
The single LCDIF embedded in i.MX93 SoC may drive multiple displays
simultaneously.  Check bus format and flags across first bridges in
->atomic_check() to ensure they are consistent.  This is a preparation
for adding i.MX93 LCDIF support.

Acked-by: Alexander Stein 
Tested-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v4->v5:
* Add Alexander's A-b and T-b tags.

v3->v4:
* No change.

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Drop a comment about bridge input bus format from lcdif_crtc_atomic_check().

 drivers/gpu/drm/mxsfb/lcdif_drv.c |  2 -
 drivers/gpu/drm/mxsfb/lcdif_drv.h |  1 -
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 76 ++-
 3 files changed, 55 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index 6fb5b469ee5a..e816f87828fb 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -52,8 +52,6 @@ static int lcdif_attach_bridge(struct lcdif_drm_private 
*lcdif)
if (ret)
return dev_err_probe(drm->dev, ret, "Failed to attach 
bridge\n");
 
-   lcdif->bridge = bridge;
-
return 0;
 }
 
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h 
b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index 6cdba6e20c02..aa6d099a1897 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
@@ -31,7 +31,6 @@ struct lcdif_drm_private {
} planes;
struct drm_crtc crtc;
struct drm_encoder  encoder;
-   struct drm_bridge   *bridge;
 };
 
 static inline struct lcdif_drm_private *
diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index d46de433cd8e..d6009b353a16 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -424,15 +425,19 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
   struct drm_atomic_state *state)
 {
struct drm_device *drm = crtc->dev;
-   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
  crtc);
struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
bool has_primary = crtc_state->plane_mask &
   drm_plane_mask(crtc->primary);
+   struct drm_connector_state *connector_state;
+   struct drm_connector *connector;
+   struct drm_encoder *encoder;
struct drm_bridge_state *bridge_state;
-   struct drm_bridge *bridge = lcdif->bridge;
-   int ret;
+   struct drm_bridge *bridge;
+   u32 bus_format, bus_flags;
+   bool format_set = false, flags_set = false;
+   int ret, i;
 
/* The primary plane has to be enabled when the CRTC is active. */
if (crtc_state->active && !has_primary)
@@ -442,26 +447,55 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
if (ret)
return ret;
 
-   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
-   if (!bridge_state)
-   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_FIXED;
-   else
-   lcdif_crtc_state->bus_format = 
bridge_state->input_bus_cfg.format;
-
-   if (lcdif_crtc_state->bus_format == MEDIA_BUS_FMT_FIXED) {
-   dev_warn_once(drm->dev,
- "Bridge does not provide bus format, assuming 
MEDIA_BUS_FMT_RGB888_1X24.\n"
- "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
-   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   /* Try to find consistent bus format and flags across first bridges. */
+   for_each_new_connector_in_state(state, connector, connector_state, i) {
+   if (!connector_state->crtc)
+   continue;
+
+   encoder = connector_state->best_encoder;
+
+   bridge = drm_bridge_chain_get_first_bridge(encoder);
+   if (!bridge)
+   continue;
+
+   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+   if (!bridge_state)
+   bus_format = MEDIA_BUS_FMT_FIXED;
+   else
+   bus_format = bridge_state->input_bus_cfg.format;
+
+   if (bus_format == MEDIA_BUS_FMT_FIXED) {
+   dev_warn(drm->dev,
+"[ENCODER:%d:%s]'s bridge does not provide bus 
format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
+"Please fix

[PATCH v5 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()

2023-05-07 Thread Liu Ying
Instead of determining LCDIF output bus format and bus flags in
->atomic_enable(), do that in ->atomic_check().  This is a
preparation for the upcoming patch to check consistent bus format
and bus flags across all first downstream bridges in ->atomic_check().
New lcdif_crtc_state structure is introduced to cache bus format
and bus flags states in ->atomic_check() so that they can be read
in ->atomic_enable().

Tested-by: Alexander Stein 
Reviewed-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v4->v5:
* Add Alexander's R-b and T-b tags.

v3->v4:
* Use 'new_{c,p}state' instead of 'new_{crtc,plane}_state'. (Alexander)
* Simplify lcdif_crtc_reset() by calling lcdif_crtc_atomic_destroy_state().
  (Alexander)
* Add '!crtc->state' check in lcdif_crtc_atomic_duplicate_state(). (Alexander)

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Add comment on the 'base' member of lcdif_crtc_state structure to
  note it should always be the first member. (Lothar)

 drivers/gpu/drm/mxsfb/lcdif_kms.c | 134 ++
 1 file changed, 99 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index e54200a9fcb9..d46de433cd8e 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -30,6 +30,18 @@
 #include "lcdif_drv.h"
 #include "lcdif_regs.h"
 
+struct lcdif_crtc_state {
+   struct drm_crtc_state   base;   /* always be the first member */
+   u32 bus_format;
+   u32 bus_flags;
+};
+
+static inline struct lcdif_crtc_state *
+to_lcdif_crtc_state(struct drm_crtc_state *s)
+{
+   return container_of(s, struct lcdif_crtc_state, base);
+}
+
 /* 
-
  * CRTC
  */
@@ -385,48 +397,72 @@ static void lcdif_reset_block(struct lcdif_drm_private 
*lcdif)
readl(lcdif->base + LCDC_V8_CTRL);
 }
 
-static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
-struct drm_plane_state *plane_state,
-struct drm_bridge_state *bridge_state,
-const u32 bus_format)
+static void lcdif_crtc_mode_set_nofb(struct drm_crtc_state *crtc_state,
+struct drm_plane_state *plane_state)
 {
-   struct drm_device *drm = lcdif->crtc.dev;
-   struct drm_display_mode *m = >crtc.state->adjusted_mode;
-   u32 bus_flags = 0;
-
-   if (lcdif->bridge->timings)
-   bus_flags = lcdif->bridge->timings->input_bus_flags;
-   else if (bridge_state)
-   bus_flags = bridge_state->input_bus_cfg.flags;
+   struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
+   struct drm_device *drm = crtc_state->crtc->dev;
+   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
+   struct drm_display_mode *m = _state->adjusted_mode;
 
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
 m->crtc_clock,
 (int)(clk_get_rate(lcdif->clk) / 1000));
DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
-bus_flags);
+lcdif_crtc_state->bus_flags);
DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
 
/* Mandatory eLCDIF reset as per the Reference Manual */
lcdif_reset_block(lcdif);
 
-   lcdif_set_formats(lcdif, plane_state, bus_format);
+   lcdif_set_formats(lcdif, plane_state, lcdif_crtc_state->bus_format);
 
-   lcdif_set_mode(lcdif, bus_flags);
+   lcdif_set_mode(lcdif, lcdif_crtc_state->bus_flags);
 }
 
 static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
   struct drm_atomic_state *state)
 {
+   struct drm_device *drm = crtc->dev;
+   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
  crtc);
+   struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
bool has_primary = crtc_state->plane_mask &
   drm_plane_mask(crtc->primary);
+   struct drm_bridge_state *bridge_state;
+   struct drm_bridge *bridge = lcdif->bridge;
+   int ret;
 
/* The primary plane has to be enabled when the CRTC is active. */
if (crtc_state->active && !has_primary)
return -EINVAL;
 
-   return drm_atomic_add_affected_planes(state, crtc);
+   ret = drm_atomic_add_affected_planes(state, crtc);
+   if (ret)

[PATCH v5 2/6] drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge

2023-05-07 Thread Liu Ying
A valid bridge is already found in lcdif_attach_bridge() and set
to lcdif->bridge, so lcdif->bridge cannot be a NULL pointer. Drop
the unnecessary NULL pointer check in KMS stage.

Tested-by: Alexander Stein 
Reviewed-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v4->v5:
* Add Alexander's T-b tag.

v3->v4:
* Add Alexander's R-b tag.

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)

 drivers/gpu/drm/mxsfb/lcdif_kms.c | 33 +++
 1 file changed, 12 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index 262bc43b1079..e54200a9fcb9 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -394,7 +394,7 @@ static void lcdif_crtc_mode_set_nofb(struct 
lcdif_drm_private *lcdif,
struct drm_display_mode *m = >crtc.state->adjusted_mode;
u32 bus_flags = 0;
 
-   if (lcdif->bridge && lcdif->bridge->timings)
+   if (lcdif->bridge->timings)
bus_flags = lcdif->bridge->timings->input_bus_flags;
else if (bridge_state)
bus_flags = bridge_state->input_bus_cfg.flags;
@@ -463,30 +463,21 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc 
*crtc,
struct drm_display_mode *m = >crtc.state->adjusted_mode;
struct drm_bridge_state *bridge_state = NULL;
struct drm_device *drm = lcdif->drm;
-   u32 bus_format = 0;
+   u32 bus_format;
dma_addr_t paddr;
 
-   /* If there is a bridge attached to the LCDIF, use its bus format */
-   if (lcdif->bridge) {
-   bridge_state =
-   drm_atomic_get_new_bridge_state(state,
-   lcdif->bridge);
-   if (!bridge_state)
-   bus_format = MEDIA_BUS_FMT_FIXED;
-   else
-   bus_format = bridge_state->input_bus_cfg.format;
-
-   if (bus_format == MEDIA_BUS_FMT_FIXED) {
-   dev_warn_once(drm->dev,
- "Bridge does not provide bus format, 
assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
- "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
-   bus_format = MEDIA_BUS_FMT_RGB888_1X24;
-   }
-   }
+   bridge_state = drm_atomic_get_new_bridge_state(state, lcdif->bridge);
+   if (!bridge_state)
+   bus_format = MEDIA_BUS_FMT_FIXED;
+   else
+   bus_format = bridge_state->input_bus_cfg.format;
 
-   /* If all else fails, default to RGB888_1X24 */
-   if (!bus_format)
+   if (bus_format == MEDIA_BUS_FMT_FIXED) {
+   dev_warn_once(drm->dev,
+ "Bridge does not provide bus format, assuming 
MEDIA_BUS_FMT_RGB888_1X24.\n"
+ "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   }
 
clk_set_rate(lcdif->clk, m->crtc_clock * 1000);
 
-- 
2.37.1



[PATCH v5 1/6] dt-bindings: lcdif: Add i.MX93 LCDIF support

2023-05-07 Thread Liu Ying
There is one LCDIF embedded in i.MX93 SoC to connect with
MIPI DSI controller through LCDIF cross line pattern(controlled
by mediamix blk-ctrl) or connect with LVDS display bridge(LDB)
directly or connect with a parallel display through parallel
display format(also controlled by mediamix blk-ctrl).  i.MX93
LCDIF IP is essentially the same to i.MX8MP LCDIF IP.  Add device
tree binding for i.MX93 LCDIF.

Acked-by: Krzysztof Kozlowski 
Reviewed-by: Marek Vasut 
Reviewed-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v4->v5:
* No change.

v3->v4:
* Add Alexander's R-b tag.

v2->v3:
* No change.

v1->v2:
* Add Krzysztof's A-b and Marek's R-b tags.

 Documentation/devicetree/bindings/display/fsl,lcdif.yaml | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml 
b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
index 75b4efd70ba8..fc11ab5fc465 100644
--- a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
+++ b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
@@ -21,6 +21,7 @@ properties:
   - fsl,imx28-lcdif
   - fsl,imx6sx-lcdif
   - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
   - items:
   - enum:
   - fsl,imx6sl-lcdif
@@ -88,7 +89,9 @@ allOf:
   properties:
 compatible:
   contains:
-const: fsl,imx8mp-lcdif
+enum:
+  - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
 then:
   properties:
 clocks:
@@ -107,6 +110,7 @@ allOf:
   enum:
 - fsl,imx6sx-lcdif
 - fsl,imx8mp-lcdif
+- fsl,imx93-lcdif
 then:
   properties:
 clocks:
@@ -123,6 +127,7 @@ allOf:
   - fsl,imx8mm-lcdif
   - fsl,imx8mn-lcdif
   - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
 then:
   required:
 - power-domains
-- 
2.37.1



[PATCH v5 0/6] drm: lcdif: Add i.MX93 LCDIF support

2023-05-07 Thread Liu Ying
Hi,

This patch set aims to add i.MX93 LCDIF display controller support
in the existing LCDIF DRM driver.  The LCDIF embedded in i.MX93 SoC
is essentially the same to those embedded in i.MX8mp SoC.  Through
internal bridges, i.MX93 LCDIF may drive a MIPI DSI display or a LVDS
display or a parallel display.

Patch 1/6 adds device tree binding support for i.MX93 LCDIF in the
existing fsl,lcdif.yaml.

Patch 2/6 drops lcdif->bridge NULL pointer check as a cleanup patch.

Patch 3/6~5/6 prepare for adding i.MX93 LCDIF support step by step.

Patch 6/6 adds i.MX93 LCDIF compatible string as the last step of
adding i.MX93 LCDIF support.

v4->v5:
* Rebase this patch set upon v6.4-rc1 and resolve a trivial conflict for
  patch 5/6.
* Collect Alexander's R-b tag on patch 3/6, A-b tags on patch 4/6 and 5/6,
  T-b tags on patch 2/6~6/6.

v3->v4:
* Improve warning message when ignoring invalid LCDIF OF endpoint ids in
  patch 5/6. (Alexander)
* Use 'new_{c,p}state' instead of 'new_{crtc,plane}_state' in patch 3/6.
  (Alexander)
* Simplify lcdif_crtc_reset() by calling lcdif_crtc_atomic_destroy_state()
  in patch 3/6. (Alexander)
* Add '!crtc->state' check in lcdif_crtc_atomic_duplicate_state() in patch 3/6.
  (Alexander)
* Collect Alexander's R-b tags on patch 1/6, 2/6 and 6/6.

v2->v3:
* Fix a trivial typo in patch 6/6's commit message.

v1->v2:
* Add Krzysztof's A-b and Marek's R-b tags on patch 1/6.
* Split patch 2/2 in v1 into patch 2/6~6/6 in v2. (Marek, Alexander)
* Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
* Add comment on the 'base' member of lcdif_crtc_state structure to
  note it should always be the first member. (Lothar)
* Drop unneeded 'bridges' member from lcdif_drm_private structure.
* Drop a comment about bridge input bus format from lcdif_crtc_atomic_check().

Liu Ying (6):
  dt-bindings: lcdif: Add i.MX93 LCDIF support
  drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge
  drm: lcdif: Determine bus format and flags in ->atomic_check()
  drm: lcdif: Check consistent bus format and flags across first bridges
  drm: lcdif: Add multiple encoders and first bridges support
  drm: lcdif: Add i.MX93 LCDIF compatible string

 .../bindings/display/fsl,lcdif.yaml   |   7 +-
 drivers/gpu/drm/mxsfb/lcdif_drv.c |  71 ++-
 drivers/gpu/drm/mxsfb/lcdif_drv.h |   5 +-
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 198 --
 4 files changed, 206 insertions(+), 75 deletions(-)

-- 
2.37.1



Re: [PATCH 37/37] drm/bridge/imx/Kconfig: Prevent imx-ldb-helper from appearing in 2 separate modules

2023-03-17 Thread Liu Ying
Hi Lee,

On Fri, 2023-03-17 at 08:17 +, Lee Jones wrote:
> Fixes the following W=1 kernel build warning(s):
> 
>  scripts/Makefile.build:252: drivers/gpu/drm/bridge/imx/Makefile: 
> imx-ldb-helper.o is added to multiple modules: imx8qm-ldb imx8qxp-ldb
> 
> Cc: Liu Ying 
> Cc: Andrzej Hajda 
> Cc: Neil Armstrong 
> Cc: Robert Foss 
> Cc: Laurent Pinchart 
> Cc: Jonas Karlman 
> Cc: Jernej Skrabec 
> Cc: David Airlie 
> Cc: Daniel Vetter 
> Cc: Shawn Guo 
> Cc: Sascha Hauer 
> Cc: Pengutronix Kernel Team 
> Cc: Fabio Estevam 
> Cc: NXP Linux Team 
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-arm-ker...@lists.infradead.org
> Signed-off-by: Lee Jones 

Thank you for the patch.

> ---
>  drivers/gpu/drm/bridge/imx/Kconfig  |  7 +++
>  drivers/gpu/drm/bridge/imx/Makefile |  7 +--
>  drivers/gpu/drm/bridge/imx/imx-ldb-helper.c | 13 +
>  3 files changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/imx/Kconfig 
> b/drivers/gpu/drm/bridge/imx/Kconfig
> index 608f47f41bcd1..97018dcd078d0 100644
> --- a/drivers/gpu/drm/bridge/imx/Kconfig
> +++ b/drivers/gpu/drm/bridge/imx/Kconfig
> @@ -1,10 +1,16 @@
>  if ARCH_MXC || COMPILE_TEST
>  
> +config DRM_IMX8_LIB

I would limit this to i.MX LVDS Display Bridge(LDB) library, so I
suggest to use DRM_IMX_LDB_LIB.

> + tristate
> + help
> +   Common helper functions used by some of the drivers below.

Considering to use DRM_IMX_LDB_LIB, help message can be a bit more
specific to LDB drivers, like:

Common helper functions used by i.MX LVDS display bridge drivers below.

Regards,
Liu Ying



[PATCH v2] drm/bridge: Fix returned array size name for atomic_get_input_bus_fmts kdoc

2023-03-13 Thread Liu Ying
The returned array size for input formats is set through
atomic_get_input_bus_fmts()'s 'num_input_fmts' argument, so use
'num_input_fmts' to represent the array size in the function's kdoc,
not 'num_output_fmts'.

Fixes: 91ea83306bfa ("drm/bridge: Fix the bridge kernel doc")
Fixes: f32df58acc68 ("drm/bridge: Add the necessary bits to support bus format 
negotiation")
Signed-off-by: Liu Ying 
---
v1->v2:
* Correct Fixes tag format.
* Copy DRM bridge driver maintainers.
* Copy Boris.

 include/drm/drm_bridge.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 42f86327b40a..bf964cdfb330 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -423,11 +423,11 @@ struct drm_bridge_funcs {
 *
 * The returned array must be allocated with kmalloc() and will be
 * freed by the caller. If the allocation fails, NULL should be
-* returned. num_output_fmts must be set to the returned array size.
+* returned. num_input_fmts must be set to the returned array size.
 * Formats listed in the returned array should be listed in decreasing
 * preference order (the core will try all formats until it finds one
 * that works). When the format is not supported NULL should be
-* returned and num_output_fmts should be set to 0.
+* returned and num_input_fmts should be set to 0.
 *
 * This method is called on all elements of the bridge chain as part of
 * the bus format negotiation process that happens in
-- 
2.37.1



[PATCH] MAINTAINERS: Add include/drm/drm_bridge.h to DRM DRIVERS FOR BRIDGE CHIPS

2023-03-12 Thread Liu Ying
Appropriate maintainers should be suggested for changes to the
include/drm/drm_bridge.h header file, so add the header file to the
'DRM DRIVERS FOR BRIDGE CHIPS' section.

Signed-off-by: Liu Ying 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3d409875740d..b6e7ac70b8a8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6824,6 +6824,7 @@ S:Maintained
 T: git git://anongit.freedesktop.org/drm/drm-misc
 F: Documentation/devicetree/bindings/display/bridge/
 F: drivers/gpu/drm/bridge/
+F: include/drm/drm_bridge.h
 
 DRM DRIVERS FOR EXYNOS
 M: Inki Dae 
-- 
2.37.1



Re: [PATCH] drm: Use of_property_present() for testing DT property presence

2023-03-12 Thread Liu Ying
On Fri, 2023-03-10 at 08:47 -0600, Rob Herring wrote:
> It is preferred to use typed property access functions (i.e.
> of_property_read_ functions) rather than low-level
> of_get_property/of_find_property functions for reading properties. As
> part of this, convert of_get_property/of_find_property calls to the
> recently added of_property_present() helper when we just want to test
> for presence of a property and nothing more.
> 
> Signed-off-by: Rob Herring 
> ---
>  drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c | 2 +-

Reviewed-by: Liu Ying  # i.MX bridge

>  drivers/gpu/drm/drm_mipi_dsi.c  | 2 +-
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +-
>  drivers/gpu/drm/sun4i/sun4i_backend.c   | 2 +-
>  drivers/gpu/drm/sun4i/sun8i_mixer.c | 2 +-
>  drivers/gpu/drm/vc4/vc4_hdmi.c  | 2 +-
>  6 files changed, 6 insertions(+), 6 deletions(-)



[PATCH] drm/bridge: Fix returned array size name for atomic_get_input_bus_fmts kdoc

2023-03-09 Thread Liu Ying
The returned array size for input formats is set through
atomic_get_input_bus_fmts()'s 'num_input_fmts' argument, so use
'num_input_fmts' to represent the array size in the function's kdoc,
not 'num_output_fmts'.

Fixes: ("91ea83306bfa drm/bridge: Fix the bridge kernel doc")
Fixes: ("f32df58acc68 drm/bridge: Add the necessary bits to support bus format 
negotiation")
Signed-off-by: Liu Ying 
---
 include/drm/drm_bridge.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 6b65b0dfb4fb..288c6feda5de 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -447,11 +447,11 @@ struct drm_bridge_funcs {
 *
 * The returned array must be allocated with kmalloc() and will be
 * freed by the caller. If the allocation fails, NULL should be
-* returned. num_output_fmts must be set to the returned array size.
+* returned. num_input_fmts must be set to the returned array size.
 * Formats listed in the returned array should be listed in decreasing
 * preference order (the core will try all formats until it finds one
 * that works). When the format is not supported NULL should be
-* returned and num_output_fmts should be set to 0.
+* returned and num_input_fmts should be set to 0.
 *
 * This method is called on all elements of the bridge chain as part of
 * the bus format negotiation process that happens in
-- 
2.37.1



Re: [PATCH v4 0/6] drm: lcdif: Add i.MX93 LCDIF support

2023-02-20 Thread Liu Ying
On Mon, 2023-02-20 at 11:16 +0100, Alexander Stein wrote:
> Hi Liu,

Hi Alexander,

> 
> Am Montag, 20. Februar 2023, 09:55:19 CET schrieb Alexander Stein:
> > Hi Liu,
> > 
> > Am Freitag, 17. Februar 2023, 09:59:14 CET schrieb Liu Ying:
> > > On Fri, 2023-02-17 at 09:18 +0100, Alexander Stein wrote:
> > > > Hi Liu,
> > > 
> > > Hi Alexander,
> > > 
> > > > Am Freitag, 17. Februar 2023, 07:54:01 CET schrieb Liu Ying:
> > > > > Hi,
> > > > > 
> > > > > This patch set aims to add i.MX93 LCDIF display controller
> > > > > support
> > > > > in the existing LCDIF DRM driver.  The LCDIF embedded in
> > > > > i.MX93 SoC
> > > > > is essentially the same to those embedded in i.MX8mp
> > > > > SoC.  Through
> > > > > internal bridges, i.MX93 LCDIF may drive a MIPI DSI display
> > > > > or a LVDS
> > > > > display or a parallel display.
> > > > > 
> > > > > Patch 1/6 adds device tree binding support for i.MX93 LCDIF
> > > > > in the
> > > > > existing fsl,lcdif.yaml.
> > > > > 
> > > > > Patch 2/6 drops lcdif->bridge NULL pointer check as a cleanup
> > > > > patch.
> > > > > 
> > > > > Patch 3/6~5/6 prepare for adding i.MX93 LCDIF support step by
> > > > > step.
> > > > > 
> > > > > Patch 6/6 adds i.MX93 LCDIF compatible string as the last
> > > > > step of
> > > > > adding i.MX93 LCDIF support.
> > > > 
> > > > Thanks for the series. I could test this on my
> > > > TQMa93xxLA/MBa93xxCA with
> > > > a
> > > > single LVDS display attached, so no DSI or parallel display.
> > > > Hence I
> > > > could
> > > > not test the bus format and flags checks, but they look okay.
> > > > So you can add
> > > > Tested-by: Alexander Stein 
> > > > to the whole series as well.
> > > 
> > > Thanks for your test.
> > > 
> > > > One thing I noticed is that, sometimes it seems that before
> > > > probing
> > > > lcdif
> > > > my system completely freezes. Adding some debug output it seems
> > > > that's
> > > > during powering up the IMX93_MEDIABLK_PD_LCDIF power domain
> > > > there is
> > > > some
> > > > race condition. But adding more more detailed output made the
> > > > problem go
> > > > away. Did you notice something similar? It might be a red
> > > > hering though.
> > > 
> > > I don't see system freezing with my i.MX93 11x11 EVK when probing
> > > lcdif. I did try to boot the system several times. All look ok.
> > > This is
> > > a snippet of dmesg when lcdif probes:
> > > 
> > > --8<-
> > > -
> > > [0.753083] Serial: 8250/16550 driver, 4 ports, IRQ sharing
> > > enabled
> > > [0.761669] SuperH (H)SCI(F) driver initialized
> > > [0.766523] msm_serial: driver initialized
> > > [0.780523] printk: console [ttyLP0] enabled0x44380010 (irq =
> > > 16,
> > > base_baud = 150) is a FSL_LPUART
> > > [0.780523] printk: console [ttyLP0] enabled
> > > [0.788928] printk: bootconsole [lpuart32] disabled
> > > [0.788928] printk: bootconsole [lpuart32] disabled
> > > [0.804632] panel-simple lvds_panel: supply power not found,
> > > using
> > > dummy regulator
> > > [0.814741] [drm] Initialized imx-lcdif 1.0.0 20220417 for
> > > 4ae3.lcd-controller on minor 0
> > > [1.195930] Console: switching to colour frame buffer device
> > > 160x50
> > > [1.218385] imx-lcdif 4ae3.lcd-controller: [drm] fb0: imx-
> > > lcdifdrmfb frame buffer device
> > > [1.227099] cacheinfo: Unable to detect cache hierarchy for
> > > CPU 0
> > > [1.236725] loop: module loaded
> > > --8<-
> > > -
> > > 
> > > ~300 milliseconds are consumed by the enablement delay required
> > > by the
> > > "boe,ev121wxm-n10-1850" LVDS panel I use.
> > 
> > It seems you have the drivers compiled in. I use modules in my case
> > and
> > simple-panel as well. But this is unrelated, because lc

Re: [PATCH v4 0/6] drm: lcdif: Add i.MX93 LCDIF support

2023-02-17 Thread Liu Ying
On Fri, 2023-02-17 at 09:18 +0100, Alexander Stein wrote:
> Hi Liu,

Hi Alexander,

> 
> Am Freitag, 17. Februar 2023, 07:54:01 CET schrieb Liu Ying:
> > Hi,
> > 
> > This patch set aims to add i.MX93 LCDIF display controller support
> > in the existing LCDIF DRM driver.  The LCDIF embedded in i.MX93 SoC
> > is essentially the same to those embedded in i.MX8mp SoC.  Through
> > internal bridges, i.MX93 LCDIF may drive a MIPI DSI display or a LVDS
> > display or a parallel display.
> > 
> > Patch 1/6 adds device tree binding support for i.MX93 LCDIF in the
> > existing fsl,lcdif.yaml.
> > 
> > Patch 2/6 drops lcdif->bridge NULL pointer check as a cleanup patch.
> > 
> > Patch 3/6~5/6 prepare for adding i.MX93 LCDIF support step by step.
> > 
> > Patch 6/6 adds i.MX93 LCDIF compatible string as the last step of
> > adding i.MX93 LCDIF support.
> 
> Thanks for the series. I could test this on my TQMa93xxLA/MBa93xxCA with a 
> single LVDS display attached, so no DSI or parallel display. Hence I could 
> not 
> test the bus format and flags checks, but they look okay.
> So you can add
> Tested-by: Alexander Stein 
> to the whole series as well.

Thanks for your test.

> 
> One thing I noticed is that, sometimes it seems that before probing lcdif my 
> system completely freezes. Adding some debug output it seems that's during 
> powering up the IMX93_MEDIABLK_PD_LCDIF power domain there is some race 
> condition. But adding more more detailed output made the problem go away.
> Did you notice something similar? It might be a red hering though.

I don't see system freezing with my i.MX93 11x11 EVK when probing
lcdif. I did try to boot the system several times. All look ok. This is
a snippet of dmesg when lcdif probes:

--8<--
[0.753083] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[0.761669] SuperH (H)SCI(F) driver initialized
[0.766523] msm_serial: driver initialized
[0.780523] printk: console [ttyLP0] enabled0x44380010 (irq = 16,
base_baud = 150) is a FSL_LPUART
[0.780523] printk: console [ttyLP0] enabled
[0.788928] printk: bootconsole [lpuart32] disabled
[0.788928] printk: bootconsole [lpuart32] disabled
[0.804632] panel-simple lvds_panel: supply power not found, using
dummy regulator
[0.814741] [drm] Initialized imx-lcdif 1.0.0 20220417 for
4ae3.lcd-controller on minor 0
[1.195930] Console: switching to colour frame buffer device 160x50
[1.218385] imx-lcdif 4ae3.lcd-controller: [drm] fb0: imx-
lcdifdrmfb frame buffer device
[1.227099] cacheinfo: Unable to detect cache hierarchy for CPU 0
[1.236725] loop: module loaded
--8<------

~300 milliseconds are consumed by the enablement delay required by the
"boe,ev121wxm-n10-1850" LVDS panel I use.

Regards,
Liu Ying

> 
> Best regards,
> Alexander
> 
> > v3->v4:
> > * Improve warning message when ignoring invalid LCDIF OF endpoint ids in
> >   patch 5/6. (Alexander)
> > * Use 'new_{c,p}state' instead of 'new_{crtc,plane}_state' in patch 3/6.
> >   (Alexander)
> > * Simplify lcdif_crtc_reset() by calling lcdif_crtc_atomic_destroy_state()
> >   in patch 3/6. (Alexander)
> > * Add '!crtc->state' check in lcdif_crtc_atomic_duplicate_state() in patch
> > 3/6. (Alexander)
> > * Collect Alexander's R-b tags on patch 1/6, 2/6 and 6/6.
> > 
> > v2->v3:
> > * Fix a trivial typo in patch 6/6's commit message.
> > 
> > v1->v2:
> > * Add Krzysztof's A-b and Marek's R-b tags on patch 1/6.
> > * Split patch 2/2 in v1 into patch 2/6~6/6 in v2. (Marek, Alexander)
> > * Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
> > * Add comment on the 'base' member of lcdif_crtc_state structure to
> >   note it should always be the first member. (Lothar)
> > * Drop unneeded 'bridges' member from lcdif_drm_private structure.
> > * Drop a comment about bridge input bus format from
> > lcdif_crtc_atomic_check().
> > 
> > Liu Ying (6):
> >   dt-bindings: lcdif: Add i.MX93 LCDIF support
> >   drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge
> >   drm: lcdif: Determine bus format and flags in ->atomic_check()
> >   drm: lcdif: Check consistent bus format and flags across first bridges
> >   drm: lcdif: Add multiple encoders and first bridges support
> >   drm: lcdif: Add i.MX93 LCDIF compatible string
> > 
> >  .../bindings/display/fsl,lcdif.yaml   |   7 +-
> >  drivers/gpu/drm/mxsfb/lcdif_drv.c |  71 ++-
> >  drivers/gpu/drm/mxsfb/lcdif_drv.h |   5 +-
> >  drivers/gpu/drm/mxsfb/lcdif_kms.c | 198 --
> >  4 files changed, 206 insertions(+), 75 deletions(-)
> 
> 



[PATCH v4 6/6] drm: lcdif: Add i.MX93 LCDIF compatible string

2023-02-16 Thread Liu Ying
With all previous preparations done to make it possible for the
single LCDIF embedded in i.MX93 SoC to drive multiple displays
simultaneously, add i.MX93 LCDIF compatible string as the last
step of adding i.MX93 LCDIF support.

Reviewed-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v3->v4:
* Add Alexander's R-b tag.

v2->v3:
* Fix a trivial typo in commit message.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)

 drivers/gpu/drm/mxsfb/lcdif_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index f1f5caef390a..0eb132cad181 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -249,6 +249,7 @@ static const struct drm_driver lcdif_driver = {
 
 static const struct of_device_id lcdif_dt_ids[] = {
{ .compatible = "fsl,imx8mp-lcdif" },
+   { .compatible = "fsl,imx93-lcdif" },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, lcdif_dt_ids);
-- 
2.37.1



[PATCH v4 5/6] drm: lcdif: Add multiple encoders and first bridges support

2023-02-16 Thread Liu Ying
The single LCDIF embedded in i.MX93 SoC may drive multiple displays
simultaneously.  Look at LCDIF output port's remote port parents to
find all enabled first bridges.  Add an encoder for each found bridge
and attach the bridge to the encoder.  This is a preparation for
adding i.MX93 LCDIF support.

Signed-off-by: Liu Ying 
---
v3->v4:
* Improve warning message when ignoring invalid LCDIF OF endpoint ids.
  (Alexander)

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
* Drop unneeded 'bridges' member from lcdif_drm_private structure.

 drivers/gpu/drm/mxsfb/lcdif_drv.c | 68 +++
 drivers/gpu/drm/mxsfb/lcdif_drv.h |  4 +-
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 21 ++
 3 files changed, 66 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index b5b9a8e273c6..f1f5caef390a 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -9,13 +9,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -38,19 +41,68 @@ static const struct drm_mode_config_helper_funcs 
lcdif_mode_config_helpers = {
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 };
 
+static const struct drm_encoder_funcs lcdif_encoder_funcs = {
+   .destroy = drm_encoder_cleanup,
+};
+
 static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif)
 {
-   struct drm_device *drm = lcdif->drm;
+   struct device *dev = lcdif->drm->dev;
+   struct device_node *ep;
struct drm_bridge *bridge;
int ret;
 
-   bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0, 0);
-   if (IS_ERR(bridge))
-   return PTR_ERR(bridge);
-
-   ret = drm_bridge_attach(>encoder, bridge, NULL, 0);
-   if (ret)
-   return dev_err_probe(drm->dev, ret, "Failed to attach 
bridge\n");
+   for_each_endpoint_of_node(dev->of_node, ep) {
+   struct device_node *remote;
+   struct of_endpoint of_ep;
+   struct drm_encoder *encoder;
+
+   remote = of_graph_get_remote_port_parent(ep);
+   if (!of_device_is_available(remote)) {
+   of_node_put(remote);
+   continue;
+   }
+   of_node_put(remote);
+
+   ret = of_graph_parse_endpoint(ep, _ep);
+   if (ret < 0) {
+   dev_err(dev, "Failed to parse endpoint %pOF\n", ep);
+   of_node_put(ep);
+   return ret;
+   }
+
+   if (of_ep.id >= MAX_DISPLAYS) {
+   dev_warn(dev, "ingoring invalid endpoint id %u\n", 
of_ep.id);
+   continue;
+   }
+
+   bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, of_ep.id);
+   if (IS_ERR(bridge)) {
+   of_node_put(ep);
+   return dev_err_probe(dev, PTR_ERR(bridge),
+"Failed to get bridge for 
endpoint%u\n",
+of_ep.id);
+   }
+
+   encoder = >encoders[of_ep.id];
+   encoder->possible_crtcs = drm_crtc_mask(>crtc);
+   ret = drm_encoder_init(lcdif->drm, encoder, 
_encoder_funcs,
+  DRM_MODE_ENCODER_NONE, NULL);
+   if (ret) {
+   dev_err(dev, "Failed to initialize encoder for 
endpoint%u: %d\n",
+   of_ep.id, ret);
+   of_node_put(ep);
+   return ret;
+   }
+
+   ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+   if (ret) {
+   of_node_put(ep);
+   return dev_err_probe(dev, ret,
+"Failed to attach bridge for 
endpoint%u\n",
+of_ep.id);
+   }
+   }
 
return 0;
 }
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h 
b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index aa6d099a1897..c7400bd9bbd9 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
@@ -14,6 +14,8 @@
 #include 
 #include 
 
+#define MAX_DISPLAYS   3
+
 struct clk;
 
 struct lcdif_drm_private {
@@ -30,7 +32,7 @@ struct lcdif_drm_private {
/* i.MXRT does support overlay planes, add them here. */
} planes;
struct drm_crtc crtc;
-   struct drm_encoder  encoder;
+   struct drm_encoder  encoders[MAX_DISPLAYS];
 };
 
 static 

[PATCH v4 4/6] drm: lcdif: Check consistent bus format and flags across first bridges

2023-02-16 Thread Liu Ying
The single LCDIF embedded in i.MX93 SoC may drive multiple displays
simultaneously.  Check bus format and flags across first bridges in
->atomic_check() to ensure they are consistent.  This is a preparation
for adding i.MX93 LCDIF support.

Signed-off-by: Liu Ying 
---
v3->v4:
* No change.

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Drop a comment about bridge input bus format from lcdif_crtc_atomic_check().

 drivers/gpu/drm/mxsfb/lcdif_drv.c |  2 -
 drivers/gpu/drm/mxsfb/lcdif_drv.h |  1 -
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 76 ++-
 3 files changed, 55 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index cc2ceb301b96..b5b9a8e273c6 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -52,8 +52,6 @@ static int lcdif_attach_bridge(struct lcdif_drm_private 
*lcdif)
if (ret)
return dev_err_probe(drm->dev, ret, "Failed to attach 
bridge\n");
 
-   lcdif->bridge = bridge;
-
return 0;
 }
 
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h 
b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index 6cdba6e20c02..aa6d099a1897 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
@@ -31,7 +31,6 @@ struct lcdif_drm_private {
} planes;
struct drm_crtc crtc;
struct drm_encoder  encoder;
-   struct drm_bridge   *bridge;
 };
 
 static inline struct lcdif_drm_private *
diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index d46de433cd8e..d6009b353a16 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -424,15 +425,19 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
   struct drm_atomic_state *state)
 {
struct drm_device *drm = crtc->dev;
-   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
  crtc);
struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
bool has_primary = crtc_state->plane_mask &
   drm_plane_mask(crtc->primary);
+   struct drm_connector_state *connector_state;
+   struct drm_connector *connector;
+   struct drm_encoder *encoder;
struct drm_bridge_state *bridge_state;
-   struct drm_bridge *bridge = lcdif->bridge;
-   int ret;
+   struct drm_bridge *bridge;
+   u32 bus_format, bus_flags;
+   bool format_set = false, flags_set = false;
+   int ret, i;
 
/* The primary plane has to be enabled when the CRTC is active. */
if (crtc_state->active && !has_primary)
@@ -442,26 +447,55 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
if (ret)
return ret;
 
-   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
-   if (!bridge_state)
-   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_FIXED;
-   else
-   lcdif_crtc_state->bus_format = 
bridge_state->input_bus_cfg.format;
-
-   if (lcdif_crtc_state->bus_format == MEDIA_BUS_FMT_FIXED) {
-   dev_warn_once(drm->dev,
- "Bridge does not provide bus format, assuming 
MEDIA_BUS_FMT_RGB888_1X24.\n"
- "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
-   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   /* Try to find consistent bus format and flags across first bridges. */
+   for_each_new_connector_in_state(state, connector, connector_state, i) {
+   if (!connector_state->crtc)
+   continue;
+
+   encoder = connector_state->best_encoder;
+
+   bridge = drm_bridge_chain_get_first_bridge(encoder);
+   if (!bridge)
+   continue;
+
+   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+   if (!bridge_state)
+   bus_format = MEDIA_BUS_FMT_FIXED;
+   else
+   bus_format = bridge_state->input_bus_cfg.format;
+
+   if (bus_format == MEDIA_BUS_FMT_FIXED) {
+   dev_warn(drm->dev,
+"[ENCODER:%d:%s]'s bridge does not provide bus 
format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
+"Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n",
+encoder->base.id, enc

[PATCH v4 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()

2023-02-16 Thread Liu Ying
Instead of determining LCDIF output bus format and bus flags in
->atomic_enable(), do that in ->atomic_check().  This is a
preparation for the upcoming patch to check consistent bus format
and bus flags across all first downstream bridges in ->atomic_check().
New lcdif_crtc_state structure is introduced to cache bus format
and bus flags states in ->atomic_check() so that they can be read
in ->atomic_enable().

Signed-off-by: Liu Ying 
---
v3->v4:
* Use 'new_{c,p}state' instead of 'new_{crtc,plane}_state'. (Alexander)
* Simplify lcdif_crtc_reset() by calling lcdif_crtc_atomic_destroy_state().
  (Alexander)
* Add '!crtc->state' check in lcdif_crtc_atomic_duplicate_state(). (Alexander)

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Add comment on the 'base' member of lcdif_crtc_state structure to
  note it should always be the first member. (Lothar)

 drivers/gpu/drm/mxsfb/lcdif_kms.c | 134 ++
 1 file changed, 99 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index e54200a9fcb9..d46de433cd8e 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -30,6 +30,18 @@
 #include "lcdif_drv.h"
 #include "lcdif_regs.h"
 
+struct lcdif_crtc_state {
+   struct drm_crtc_state   base;   /* always be the first member */
+   u32 bus_format;
+   u32 bus_flags;
+};
+
+static inline struct lcdif_crtc_state *
+to_lcdif_crtc_state(struct drm_crtc_state *s)
+{
+   return container_of(s, struct lcdif_crtc_state, base);
+}
+
 /* 
-
  * CRTC
  */
@@ -385,48 +397,72 @@ static void lcdif_reset_block(struct lcdif_drm_private 
*lcdif)
readl(lcdif->base + LCDC_V8_CTRL);
 }
 
-static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
-struct drm_plane_state *plane_state,
-struct drm_bridge_state *bridge_state,
-const u32 bus_format)
+static void lcdif_crtc_mode_set_nofb(struct drm_crtc_state *crtc_state,
+struct drm_plane_state *plane_state)
 {
-   struct drm_device *drm = lcdif->crtc.dev;
-   struct drm_display_mode *m = >crtc.state->adjusted_mode;
-   u32 bus_flags = 0;
-
-   if (lcdif->bridge->timings)
-   bus_flags = lcdif->bridge->timings->input_bus_flags;
-   else if (bridge_state)
-   bus_flags = bridge_state->input_bus_cfg.flags;
+   struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
+   struct drm_device *drm = crtc_state->crtc->dev;
+   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
+   struct drm_display_mode *m = _state->adjusted_mode;
 
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
 m->crtc_clock,
 (int)(clk_get_rate(lcdif->clk) / 1000));
DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
-bus_flags);
+lcdif_crtc_state->bus_flags);
DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
 
/* Mandatory eLCDIF reset as per the Reference Manual */
lcdif_reset_block(lcdif);
 
-   lcdif_set_formats(lcdif, plane_state, bus_format);
+   lcdif_set_formats(lcdif, plane_state, lcdif_crtc_state->bus_format);
 
-   lcdif_set_mode(lcdif, bus_flags);
+   lcdif_set_mode(lcdif, lcdif_crtc_state->bus_flags);
 }
 
 static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
   struct drm_atomic_state *state)
 {
+   struct drm_device *drm = crtc->dev;
+   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
  crtc);
+   struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
bool has_primary = crtc_state->plane_mask &
   drm_plane_mask(crtc->primary);
+   struct drm_bridge_state *bridge_state;
+   struct drm_bridge *bridge = lcdif->bridge;
+   int ret;
 
/* The primary plane has to be enabled when the CRTC is active. */
if (crtc_state->active && !has_primary)
return -EINVAL;
 
-   return drm_atomic_add_affected_planes(state, crtc);
+   ret = drm_atomic_add_affected_planes(state, crtc);
+   if (ret)
+   return ret;
+
+   bridge_state = drm_atomic_get_new_bridge_state(state, bridge)

[PATCH v4 2/6] drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge

2023-02-16 Thread Liu Ying
A valid bridge is already found in lcdif_attach_bridge() and set
to lcdif->bridge, so lcdif->bridge cannot be a NULL pointer. Drop
the unnecessary NULL pointer check in KMS stage.

Reviewed-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v3->v4:
* Add Alexander's R-b tag.

v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)

 drivers/gpu/drm/mxsfb/lcdif_kms.c | 33 +++
 1 file changed, 12 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index 262bc43b1079..e54200a9fcb9 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -394,7 +394,7 @@ static void lcdif_crtc_mode_set_nofb(struct 
lcdif_drm_private *lcdif,
struct drm_display_mode *m = >crtc.state->adjusted_mode;
u32 bus_flags = 0;
 
-   if (lcdif->bridge && lcdif->bridge->timings)
+   if (lcdif->bridge->timings)
bus_flags = lcdif->bridge->timings->input_bus_flags;
else if (bridge_state)
bus_flags = bridge_state->input_bus_cfg.flags;
@@ -463,30 +463,21 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc 
*crtc,
struct drm_display_mode *m = >crtc.state->adjusted_mode;
struct drm_bridge_state *bridge_state = NULL;
struct drm_device *drm = lcdif->drm;
-   u32 bus_format = 0;
+   u32 bus_format;
dma_addr_t paddr;
 
-   /* If there is a bridge attached to the LCDIF, use its bus format */
-   if (lcdif->bridge) {
-   bridge_state =
-   drm_atomic_get_new_bridge_state(state,
-   lcdif->bridge);
-   if (!bridge_state)
-   bus_format = MEDIA_BUS_FMT_FIXED;
-   else
-   bus_format = bridge_state->input_bus_cfg.format;
-
-   if (bus_format == MEDIA_BUS_FMT_FIXED) {
-   dev_warn_once(drm->dev,
- "Bridge does not provide bus format, 
assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
- "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
-   bus_format = MEDIA_BUS_FMT_RGB888_1X24;
-   }
-   }
+   bridge_state = drm_atomic_get_new_bridge_state(state, lcdif->bridge);
+   if (!bridge_state)
+   bus_format = MEDIA_BUS_FMT_FIXED;
+   else
+   bus_format = bridge_state->input_bus_cfg.format;
 
-   /* If all else fails, default to RGB888_1X24 */
-   if (!bus_format)
+   if (bus_format == MEDIA_BUS_FMT_FIXED) {
+   dev_warn_once(drm->dev,
+ "Bridge does not provide bus format, assuming 
MEDIA_BUS_FMT_RGB888_1X24.\n"
+ "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   }
 
clk_set_rate(lcdif->clk, m->crtc_clock * 1000);
 
-- 
2.37.1



[PATCH v4 1/6] dt-bindings: lcdif: Add i.MX93 LCDIF support

2023-02-16 Thread Liu Ying
There is one LCDIF embedded in i.MX93 SoC to connect with
MIPI DSI controller through LCDIF cross line pattern(controlled
by mediamix blk-ctrl) or connect with LVDS display bridge(LDB)
directly or connect with a parallel display through parallel
display format(also controlled by mediamix blk-ctrl).  i.MX93
LCDIF IP is essentially the same to i.MX8MP LCDIF IP.  Add device
tree binding for i.MX93 LCDIF.

Acked-by: Krzysztof Kozlowski 
Reviewed-by: Marek Vasut 
Reviewed-by: Alexander Stein 
Signed-off-by: Liu Ying 
---
v3->v4:
* Add Alexander's R-b tag.

v2->v3:
* No change.

v1->v2:
* Add Krzysztof's A-b and Marek's R-b tags.

 Documentation/devicetree/bindings/display/fsl,lcdif.yaml | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml 
b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
index 75b4efd70ba8..fc11ab5fc465 100644
--- a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
+++ b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
@@ -21,6 +21,7 @@ properties:
   - fsl,imx28-lcdif
   - fsl,imx6sx-lcdif
   - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
   - items:
   - enum:
   - fsl,imx6sl-lcdif
@@ -88,7 +89,9 @@ allOf:
   properties:
 compatible:
   contains:
-const: fsl,imx8mp-lcdif
+enum:
+  - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
 then:
   properties:
 clocks:
@@ -107,6 +110,7 @@ allOf:
   enum:
 - fsl,imx6sx-lcdif
 - fsl,imx8mp-lcdif
+- fsl,imx93-lcdif
 then:
   properties:
 clocks:
@@ -123,6 +127,7 @@ allOf:
   - fsl,imx8mm-lcdif
   - fsl,imx8mn-lcdif
   - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
 then:
   required:
 - power-domains
-- 
2.37.1



[PATCH v4 0/6] drm: lcdif: Add i.MX93 LCDIF support

2023-02-16 Thread Liu Ying
Hi,

This patch set aims to add i.MX93 LCDIF display controller support
in the existing LCDIF DRM driver.  The LCDIF embedded in i.MX93 SoC
is essentially the same to those embedded in i.MX8mp SoC.  Through
internal bridges, i.MX93 LCDIF may drive a MIPI DSI display or a LVDS
display or a parallel display.

Patch 1/6 adds device tree binding support for i.MX93 LCDIF in the
existing fsl,lcdif.yaml.

Patch 2/6 drops lcdif->bridge NULL pointer check as a cleanup patch.

Patch 3/6~5/6 prepare for adding i.MX93 LCDIF support step by step.

Patch 6/6 adds i.MX93 LCDIF compatible string as the last step of
adding i.MX93 LCDIF support.

v3->v4:
* Improve warning message when ignoring invalid LCDIF OF endpoint ids in
  patch 5/6. (Alexander)
* Use 'new_{c,p}state' instead of 'new_{crtc,plane}_state' in patch 3/6.
  (Alexander)
* Simplify lcdif_crtc_reset() by calling lcdif_crtc_atomic_destroy_state()
  in patch 3/6. (Alexander)
* Add '!crtc->state' check in lcdif_crtc_atomic_duplicate_state() in patch 3/6.
  (Alexander)
* Collect Alexander's R-b tags on patch 1/6, 2/6 and 6/6.

v2->v3:
* Fix a trivial typo in patch 6/6's commit message.

v1->v2:
* Add Krzysztof's A-b and Marek's R-b tags on patch 1/6.
* Split patch 2/2 in v1 into patch 2/6~6/6 in v2. (Marek, Alexander)
* Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
* Add comment on the 'base' member of lcdif_crtc_state structure to
  note it should always be the first member. (Lothar)
* Drop unneeded 'bridges' member from lcdif_drm_private structure.
* Drop a comment about bridge input bus format from lcdif_crtc_atomic_check().

Liu Ying (6):
  dt-bindings: lcdif: Add i.MX93 LCDIF support
  drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge
  drm: lcdif: Determine bus format and flags in ->atomic_check()
  drm: lcdif: Check consistent bus format and flags across first bridges
  drm: lcdif: Add multiple encoders and first bridges support
  drm: lcdif: Add i.MX93 LCDIF compatible string

 .../bindings/display/fsl,lcdif.yaml   |   7 +-
 drivers/gpu/drm/mxsfb/lcdif_drv.c |  71 ++-
 drivers/gpu/drm/mxsfb/lcdif_drv.h |   5 +-
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 198 --
 4 files changed, 206 insertions(+), 75 deletions(-)

-- 
2.37.1



Re: [PATCH v3 5/6] drm: lcdif: Add multiple encoders and first bridges support

2023-02-15 Thread Liu Ying
On Wed, 2023-02-15 at 08:54 +0100, Alexander Stein wrote:
> Hi Liu,

Hi Alexander,

> 
> thanks for the update.

Thanks for the review.

> 
> Am Montag, 13. Februar 2023, 09:56:11 CET schrieb Liu Ying:
> > The single LCDIF embedded in i.MX93 SoC may drive multiple displays
> > simultaneously.  Look at LCDIF output port's remote port parents to
> > find all enabled first bridges.  Add an encoder for each found
> > bridge
> > and attach the bridge to the encoder.  This is a preparation for
> > adding i.MX93 LCDIF support.
> > 
> > Signed-off-by: Liu Ying 
> > ---
> > v2->v3:
> > * No change.
> > 
> > v1->v2:
> > * Split from patch 2/2 in v1. (Marek, Alexander)
> > * Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
> > * Drop unneeded 'bridges' member from lcdif_drm_private structure.
> > 
> >  drivers/gpu/drm/mxsfb/lcdif_drv.c | 68
> > +++
> >  drivers/gpu/drm/mxsfb/lcdif_drv.h |  4 +-
> >  drivers/gpu/drm/mxsfb/lcdif_kms.c | 21 ++
> >  3 files changed, 66 insertions(+), 27 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c
> > b/drivers/gpu/drm/mxsfb/lcdif_drv.c index
> > b5b9a8e273c6..eb6c265fa2fe 100644
> > --- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
> > +++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
> > @@ -9,13 +9,16 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> > 
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -38,19 +41,68 @@ static const struct
> > drm_mode_config_helper_funcs
> > lcdif_mode_config_helpers = { .atomic_commit_tail =
> > drm_atomic_helper_commit_tail_rpm,
> >  };
> > 
> > +static const struct drm_encoder_funcs lcdif_encoder_funcs = {
> > +   .destroy = drm_encoder_cleanup,
> > +};
> > +
> >  static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif)
> >  {
> > -   struct drm_device *drm = lcdif->drm;
> > +   struct device *dev = lcdif->drm->dev;
> > +   struct device_node *ep;
> > struct drm_bridge *bridge;
> > int ret;
> > 
> > -   bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0,
> > 0);
> > -   if (IS_ERR(bridge))
> > -   return PTR_ERR(bridge);
> > -
> > -   ret = drm_bridge_attach(>encoder, bridge, NULL, 0);
> > -   if (ret)
> > -   return dev_err_probe(drm->dev, ret, "Failed to attach 
> 
> bridge\n");
> > +   for_each_endpoint_of_node(dev->of_node, ep) {
> > +   struct device_node *remote;
> > +   struct of_endpoint of_ep;
> > +   struct drm_encoder *encoder;
> > +
> > +   remote = of_graph_get_remote_port_parent(ep);
> 
> Is it possible for remote to be NULL?

Yes. But, no worries.  Lothar said the check for '!remote' is not
needed in v1 comment because of_device_is_available() checks that.

> 
> > +   if (!of_device_is_available(remote)) {
> > +   of_node_put(remote);
> > +   continue;
> > +   }
> > +   of_node_put(remote);
> > +
> > +   ret = of_graph_parse_endpoint(ep, _ep);
> > +   if (ret < 0) {
> > +   dev_err(dev, "Failed to parse endpoint
> > %pOF\n", 
> 
> ep);
> > +   of_node_put(ep);
> > +   return ret;
> > +   }
> > +
> > +   if (of_ep.id >= MAX_DISPLAYS) {
> > +   dev_warn(dev, "invalid endpoint id %u\n", 
> 
> of_ep.id);
> 
> I would write
> dev_warn(dev, "ignoring invalid endpoint id %u\n", of_ep.id);
> just because the parsing continues but this one is skipped.

Ok, will do that in next version.

> 
> > +   continue;
> > +   }
> > +
> > +   bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 
> 
> of_ep.id);
> > +   if (IS_ERR(bridge)) {
> > +   of_node_put(ep);
> > +   return dev_err_probe(dev, PTR_ERR(bridge),
> > +"Failed to get bridge 
> 
> for endpoint%u\n",
> > +of_ep.id);
> > +   }
> > +
> > +   encoder = >encoders[of_ep.id];
> > +   encoder->possible_crtcs = drm_crtc_mask(>cr

Re: [PATCH v3 4/6] drm: lcdif: Check consistent bus format and flags across first bridges

2023-02-15 Thread Liu Ying
On Wed, 2023-02-15 at 08:55 +0100, Alexander Stein wrote:
> Hi Liu,

Hi Alexander,

> 
> thanks for the update.

Thanks for the review.

> 
> Am Montag, 13. Februar 2023, 09:56:10 CET schrieb Liu Ying:
> > The single LCDIF embedded in i.MX93 SoC may drive multiple displays
> > simultaneously.  Check bus format and flags across first bridges in
> > ->atomic_check() to ensure they are consistent.  This is a
> > preparation
> > for adding i.MX93 LCDIF support.
> > 
> > Signed-off-by: Liu Ying 
> > ---
> > v2->v3:
> > * No change.
> > 
> > v1->v2:
> > * Split from patch 2/2 in v1. (Marek, Alexander)
> > * Drop a comment about bridge input bus format from
> > lcdif_crtc_atomic_check().
> > 
> >  drivers/gpu/drm/mxsfb/lcdif_drv.c |  2 -
> >  drivers/gpu/drm/mxsfb/lcdif_drv.h |  1 -
> >  drivers/gpu/drm/mxsfb/lcdif_kms.c | 76 ++-
> > 
> >  3 files changed, 55 insertions(+), 24 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c
> > b/drivers/gpu/drm/mxsfb/lcdif_drv.c index
> > cc2ceb301b96..b5b9a8e273c6 100644
> > --- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
> > +++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
> > @@ -52,8 +52,6 @@ static int lcdif_attach_bridge(struct
> > lcdif_drm_private
> > *lcdif) if (ret)
> > return dev_err_probe(drm->dev, ret, "Failed to attach 
> 
> bridge\n");
> > 
> > -   lcdif->bridge = bridge;
> > -
> > return 0;
> >  }
> > 
> > diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h
> > b/drivers/gpu/drm/mxsfb/lcdif_drv.h index
> > 6cdba6e20c02..aa6d099a1897 100644
> > --- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
> > +++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
> > @@ -31,7 +31,6 @@ struct lcdif_drm_private {
> > } planes;
> > struct drm_crtc crtc;
> > struct drm_encoder  encoder;
> > -   struct drm_bridge   *bridge;
> >  };
> > 
> >  static inline struct lcdif_drm_private *
> > diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > b/drivers/gpu/drm/mxsfb/lcdif_kms.c index
> > 294cecdf5439..4ea3d2b2cf61 100644
> > --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > @@ -17,6 +17,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -424,15 +425,19 @@ static int lcdif_crtc_atomic_check(struct
> > drm_crtc
> > *crtc, struct drm_atomic_state *state)
> >  {
> > struct drm_device *drm = crtc->dev;
> > -   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
> > struct drm_crtc_state *crtc_state = 
> 
> drm_atomic_get_new_crtc_state(state,
> > 
> 
> crtc);
> > struct lcdif_crtc_state *lcdif_crtc_state =
> > to_lcdif_crtc_state(crtc_state); bool has_primary = crtc_state-
> > >plane_mask
> > &
> >drm_plane_mask(crtc->primary);
> > +   struct drm_connector_state *connector_state;
> > +   struct drm_connector *connector;
> > +   struct drm_encoder *encoder;
> > struct drm_bridge_state *bridge_state;
> > -   struct drm_bridge *bridge = lcdif->bridge;
> > -   int ret;
> > +   struct drm_bridge *bridge;
> > +   u32 bus_format, bus_flags;
> > +   bool format_set = false, flags_set = false;
> > +   int ret, i;
> > 
> > /* The primary plane has to be enabled when the CRTC is active.
> > */
> > if (crtc_state->active && !has_primary)
> > @@ -442,26 +447,55 @@ static int lcdif_crtc_atomic_check(struct
> > drm_crtc
> > *crtc, if (ret)
> > return ret;
> > 
> > -   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
> > -   if (!bridge_state)
> > -   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_FIXED;
> > -   else
> > -   lcdif_crtc_state->bus_format = bridge_state-
> > input_bus_cfg.format;
> > -
> > -   if (lcdif_crtc_state->bus_format == MEDIA_BUS_FMT_FIXED) {
> > -   dev_warn_once(drm->dev,
> > - "Bridge does not provide bus format, 
> 
> assuming
> > MEDIA_BUS_FMT_RGB888_1X24.\n" -   "Please
> > fix 
> 
> bridge driver by
> > handling atomic_get_input_bus_fmts.\n"); -  lcdif_crtc_stat
> > e-
> > bus_format =
> > MEDIA_BUS_

Re: [PATCH v3 1/6] dt-bindings: lcdif: Add i.MX93 LCDIF support

2023-02-14 Thread Liu Ying
On Wed, 2023-02-15 at 08:26 +0100, Alexander Stein wrote:
> Hi Liu,

Hi Alexander,

> 
> thanks for the update.

Thanks for the review.

> 
> Am Montag, 13. Februar 2023, 09:56:07 CET schrieb Liu Ying:
> > There is one LCDIF embedded in i.MX93 SoC to connect with
> > MIPI DSI controller through LCDIF cross line pattern(controlled
> > by mediamix blk-ctrl) or connect with LVDS display bridge(LDB)
> > directly or connect with a parallel display through parallel
> > display format(also controlled by mediamix blk-ctrl).  i.MX93
> > LCDIF IP is essentially the same to i.MX8MP LCDIF IP.  Add device
> > tree binding for i.MX93 LCDIF.
> > 
> > Acked-by: Krzysztof Kozlowski 
> > Reviewed-by: Marek Vasut 
> > Signed-off-by: Liu Ying 
> > ---
> > v2->v3:
> > * No change.
> > 
> > v1->v2:
> > * Add Krzysztof's A-b and Marek's R-b tags on patch 1/6.
> > 
> >  Documentation/devicetree/bindings/display/fsl,lcdif.yaml | 7
> > ++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
> > b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml index
> > 75b4efd70ba8..fc11ab5fc465 100644
> > --- a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
> > +++ b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
> > @@ -21,6 +21,7 @@ properties:
> >- fsl,imx28-lcdif
> >- fsl,imx6sx-lcdif
> >- fsl,imx8mp-lcdif
> > +  - fsl,imx93-lcdif
> >- items:
> >- enum:
> >- fsl,imx6sl-lcdif
> > @@ -88,7 +89,9 @@ allOf:
> >properties:
> >  compatible:
> >contains:
> > -const: fsl,imx8mp-lcdif
> > +enum:
> > +  - fsl,imx8mp-lcdif
> > +  - fsl,imx93-lcdif
> >  then:
> >properties:
> >  clocks:
> > @@ -107,6 +110,7 @@ allOf:
> >enum:
> >  - fsl,imx6sx-lcdif
> >  - fsl,imx8mp-lcdif
> > +- fsl,imx93-lcdif
> >  then:
> >properties:
> >  clocks:
> > @@ -123,6 +127,7 @@ allOf:
> >- fsl,imx8mm-lcdif
> >- fsl,imx8mn-lcdif
> >- fsl,imx8mp-lcdif
> > +  - fsl,imx93-lcdif
> >  then:
> >required:
> >  - power-domains
> 
> I would have expected that fsl,imx93-lcdif supports up to 3 endpoints
> (MIPI 
> DSI, LVDS, and parallel) in a 'ports' subnode. But this binding only
> supports 
> a single 'port' sub-node. Also an example for this case might be very
> helpful.

The port node allows multiple endpoints(See graph.yaml[1]).  It's
enough to use the existing port node instead of using ports node.

For i.MX93 LCDIF, the port node will be something like this:
8<--
port {
#address-cells = <1>;
#size-cells = <0>;

lcdif_to_pdfc: endpoint@0 {
    reg = <0>;
};

lcdif_to_ldb: endpoint@1 {
reg = <1>;
};

lcdif_to_cross_line_pattern: endpoint@2 {
reg = <2>;
};
};
8<--

Looks like it's not necessary to add a specifc example for i.MX93
LCDIF.

[1] 
https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/graph.yaml#L48

Regards,
Liu Ying



Re: [PATCH v3 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()

2023-02-14 Thread Liu Ying
On Tue, 2023-02-14 at 15:12 +0100, Alexander Stein wrote:
> Hi Liu,

Hi Alexander,

> 
> thanks for the update.

Thanks for your review.

> 
> Am Montag, 13. Februar 2023, 09:56:09 CET schrieb Liu Ying:
> > Instead of determining LCDIF output bus format and bus flags in
> > ->atomic_enable(), do that in ->atomic_check().  This is a
> > preparation for the upcoming patch to check consistent bus format
> > and bus flags across all first downstream bridges in
> > ->atomic_check().
> > New lcdif_crtc_state structure is introduced to cache bus format
> > and bus flags states in ->atomic_check() so that they can be read
> > in ->atomic_enable().
> > 
> > Signed-off-by: Liu Ying 
> > ---
> > v2->v3:
> > * No change.
> > 
> > v1->v2:
> > * Split from patch 2/2 in v1. (Marek, Alexander)
> > * Add comment on the 'base' member of lcdif_crtc_state structure to
> >   note it should always be the first member. (Lothar)
> > 
> >  drivers/gpu/drm/mxsfb/lcdif_kms.c | 138 ++--
> > --
> >  1 file changed, 100 insertions(+), 38 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > b/drivers/gpu/drm/mxsfb/lcdif_kms.c index
> > e54200a9fcb9..294cecdf5439 100644
> > --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > @@ -30,6 +30,18 @@
> >  #include "lcdif_drv.h"
> >  #include "lcdif_regs.h"
> > 
> > +struct lcdif_crtc_state {
> > +   struct drm_crtc_state   base;   /* always be the first 
> 
> member */
> 
> Is it strictly necessary that base is the first member?
> to_lcdif_crtc_state() 
> should be able to handle any position within the struct. I mean it's
> sensible 
> to put it in first place. But the comment somehow bugs me.

The comment was added in v2 to make sure to_lcdif_crtc_state() work ok
when a NULL pointer is handed over to it.  The NULL pointer worries
Lothar a bit as we can see Lothar's comment for v1.

> 
> > +   u32 bus_format;
> > +   u32 bus_flags;
> > +};
> > +
> > +static inline struct lcdif_crtc_state *
> > +to_lcdif_crtc_state(struct drm_crtc_state *s)
> > +{
> > +   return container_of(s, struct lcdif_crtc_state, base);
> > +}
> > +
> >  /*
> > -
> > --
> > -- * CRTC
> >   */
> > @@ -385,48 +397,72 @@ static void lcdif_reset_block(struct
> > lcdif_drm_private
> > *lcdif) readl(lcdif->base + LCDC_V8_CTRL);
> >  }
> > 
> > -static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private
> > *lcdif,
> > -struct drm_plane_state 
> 
> *plane_state,
> > -struct drm_bridge_state 
> 
> *bridge_state,
> > -const u32 bus_format)
> > +static void lcdif_crtc_mode_set_nofb(struct drm_crtc_state
> > *crtc_state,
> > +struct drm_plane_state 
> 
> *plane_state)
> >  {
> > -   struct drm_device *drm = lcdif->crtc.dev;
> > -   struct drm_display_mode *m = >crtc.state->adjusted_mode;
> > -   u32 bus_flags = 0;
> > -
> > -   if (lcdif->bridge->timings)
> > -   bus_flags = lcdif->bridge->timings->input_bus_flags;
> > -   else if (bridge_state)
> > -   bus_flags = bridge_state->input_bus_cfg.flags;
> > +   struct lcdif_crtc_state *lcdif_crtc_state =
> > to_lcdif_crtc_state(crtc_state); +  struct drm_device *drm =
> > crtc_state->crtc->dev;
> > +   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
> > +   struct drm_display_mode *m = _state->adjusted_mode;
> > 
> > DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual:
> > %dkHz)
> 
> \n",
> >  m->crtc_clock,
> >  (int)(clk_get_rate(lcdif->clk) / 1000));
> > DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
> > -bus_flags);
> > +lcdif_crtc_state->bus_flags);
> > DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m-
> > >flags);
> > 
> > /* Mandatory eLCDIF reset as per the Reference Manual */
> > lcdif_reset_block(lcdif);
> > 
> > -   lcdif_set_formats(lcdif, plane_state, bus_format);
> > +   lcdif_set_formats(lcdif, plane_state, lcdif_crtc_state-
> &g

[PATCH v3 6/6] drm: lcdif: Add i.MX93 LCDIF compatible string

2023-02-13 Thread Liu Ying
With all previous preparations done to make it possible for the
single LCDIF embedded in i.MX93 SoC to drive multiple displays
simultaneously, add i.MX93 LCDIF compatible string as the last
step of adding i.MX93 LCDIF support.

Signed-off-by: Liu Ying 
---
v2->v3:
* Fix a trivial typo in commit message.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)

 drivers/gpu/drm/mxsfb/lcdif_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index eb6c265fa2fe..48c43b273a4a 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -249,6 +249,7 @@ static const struct drm_driver lcdif_driver = {
 
 static const struct of_device_id lcdif_dt_ids[] = {
{ .compatible = "fsl,imx8mp-lcdif" },
+   { .compatible = "fsl,imx93-lcdif" },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, lcdif_dt_ids);
-- 
2.37.1



[PATCH v3 5/6] drm: lcdif: Add multiple encoders and first bridges support

2023-02-13 Thread Liu Ying
The single LCDIF embedded in i.MX93 SoC may drive multiple displays
simultaneously.  Look at LCDIF output port's remote port parents to
find all enabled first bridges.  Add an encoder for each found bridge
and attach the bridge to the encoder.  This is a preparation for
adding i.MX93 LCDIF support.

Signed-off-by: Liu Ying 
---
v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
* Drop unneeded 'bridges' member from lcdif_drm_private structure.

 drivers/gpu/drm/mxsfb/lcdif_drv.c | 68 +++
 drivers/gpu/drm/mxsfb/lcdif_drv.h |  4 +-
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 21 ++
 3 files changed, 66 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index b5b9a8e273c6..eb6c265fa2fe 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -9,13 +9,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -38,19 +41,68 @@ static const struct drm_mode_config_helper_funcs 
lcdif_mode_config_helpers = {
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 };
 
+static const struct drm_encoder_funcs lcdif_encoder_funcs = {
+   .destroy = drm_encoder_cleanup,
+};
+
 static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif)
 {
-   struct drm_device *drm = lcdif->drm;
+   struct device *dev = lcdif->drm->dev;
+   struct device_node *ep;
struct drm_bridge *bridge;
int ret;
 
-   bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0, 0);
-   if (IS_ERR(bridge))
-   return PTR_ERR(bridge);
-
-   ret = drm_bridge_attach(>encoder, bridge, NULL, 0);
-   if (ret)
-   return dev_err_probe(drm->dev, ret, "Failed to attach 
bridge\n");
+   for_each_endpoint_of_node(dev->of_node, ep) {
+   struct device_node *remote;
+   struct of_endpoint of_ep;
+   struct drm_encoder *encoder;
+
+   remote = of_graph_get_remote_port_parent(ep);
+   if (!of_device_is_available(remote)) {
+   of_node_put(remote);
+   continue;
+   }
+   of_node_put(remote);
+
+   ret = of_graph_parse_endpoint(ep, _ep);
+   if (ret < 0) {
+   dev_err(dev, "Failed to parse endpoint %pOF\n", ep);
+   of_node_put(ep);
+   return ret;
+   }
+
+   if (of_ep.id >= MAX_DISPLAYS) {
+   dev_warn(dev, "invalid endpoint id %u\n", of_ep.id);
+   continue;
+   }
+
+   bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, of_ep.id);
+   if (IS_ERR(bridge)) {
+   of_node_put(ep);
+   return dev_err_probe(dev, PTR_ERR(bridge),
+"Failed to get bridge for 
endpoint%u\n",
+of_ep.id);
+   }
+
+   encoder = >encoders[of_ep.id];
+   encoder->possible_crtcs = drm_crtc_mask(>crtc);
+   ret = drm_encoder_init(lcdif->drm, encoder, 
_encoder_funcs,
+  DRM_MODE_ENCODER_NONE, NULL);
+   if (ret) {
+   dev_err(dev, "Failed to initialize encoder for 
endpoint%u: %d\n",
+   of_ep.id, ret);
+   of_node_put(ep);
+   return ret;
+   }
+
+   ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+   if (ret) {
+   of_node_put(ep);
+   return dev_err_probe(dev, ret,
+"Failed to attach bridge for 
endpoint%u\n",
+of_ep.id);
+   }
+   }
 
return 0;
 }
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h 
b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index aa6d099a1897..c7400bd9bbd9 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
@@ -14,6 +14,8 @@
 #include 
 #include 
 
+#define MAX_DISPLAYS   3
+
 struct clk;
 
 struct lcdif_drm_private {
@@ -30,7 +32,7 @@ struct lcdif_drm_private {
/* i.MXRT does support overlay planes, add them here. */
} planes;
struct drm_crtc crtc;
-   struct drm_encoder  encoder;
+   struct drm_encoder  encoders[MAX_DISPLAYS];
 };
 
 static inline struct lcdif_drm_private *
diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb

[PATCH v3 4/6] drm: lcdif: Check consistent bus format and flags across first bridges

2023-02-13 Thread Liu Ying
The single LCDIF embedded in i.MX93 SoC may drive multiple displays
simultaneously.  Check bus format and flags across first bridges in
->atomic_check() to ensure they are consistent.  This is a preparation
for adding i.MX93 LCDIF support.

Signed-off-by: Liu Ying 
---
v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Drop a comment about bridge input bus format from lcdif_crtc_atomic_check().

 drivers/gpu/drm/mxsfb/lcdif_drv.c |  2 -
 drivers/gpu/drm/mxsfb/lcdif_drv.h |  1 -
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 76 ++-
 3 files changed, 55 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index cc2ceb301b96..b5b9a8e273c6 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -52,8 +52,6 @@ static int lcdif_attach_bridge(struct lcdif_drm_private 
*lcdif)
if (ret)
return dev_err_probe(drm->dev, ret, "Failed to attach 
bridge\n");
 
-   lcdif->bridge = bridge;
-
return 0;
 }
 
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h 
b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index 6cdba6e20c02..aa6d099a1897 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
@@ -31,7 +31,6 @@ struct lcdif_drm_private {
} planes;
struct drm_crtc crtc;
struct drm_encoder  encoder;
-   struct drm_bridge   *bridge;
 };
 
 static inline struct lcdif_drm_private *
diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index 294cecdf5439..4ea3d2b2cf61 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -424,15 +425,19 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
   struct drm_atomic_state *state)
 {
struct drm_device *drm = crtc->dev;
-   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
  crtc);
struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
bool has_primary = crtc_state->plane_mask &
   drm_plane_mask(crtc->primary);
+   struct drm_connector_state *connector_state;
+   struct drm_connector *connector;
+   struct drm_encoder *encoder;
struct drm_bridge_state *bridge_state;
-   struct drm_bridge *bridge = lcdif->bridge;
-   int ret;
+   struct drm_bridge *bridge;
+   u32 bus_format, bus_flags;
+   bool format_set = false, flags_set = false;
+   int ret, i;
 
/* The primary plane has to be enabled when the CRTC is active. */
if (crtc_state->active && !has_primary)
@@ -442,26 +447,55 @@ static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
if (ret)
return ret;
 
-   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
-   if (!bridge_state)
-   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_FIXED;
-   else
-   lcdif_crtc_state->bus_format = 
bridge_state->input_bus_cfg.format;
-
-   if (lcdif_crtc_state->bus_format == MEDIA_BUS_FMT_FIXED) {
-   dev_warn_once(drm->dev,
- "Bridge does not provide bus format, assuming 
MEDIA_BUS_FMT_RGB888_1X24.\n"
- "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
-   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   /* Try to find consistent bus format and flags across first bridges. */
+   for_each_new_connector_in_state(state, connector, connector_state, i) {
+   if (!connector_state->crtc)
+   continue;
+
+   encoder = connector_state->best_encoder;
+
+   bridge = drm_bridge_chain_get_first_bridge(encoder);
+   if (!bridge)
+   continue;
+
+   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+   if (!bridge_state)
+   bus_format = MEDIA_BUS_FMT_FIXED;
+   else
+   bus_format = bridge_state->input_bus_cfg.format;
+
+   if (bus_format == MEDIA_BUS_FMT_FIXED) {
+   dev_warn(drm->dev,
+"[ENCODER:%d:%s]'s bridge does not provide bus 
format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
+"Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n",
+encoder->base.id, encode

[PATCH v3 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()

2023-02-13 Thread Liu Ying
Instead of determining LCDIF output bus format and bus flags in
->atomic_enable(), do that in ->atomic_check().  This is a
preparation for the upcoming patch to check consistent bus format
and bus flags across all first downstream bridges in ->atomic_check().
New lcdif_crtc_state structure is introduced to cache bus format
and bus flags states in ->atomic_check() so that they can be read
in ->atomic_enable().

Signed-off-by: Liu Ying 
---
v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)
* Add comment on the 'base' member of lcdif_crtc_state structure to
  note it should always be the first member. (Lothar)

 drivers/gpu/drm/mxsfb/lcdif_kms.c | 138 ++
 1 file changed, 100 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index e54200a9fcb9..294cecdf5439 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -30,6 +30,18 @@
 #include "lcdif_drv.h"
 #include "lcdif_regs.h"
 
+struct lcdif_crtc_state {
+   struct drm_crtc_state   base;   /* always be the first member */
+   u32 bus_format;
+   u32 bus_flags;
+};
+
+static inline struct lcdif_crtc_state *
+to_lcdif_crtc_state(struct drm_crtc_state *s)
+{
+   return container_of(s, struct lcdif_crtc_state, base);
+}
+
 /* 
-
  * CRTC
  */
@@ -385,48 +397,72 @@ static void lcdif_reset_block(struct lcdif_drm_private 
*lcdif)
readl(lcdif->base + LCDC_V8_CTRL);
 }
 
-static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
-struct drm_plane_state *plane_state,
-struct drm_bridge_state *bridge_state,
-const u32 bus_format)
+static void lcdif_crtc_mode_set_nofb(struct drm_crtc_state *crtc_state,
+struct drm_plane_state *plane_state)
 {
-   struct drm_device *drm = lcdif->crtc.dev;
-   struct drm_display_mode *m = >crtc.state->adjusted_mode;
-   u32 bus_flags = 0;
-
-   if (lcdif->bridge->timings)
-   bus_flags = lcdif->bridge->timings->input_bus_flags;
-   else if (bridge_state)
-   bus_flags = bridge_state->input_bus_cfg.flags;
+   struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
+   struct drm_device *drm = crtc_state->crtc->dev;
+   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
+   struct drm_display_mode *m = _state->adjusted_mode;
 
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
 m->crtc_clock,
 (int)(clk_get_rate(lcdif->clk) / 1000));
DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
-bus_flags);
+lcdif_crtc_state->bus_flags);
DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
 
/* Mandatory eLCDIF reset as per the Reference Manual */
lcdif_reset_block(lcdif);
 
-   lcdif_set_formats(lcdif, plane_state, bus_format);
+   lcdif_set_formats(lcdif, plane_state, lcdif_crtc_state->bus_format);
 
-   lcdif_set_mode(lcdif, bus_flags);
+   lcdif_set_mode(lcdif, lcdif_crtc_state->bus_flags);
 }
 
 static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
   struct drm_atomic_state *state)
 {
+   struct drm_device *drm = crtc->dev;
+   struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
  crtc);
+   struct lcdif_crtc_state *lcdif_crtc_state = 
to_lcdif_crtc_state(crtc_state);
bool has_primary = crtc_state->plane_mask &
   drm_plane_mask(crtc->primary);
+   struct drm_bridge_state *bridge_state;
+   struct drm_bridge *bridge = lcdif->bridge;
+   int ret;
 
/* The primary plane has to be enabled when the CRTC is active. */
if (crtc_state->active && !has_primary)
return -EINVAL;
 
-   return drm_atomic_add_affected_planes(state, crtc);
+   ret = drm_atomic_add_affected_planes(state, crtc);
+   if (ret)
+   return ret;
+
+   bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+   if (!bridge_state)
+   lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_FIXED;
+   else
+   lcdif_crtc_state->bus_format = 
bridge_state->input_bus_cfg.format;
+
+   if (lcdif_crtc_state->bus_fo

[PATCH v3 2/6] drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge

2023-02-13 Thread Liu Ying
A valid bridge is already found in lcdif_attach_bridge() and set
to lcdif->bridge, so lcdif->bridge cannot be a NULL pointer. Drop
the unnecessary NULL pointer check in KMS stage.

Signed-off-by: Liu Ying 
---
v2->v3:
* No change.

v1->v2:
* Split from patch 2/2 in v1. (Marek, Alexander)

 drivers/gpu/drm/mxsfb/lcdif_kms.c | 33 +++
 1 file changed, 12 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index 262bc43b1079..e54200a9fcb9 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -394,7 +394,7 @@ static void lcdif_crtc_mode_set_nofb(struct 
lcdif_drm_private *lcdif,
struct drm_display_mode *m = >crtc.state->adjusted_mode;
u32 bus_flags = 0;
 
-   if (lcdif->bridge && lcdif->bridge->timings)
+   if (lcdif->bridge->timings)
bus_flags = lcdif->bridge->timings->input_bus_flags;
else if (bridge_state)
bus_flags = bridge_state->input_bus_cfg.flags;
@@ -463,30 +463,21 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc 
*crtc,
struct drm_display_mode *m = >crtc.state->adjusted_mode;
struct drm_bridge_state *bridge_state = NULL;
struct drm_device *drm = lcdif->drm;
-   u32 bus_format = 0;
+   u32 bus_format;
dma_addr_t paddr;
 
-   /* If there is a bridge attached to the LCDIF, use its bus format */
-   if (lcdif->bridge) {
-   bridge_state =
-   drm_atomic_get_new_bridge_state(state,
-   lcdif->bridge);
-   if (!bridge_state)
-   bus_format = MEDIA_BUS_FMT_FIXED;
-   else
-   bus_format = bridge_state->input_bus_cfg.format;
-
-   if (bus_format == MEDIA_BUS_FMT_FIXED) {
-   dev_warn_once(drm->dev,
- "Bridge does not provide bus format, 
assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
- "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
-   bus_format = MEDIA_BUS_FMT_RGB888_1X24;
-   }
-   }
+   bridge_state = drm_atomic_get_new_bridge_state(state, lcdif->bridge);
+   if (!bridge_state)
+   bus_format = MEDIA_BUS_FMT_FIXED;
+   else
+   bus_format = bridge_state->input_bus_cfg.format;
 
-   /* If all else fails, default to RGB888_1X24 */
-   if (!bus_format)
+   if (bus_format == MEDIA_BUS_FMT_FIXED) {
+   dev_warn_once(drm->dev,
+ "Bridge does not provide bus format, assuming 
MEDIA_BUS_FMT_RGB888_1X24.\n"
+ "Please fix bridge driver by handling 
atomic_get_input_bus_fmts.\n");
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   }
 
clk_set_rate(lcdif->clk, m->crtc_clock * 1000);
 
-- 
2.37.1



[PATCH v3 1/6] dt-bindings: lcdif: Add i.MX93 LCDIF support

2023-02-13 Thread Liu Ying
There is one LCDIF embedded in i.MX93 SoC to connect with
MIPI DSI controller through LCDIF cross line pattern(controlled
by mediamix blk-ctrl) or connect with LVDS display bridge(LDB)
directly or connect with a parallel display through parallel
display format(also controlled by mediamix blk-ctrl).  i.MX93
LCDIF IP is essentially the same to i.MX8MP LCDIF IP.  Add device
tree binding for i.MX93 LCDIF.

Acked-by: Krzysztof Kozlowski 
Reviewed-by: Marek Vasut 
Signed-off-by: Liu Ying 
---
v2->v3:
* No change.

v1->v2:
* Add Krzysztof's A-b and Marek's R-b tags on patch 1/6.

 Documentation/devicetree/bindings/display/fsl,lcdif.yaml | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml 
b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
index 75b4efd70ba8..fc11ab5fc465 100644
--- a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
+++ b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
@@ -21,6 +21,7 @@ properties:
   - fsl,imx28-lcdif
   - fsl,imx6sx-lcdif
   - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
   - items:
   - enum:
   - fsl,imx6sl-lcdif
@@ -88,7 +89,9 @@ allOf:
   properties:
 compatible:
   contains:
-const: fsl,imx8mp-lcdif
+enum:
+  - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
 then:
   properties:
 clocks:
@@ -107,6 +110,7 @@ allOf:
   enum:
 - fsl,imx6sx-lcdif
 - fsl,imx8mp-lcdif
+- fsl,imx93-lcdif
 then:
   properties:
 clocks:
@@ -123,6 +127,7 @@ allOf:
   - fsl,imx8mm-lcdif
   - fsl,imx8mn-lcdif
   - fsl,imx8mp-lcdif
+  - fsl,imx93-lcdif
 then:
   required:
 - power-domains
-- 
2.37.1



[PATCH v3 0/6] drm: lcdif: Add i.MX93 LCDIF support

2023-02-13 Thread Liu Ying
Hi,

This patch set aims to add i.MX93 LCDIF display controller support
in the existing LCDIF DRM driver.  The LCDIF embedded in i.MX93 SoC
is essentially the same to those embedded in i.MX8mp SoC.  Through
internal bridges, i.MX93 LCDIF may drive a MIPI DSI display or a LVDS
display or a parallel display.

Patch 1/6 adds device tree binding support for i.MX93 LCDIF in the
existing fsl,lcdif.yaml.

Patch 2/6 drops lcdif->bridge NULL pointer check as a cleanup patch.

Patch 3/6~5/6 prepare for adding i.MX93 LCDIF support step by step.

Patch 6/6 adds i.MX93 LCDIF compatible string as the last step of
adding i.MX93 LCDIF support.

v2->v3:
* Fix a trivial typo in patch 6/6's commit message.

v1->v2:
* Add Krzysztof's A-b and Marek's R-b tags on patch 1/6.
* Split patch 2/2 in v1 into patch 2/6~6/6 in v2. (Marek, Alexander)
* Drop '!remote ||' from lcdif_attach_bridge(). (Lothar)
* Add comment on the 'base' member of lcdif_crtc_state structure to
  note it should always be the first member. (Lothar)
* Drop unneeded 'bridges' member from lcdif_drm_private structure.
* Drop a comment about bridge input bus format from lcdif_crtc_atomic_check().

Liu Ying (6):
  dt-bindings: lcdif: Add i.MX93 LCDIF support
  drm: lcdif: Drop unnecessary NULL pointer check on lcdif->bridge
  drm: lcdif: Determine bus format and flags in ->atomic_check()
  drm: lcdif: Check consistent bus format and flags across first bridges
  drm: lcdif: Add multiple encoders and first bridges support
  drm: lcdif: Add i.MX93 LCDIF compatible string

 .../bindings/display/fsl,lcdif.yaml   |   7 +-
 drivers/gpu/drm/mxsfb/lcdif_drv.c |  71 +-
 drivers/gpu/drm/mxsfb/lcdif_drv.h |   5 +-
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 202 --
 4 files changed, 207 insertions(+), 78 deletions(-)

-- 
2.37.1



[PATCH 2/2] drm/panel: panel-simple: Add BOE EV121WXM-N10-1850 panel support

2023-02-11 Thread Liu Ying
Add BOE EV121WXM-N10-1850 12.1" WXGA (1280x800) TFT LCD panel support.
The panel has a LVDS display interface.

The panel's product specification can be found at:
http://www.onetech.com.tw/files/EV121WXM-N10-1850ProductSpecification_20180801.pdf

Signed-off-by: Liu Ying 
---
 drivers/gpu/drm/panel/panel-simple.c | 33 
 1 file changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 8a3b685c2fcc..ac7aea7c186d 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1211,6 +1211,36 @@ static const struct panel_desc bananapi_s070wv20_ct16 = {
},
 };
 
+static const struct drm_display_mode boe_ev121wxm_n10_1850_mode = {
+   .clock = 71000,
+   .hdisplay = 1280,
+   .hsync_start = 1280 + 48,
+   .hsync_end = 1280 + 48 + 32,
+   .htotal = 1280 + 48 + 32 + 80,
+   .vdisplay = 800,
+   .vsync_start = 800 + 3,
+   .vsync_end = 800 + 3 + 6,
+   .vtotal = 800 + 3 + 6 + 14,
+};
+
+static const struct panel_desc boe_ev121wxm_n10_1850 = {
+   .modes = _ev121wxm_n10_1850_mode,
+   .num_modes = 1,
+   .bpc = 8,
+   .size = {
+   .width = 261,
+   .height = 163,
+   },
+   .delay = {
+   .prepare = 9,
+   .enable = 300,
+   .unprepare = 300,
+   .disable = 560,
+   },
+   .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+   .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct drm_display_mode boe_hv070wsa_mode = {
.clock = 42105,
.hdisplay = 1024,
@@ -3984,6 +4014,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "bananapi,s070wv20-ct16",
.data = _s070wv20_ct16,
+   }, {
+   .compatible = "boe,ev121wxm-n10-1850",
+   .data = _ev121wxm_n10_1850,
}, {
.compatible = "boe,hv070wsa-100",
.data = _hv070wsa
-- 
2.37.1



[PATCH 1/2] dt-bindings: display: simple: Add BOE EV121WXM-N10-1850 panel

2023-02-11 Thread Liu Ying
Add BOE EV121WXM-N10-1850 12.1" WXGA (1280x800) TFT LCD panel
compatible string.  The panel has a LVDS display interface.

The panel's product specification can be found at:
http://www.onetech.com.tw/files/EV121WXM-N10-1850ProductSpecification_20180801.pdf

Signed-off-by: Liu Ying 
---
 .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
index 18241f4051d2..e99306603096 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
@@ -77,6 +77,8 @@ properties:
   - auo,t215hvn01
 # Shanghai AVIC Optoelectronics 7" 1024x600 color TFT-LCD panel
   - avic,tm070ddh03
+# BOE EV121WXM-N10-1850 12.1" WXGA (1280x800) TFT LCD panel
+  - boe,ev121wxm-n10-1850
 # BOE HV070WSA-100 7.01" WSVGA TFT LCD panel
   - boe,hv070wsa-100
 # BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel
-- 
2.37.1



[PATCH 0/2] drm/panel: panel-simple: Add BOE EV121WXM-N10-1850 panel support

2023-02-11 Thread Liu Ying
Hi,

This patch series aims to add BOE EV121WXM-N10-1850 panel support
in the DRM simple panel driver.

Patch 1/2 adds dt-bindings support for the panel.
Patch 2/2 adds the panel support in the DRM simple panel driver.

Liu Ying (2):
  dt-bindings: display: simple: Add BOE EV121WXM-N10-1850 panel
  drm/panel: panel-simple: Add BOE EV121WXM-N10-1850 panel support

 .../bindings/display/panel/panel-simple.yaml  |  2 ++
 drivers/gpu/drm/panel/panel-simple.c  | 33 +++
 2 files changed, 35 insertions(+)

-- 
2.37.1



Re: [PATCH 1/2] dt-bindings: display: bridge: Add NXP i.MX93 parallel display format configuration

2023-01-30 Thread Liu Ying
On Mon, 2023-01-30 at 15:39 -0600, Rob Herring wrote:
> On Mon, Jan 30, 2023 at 04:39:05PM +0800, Liu Ying wrote:
> > On Sun, 2023-01-29 at 12:46 +0100, Krzysztof Kozlowski wrote:
> > > On 28/01/2023 04:47, Liu Ying wrote:
> > > > NXP i.MX93 mediamix blk-ctrl contains one DISPLAY_MUX register
> > > > which
> > > > configures parallel display format by using the
> > > > "PARALLEL_DISP_FORMAT"
> > > > field. Add device tree bindings for the display format
> > > > configuration.
> > > > 
> > > > Signed-off-by: Liu Ying 
> > > > ---
> > > >  .../display/bridge/nxp,imx93-pdfc.yaml| 78
> > > > +++
> > > >  1 file changed, 78 insertions(+)
> > > >  create mode 100644
> > > > Documentation/devicetree/bindings/display/bridge/nxp,imx93-
> > > > pdfc.yaml
> > > > 
> > > > diff --git
> > > > a/Documentation/devicetree/bindings/display/bridge/nxp,imx93-
> > > > pdfc.yaml
> > > > b/Documentation/devicetree/bindings/display/bridge/nxp,imx93-
> > > > pdfc.yaml
> > > > new file mode 100644
> > > > index ..a84bfb46b01d
> > > > --- /dev/null
> > > > +++
> > > > b/Documentation/devicetree/bindings/display/bridge/nxp,imx93-
> > > > pdfc.yaml
> > > > @@ -0,0 +1,78 @@
> > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > +%YAML 1.2
> > > > +---
> > > > +$id: 
> > > > 
https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdisplay%2Fbridge%2Fnxp%2Cimx93-pdfc.yaml%23=05%7C01%7Cvictor.liu%40nxp.com%7C3e8db7ce3170451bc0e208db030a6ad0%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C638107115502467822%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C=c%2BQ%2Bhpov6L9b905ozKPrkWiTzaRD3ZFsEh0urw5evsQ%3D=0
> > > > +$schema: 
> > > > 
https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23=05%7C01%7Cvictor.liu%40nxp.com%7C3e8db7ce3170451bc0e208db030a6ad0%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C638107115502467822%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C=SkPZLJIR9uoqk4mRqSsfu963S%2Baa7xXmyCqzR36LJ30%3D=0
> > > > +
> > > > +title: NXP i.MX93 Parallel Display Format Configuration
> > > > +
> > > > +maintainers:
> > > > +  - Liu Ying 
> > > > +
> > > > +description: |
> > > > +  The i.MX93 mediamix blk-ctrl contains one DISPLAY_MUX
> > > > register
> > > > which
> > > > +  configures parallel display format by using the
> > > > "PARALLEL_DISP_FORMAT"
> > > > +  field.
> > > > +
> > > > +properties:
> > > > +  compatible:
> > > > +const: nxp,imx93-pdfc
> > > 
> > > 
> > > Based on description, I have doubts this is a separate bridge
> > > device.
> > > Why this is not part of display driver/bindings?
> > 
> > The relevant display controller in i.MX93 SoC is LCDIF. From
> > hardware
> > design PoV, the parallel display format configuration logic is not
> > a
> > part of LCDIF. Instead, it's a part of i.MX93 mediamix blk-ctrl.
> > The
> > blk-ctrl includes controls for miscellaneous devices with small
> > logics,
> > like this parallel display format configuration, LVDS Display
> > Bridge(LDB, see fsl,ldb.yaml) and so on. The below pipeline
> > describes
> > data flow of a parallel display LCD panel:
> > 
> > DRAM -> LCDIF -> parallel display format configuration -> LCD panel
> > 
> > So, the parallel display format configuration appears to be a
> > separate
> > bridge.
> > 
> > > 
> > > We do not create usually devices for single registers, because
> > > they
> > > are
> > > not a devices. Devices are a bit more complex - have some pin
> > > inputs/outputs, not a register only. Of course there are
> > > exception,
> > > but
> > > this one does not look like one.
> > 
> > IMHO, this one is a standalone device although it is controlled by
> > one
> > single register. It's input pins connect to LCDIF and output pins
> > connect to i.MX93 SoC's pins/pads.
> 
> Fair enough. It needs to be defined as part of the mediamix blkctrl 
> schema though.

Do you mean that we can keep this schema and need to allow child
devices in fsl,imx93-media-blk-ctrl.yaml?

Cc'ing Peng.

Peng, it appears that you are listed in the maintainers of fsl,imx93-
media-blk-ctrl.yaml. I think it needs to be extended to allow child
devices. Do you consider to do that?

Regards,
Liu Ying

> 
> Rob



  1   2   3   4   5   6   7   8   9   10   >