linux-samsung-soc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge
@ 2021-07-04  9:02 Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 01/17] drm/exynos: dsi: Convert to bridge driver Jagan Teki
                   ` (17 more replies)
  0 siblings, 18 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

This series supports common bridge support for Samsung MIPI DSIM
which is used in Exynos and i.MX8MM SoC's.

The final bridge supports both the Exynos and i.MX8MM DSI devices.

Right now bridge offers two sets of implementations.

A. With component_ops and exynos specific code exclusively for
   exynos dsi drivers and it's legacy bindings.

B. Without componenet_ops for newly implemented bridges and its
   users like i.MX8MM.

The future plan is to fix the implementation A) by dropping
component_ops and fixing exynos specific code in order to make
the bridge more mature to use and the same is mentioned in
drivers TODO.

Patch 0001 - 0006: Bridge conversion
Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions

Tested in Engicam i.Core MX8M Mini SoM.

Anyone interest, please have a look on this repo
https://github.com/openedev/linux/tree/070421-imx8mm-dsim

Would appreciate anyone from the exynos team to test it on
the exynos platform?

Any inputs?
Jagan.

Jagan Teki (17):
  drm/exynos: dsi: Convert to bridge driver
  drm/exynos: dsi: Handle drm_device for bridge
  drm/exynos: dsi: Use the drm_panel_bridge API
  drm/exynos: dsi: Create bridge connector for encoder
  drm/exynos: dsi: Get the mode from bridge
  drm/exynos: dsi: Handle exynos specifics via driver_data
  drm: bridge: Move exynos_drm_dsi into bridges
  dt-bindings: display: bridge: Add Samsung MIPI DSIM bridge
  drm: bridge: samsung-dsim: Add module init, exit
  drm: bridge: samsung-dsim: Update the of_node for port(s)
  drm: bridge: samsung-dsim: Find the possible DSI devices
  dt-bindings: display: bridge: samsung,mipi-dsim: Add i.MX8MM support
  drm: bridge: samsung-dsim: Add i.MX8MM support
  drm: bridge: samsung-dsim: Add input_bus_flags
  drm: bridge: samsung-dsim: Move DSI init in bridge enable
  drm: bridge: samsung-dsim: Fix PLL_P offset
  drm: bridge: samsung-dsim: Add bridge mode_fixup

 .../display/bridge/samsung,mipi-dsim.yaml     | 360 +++++++++
 .../bindings/display/exynos/exynos_dsim.txt   |  90 ---
 MAINTAINERS                                   |  12 +
 drivers/gpu/drm/bridge/Kconfig                |  15 +
 drivers/gpu/drm/bridge/Makefile               |   1 +
 .../samsung-dsim.c}                           | 758 ++++++++++--------
 drivers/gpu/drm/exynos/Kconfig                |   9 -
 drivers/gpu/drm/exynos/Makefile               |   1 -
 8 files changed, 795 insertions(+), 451 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
 delete mode 100644 Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
 rename drivers/gpu/drm/{exynos/exynos_drm_dsi.c => bridge/samsung-dsim.c} (69%)

-- 
2.25.1


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

* [RFC PATCH 01/17] drm/exynos: dsi: Convert to bridge driver
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 02/17] drm/exynos: dsi: Handle drm_device for bridge Jagan Teki
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

DRM bridge drivers have built-in handling of treating
all display pipeline components as bridges.

Convert exynos_drm_dsi to a bridge driver with built-in
encoder support for compatibility with existing component
drivers.

This keeps switching the driver into the bridge in a more
feasible manner.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 57 +++++++++++++++++--------
 1 file changed, 39 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 1d777d8c1a83..90d2ce2c3055 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -257,6 +257,7 @@ struct exynos_dsi {
 	struct drm_connector connector;
 	struct drm_panel *panel;
 	struct list_head bridge_chain;
+	struct drm_bridge bridge;
 	struct drm_bridge *out_bridge;
 	struct device *dev;
 
@@ -287,9 +288,9 @@ struct exynos_dsi {
 #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
 #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
 
-static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e)
+static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b)
 {
-	return container_of(e, struct exynos_dsi, encoder);
+	return container_of(b, struct exynos_dsi, bridge);
 }
 
 enum reg_idx {
@@ -1374,9 +1375,9 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
 	}
 }
 
-static void exynos_dsi_enable(struct drm_encoder *encoder)
+static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
 {
-	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
+	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
 	struct drm_bridge *iter;
 	int ret;
 
@@ -1429,9 +1430,9 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
 	pm_runtime_put(dsi->dev);
 }
 
-static void exynos_dsi_disable(struct drm_encoder *encoder)
+static void exynos_dsi_bridge_disable(struct drm_bridge *bridge)
 {
-	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
+	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
 	struct drm_bridge *iter;
 
 	if (!(dsi->state & DSIM_STATE_ENABLED))
@@ -1494,9 +1495,9 @@ static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs
 	.get_modes = exynos_dsi_get_modes,
 };
 
-static int exynos_dsi_create_connector(struct drm_encoder *encoder)
+static int exynos_dsi_create_connector(struct exynos_dsi *dsi)
 {
-	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
+	struct drm_encoder *encoder = &dsi->encoder;
 	struct drm_connector *connector = &dsi->connector;
 	struct drm_device *drm = encoder->dev;
 	int ret;
@@ -1522,9 +1523,16 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
 	return 0;
 }
 
-static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {
-	.enable = exynos_dsi_enable,
-	.disable = exynos_dsi_disable,
+static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
+				    enum drm_bridge_attach_flags flags)
+{
+	return 0;
+}
+
+static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
+	.enable = exynos_dsi_bridge_enable,
+	.disable = exynos_dsi_bridge_disable,
+	.attach = exynos_dsi_bridge_attach,
 };
 
 MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
@@ -1543,7 +1551,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 		dsi->out_bridge = out_bridge;
 		list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
 	} else {
-		int ret = exynos_dsi_create_connector(encoder);
+		int ret = exynos_dsi_create_connector(dsi);
 
 		if (ret) {
 			DRM_DEV_ERROR(dsi->dev,
@@ -1596,7 +1604,7 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
 
 	if (dsi->panel) {
 		mutex_lock(&drm->mode_config.mutex);
-		exynos_dsi_disable(&dsi->encoder);
+		exynos_dsi_bridge_disable(&dsi->bridge);
 		dsi->panel = NULL;
 		dsi->connector.status = connector_status_disconnected;
 		mutex_unlock(&drm->mode_config.mutex);
@@ -1702,12 +1710,16 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 
 	drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
 
-	drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs);
-
 	ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
 	if (ret < 0)
 		return ret;
 
+	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, 0);
+	if (ret) {
+		drm_encoder_cleanup(&dsi->encoder);
+		return ret;
+	}
+
 	in_bridge_node = of_graph_get_remote_node(dev->of_node, DSI_PORT_IN, 0);
 	if (in_bridge_node) {
 		in_bridge = of_drm_find_bridge(in_bridge_node);
@@ -1723,10 +1735,9 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master,
 				void *data)
 {
 	struct exynos_dsi *dsi = dev_get_drvdata(dev);
-	struct drm_encoder *encoder = &dsi->encoder;
-
-	exynos_dsi_disable(encoder);
 
+	exynos_dsi_bridge_disable(&dsi->bridge);
+	drm_encoder_cleanup(&dsi->encoder);
 	mipi_dsi_host_unregister(&dsi->dsi_host);
 }
 
@@ -1821,6 +1832,12 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(dev);
 
+	dsi->bridge.funcs = &exynos_dsi_bridge_funcs;
+	dsi->bridge.of_node = dev->of_node;
+	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
+
+	drm_bridge_add(&dsi->bridge);
+
 	ret = component_add(dev, &exynos_dsi_component_ops);
 	if (ret)
 		goto err_disable_runtime;
@@ -1835,6 +1852,10 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 
 static int exynos_dsi_remove(struct platform_device *pdev)
 {
+	struct exynos_dsi *dsi = platform_get_drvdata(pdev);
+
+	drm_bridge_remove(&dsi->bridge);
+
 	pm_runtime_disable(&pdev->dev);
 
 	component_del(&pdev->dev, &exynos_dsi_component_ops);
-- 
2.25.1


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

* [RFC PATCH 02/17] drm/exynos: dsi: Handle drm_device for bridge
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 01/17] drm/exynos: dsi: Convert to bridge driver Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 03/17] drm/exynos: dsi: Use the drm_panel_bridge API Jagan Teki
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Now the exynos dsi driver supports bridge and legacy
encoder.

In order to support drm_device in both the implementations
it is required to preserve the drm_device in a private
structure and use it accordingly.

1. encoder case, the bind will assign the drm_device into
   encoder->dev, so preserve the drm_device in the bind call.

2. bridge case, the drm_bridge_attach will assign the
   drm_device into bridge->dev, so preserve the drm_device
   in the bridge_attach function call.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 90d2ce2c3055..d7d60aee465b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -259,6 +259,7 @@ struct exynos_dsi {
 	struct list_head bridge_chain;
 	struct drm_bridge bridge;
 	struct drm_bridge *out_bridge;
+	struct drm_device *drm;
 	struct device *dev;
 
 	void __iomem *reg_base;
@@ -1495,11 +1496,11 @@ static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs
 	.get_modes = exynos_dsi_get_modes,
 };
 
-static int exynos_dsi_create_connector(struct exynos_dsi *dsi)
+static int exynos_dsi_create_connector(struct exynos_dsi *dsi,
+				       struct drm_device *drm)
 {
 	struct drm_encoder *encoder = &dsi->encoder;
 	struct drm_connector *connector = &dsi->connector;
-	struct drm_device *drm = encoder->dev;
 	int ret;
 
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
@@ -1526,6 +1527,10 @@ static int exynos_dsi_create_connector(struct exynos_dsi *dsi)
 static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
 				    enum drm_bridge_attach_flags flags)
 {
+	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
+
+	dsi->drm = bridge->dev;
+
 	return 0;
 }
 
@@ -1542,7 +1547,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 {
 	struct exynos_dsi *dsi = host_to_dsi(host);
 	struct drm_encoder *encoder = &dsi->encoder;
-	struct drm_device *drm = encoder->dev;
+	struct drm_device *drm = dsi->drm;
 	struct drm_bridge *out_bridge;
 
 	out_bridge  = of_drm_find_bridge(device->dev.of_node);
@@ -1551,7 +1556,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 		dsi->out_bridge = out_bridge;
 		list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
 	} else {
-		int ret = exynos_dsi_create_connector(dsi);
+		int ret = exynos_dsi_create_connector(dsi, drm);
 
 		if (ret) {
 			DRM_DEV_ERROR(dsi->dev,
@@ -1600,7 +1605,7 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
 				  struct mipi_dsi_device *device)
 {
 	struct exynos_dsi *dsi = host_to_dsi(host);
-	struct drm_device *drm = dsi->encoder.dev;
+	struct drm_device *drm = dsi->drm;
 
 	if (dsi->panel) {
 		mutex_lock(&drm->mode_config.mutex);
@@ -1728,6 +1733,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 		of_node_put(in_bridge_node);
 	}
 
+	dsi->drm = drm_dev;
+
 	return mipi_dsi_host_register(&dsi->dsi_host);
 }
 
-- 
2.25.1


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

* [RFC PATCH 03/17] drm/exynos: dsi: Use the drm_panel_bridge API
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 01/17] drm/exynos: dsi: Convert to bridge driver Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 02/17] drm/exynos: dsi: Handle drm_device for bridge Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-05 11:47   ` Marek Szyprowski
  2021-07-04  9:02 ` [RFC PATCH 04/17] drm/exynos: dsi: Create bridge connector for encoder Jagan Teki
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Use drm_panel_bridge to replace manual panel and
bridge_chain handling code.

This makes the driver simpler to allow all components
in the display pipeline to be treated as bridges by
cleaning the way to generic connector handling.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 167 ++++--------------------
 1 file changed, 23 insertions(+), 144 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index d7d60aee465b..24f0b082ac6d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -254,9 +254,6 @@ struct exynos_dsi_driver_data {
 struct exynos_dsi {
 	struct drm_encoder encoder;
 	struct mipi_dsi_host dsi_host;
-	struct drm_connector connector;
-	struct drm_panel *panel;
-	struct list_head bridge_chain;
 	struct drm_bridge bridge;
 	struct drm_bridge *out_bridge;
 	struct drm_device *drm;
@@ -287,7 +284,6 @@ struct exynos_dsi {
 };
 
 #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
-#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
 
 static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b)
 {
@@ -1379,7 +1375,6 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
 static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
 {
 	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
-	struct drm_bridge *iter;
 	int ret;
 
 	if (dsi->state & DSIM_STATE_ENABLED)
@@ -1393,134 +1388,51 @@ static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
 
 	dsi->state |= DSIM_STATE_ENABLED;
 
-	if (dsi->panel) {
-		ret = drm_panel_prepare(dsi->panel);
-		if (ret < 0)
-			goto err_put_sync;
-	} else {
-		list_for_each_entry_reverse(iter, &dsi->bridge_chain,
-					    chain_node) {
-			if (iter->funcs->pre_enable)
-				iter->funcs->pre_enable(iter);
-		}
-	}
-
 	exynos_dsi_set_display_mode(dsi);
 	exynos_dsi_set_display_enable(dsi, true);
 
-	if (dsi->panel) {
-		ret = drm_panel_enable(dsi->panel);
-		if (ret < 0)
-			goto err_display_disable;
-	} else {
-		list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
-			if (iter->funcs->enable)
-				iter->funcs->enable(iter);
-		}
-	}
-
 	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
 	return;
-
-err_display_disable:
-	exynos_dsi_set_display_enable(dsi, false);
-	drm_panel_unprepare(dsi->panel);
-
-err_put_sync:
-	dsi->state &= ~DSIM_STATE_ENABLED;
-	pm_runtime_put(dsi->dev);
 }
 
 static void exynos_dsi_bridge_disable(struct drm_bridge *bridge)
 {
 	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
-	struct drm_bridge *iter;
 
 	if (!(dsi->state & DSIM_STATE_ENABLED))
 		return;
 
 	dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
 
-	drm_panel_disable(dsi->panel);
-
-	list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
-		if (iter->funcs->disable)
-			iter->funcs->disable(iter);
-	}
-
 	exynos_dsi_set_display_enable(dsi, false);
-	drm_panel_unprepare(dsi->panel);
-
-	list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
-		if (iter->funcs->post_disable)
-			iter->funcs->post_disable(iter);
-	}
 
 	dsi->state &= ~DSIM_STATE_ENABLED;
 	pm_runtime_put_sync(dsi->dev);
 }
 
-static enum drm_connector_status
-exynos_dsi_detect(struct drm_connector *connector, bool force)
-{
-	return connector->status;
-}
-
-static void exynos_dsi_connector_destroy(struct drm_connector *connector)
+static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi,
+				      struct device_node *node)
 {
-	drm_connector_unregister(connector);
-	drm_connector_cleanup(connector);
-	connector->dev = NULL;
-}
-
-static const struct drm_connector_funcs exynos_dsi_connector_funcs = {
-	.detect = exynos_dsi_detect,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.destroy = exynos_dsi_connector_destroy,
-	.reset = drm_atomic_helper_connector_reset,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static int exynos_dsi_get_modes(struct drm_connector *connector)
-{
-	struct exynos_dsi *dsi = connector_to_dsi(connector);
-
-	if (dsi->panel)
-		return drm_panel_get_modes(dsi->panel, connector);
-
-	return 0;
-}
+	struct drm_bridge *panel_bridge;
+	struct drm_panel *panel;
 
-static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = {
-	.get_modes = exynos_dsi_get_modes,
-};
+	panel_bridge = of_drm_find_bridge(node);
+	if (!panel_bridge) {
+		panel = of_drm_find_panel(node);
+		if (!IS_ERR(panel)) {
+			panel_bridge = drm_panel_bridge_add(panel);
+			if (IS_ERR(panel_bridge))
+				return PTR_ERR(panel_bridge);
+		}
+	}
 
-static int exynos_dsi_create_connector(struct exynos_dsi *dsi,
-				       struct drm_device *drm)
-{
-	struct drm_encoder *encoder = &dsi->encoder;
-	struct drm_connector *connector = &dsi->connector;
-	int ret;
+	of_node_put(node);
 
-	connector->polled = DRM_CONNECTOR_POLL_HPD;
+	dsi->out_bridge = panel_bridge;
 
-	ret = drm_connector_init(drm, connector, &exynos_dsi_connector_funcs,
-				 DRM_MODE_CONNECTOR_DSI);
-	if (ret) {
-		DRM_DEV_ERROR(dsi->dev,
-			      "Failed to initialize connector with drm\n");
-		return ret;
-	}
+	if (!dsi->out_bridge)
+		return -EPROBE_DEFER;
 
-	connector->status = connector_status_disconnected;
-	drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
-	drm_connector_attach_encoder(connector, encoder);
-	if (!drm->registered)
-		return 0;
-
-	connector->funcs->reset(connector);
-	drm_connector_register(connector);
 	return 0;
 }
 
@@ -1531,7 +1443,8 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
 
 	dsi->drm = bridge->dev;
 
-	return 0;
+	return drm_bridge_attach(bridge->encoder, dsi->out_bridge, bridge,
+				 flags);
 }
 
 static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
@@ -1546,32 +1459,12 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 				  struct mipi_dsi_device *device)
 {
 	struct exynos_dsi *dsi = host_to_dsi(host);
-	struct drm_encoder *encoder = &dsi->encoder;
 	struct drm_device *drm = dsi->drm;
-	struct drm_bridge *out_bridge;
-
-	out_bridge  = of_drm_find_bridge(device->dev.of_node);
-	if (out_bridge) {
-		drm_bridge_attach(encoder, out_bridge, NULL, 0);
-		dsi->out_bridge = out_bridge;
-		list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
-	} else {
-		int ret = exynos_dsi_create_connector(dsi, drm);
-
-		if (ret) {
-			DRM_DEV_ERROR(dsi->dev,
-				      "failed to create connector ret = %d\n",
-				      ret);
-			drm_encoder_cleanup(encoder);
-			return ret;
-		}
+	int ret;
 
-		dsi->panel = of_drm_find_panel(device->dev.of_node);
-		if (IS_ERR(dsi->panel))
-			dsi->panel = NULL;
-		else
-			dsi->connector.status = connector_status_connected;
-	}
+	ret = exynos_dsi_panel_or_bridge(dsi, device->dev.of_node);
+	if (ret)
+		return ret;
 
 	/*
 	 * This is a temporary solution and should be made by more generic way.
@@ -1607,19 +1500,6 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
 	struct exynos_dsi *dsi = host_to_dsi(host);
 	struct drm_device *drm = dsi->drm;
 
-	if (dsi->panel) {
-		mutex_lock(&drm->mode_config.mutex);
-		exynos_dsi_bridge_disable(&dsi->bridge);
-		dsi->panel = NULL;
-		dsi->connector.status = connector_status_disconnected;
-		mutex_unlock(&drm->mode_config.mutex);
-	} else {
-		if (dsi->out_bridge->funcs->detach)
-			dsi->out_bridge->funcs->detach(dsi->out_bridge);
-		dsi->out_bridge = NULL;
-		INIT_LIST_HEAD(&dsi->bridge_chain);
-	}
-
 	if (drm->mode_config.poll_enabled)
 		drm_kms_helper_hotplug_event(drm);
 
@@ -1770,7 +1650,6 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 	init_completion(&dsi->completed);
 	spin_lock_init(&dsi->transfer_lock);
 	INIT_LIST_HEAD(&dsi->transfer_list);
-	INIT_LIST_HEAD(&dsi->bridge_chain);
 
 	dsi->dsi_host.ops = &exynos_dsi_ops;
 	dsi->dsi_host.dev = dev;
-- 
2.25.1


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

* [RFC PATCH 04/17] drm/exynos: dsi: Create bridge connector for encoder
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (2 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 03/17] drm/exynos: dsi: Use the drm_panel_bridge API Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 05/17] drm/exynos: dsi: Get the mode from bridge Jagan Teki
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Use drm_bridge_connector_init to create a connector
for display pipelines that use drm_bridge for encoder
implementation.

This allows splitting connector operations across
multiple bridges when necessary, instead of having
the last bridge in the chain creating the connector
and handling all connector operations internally.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 24f0b082ac6d..d828be07c325 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -24,6 +24,7 @@
 #include <video/videomode.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge_connector.h>
 #include <drm/drm_bridge.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_mipi_dsi.h>
@@ -1591,6 +1592,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 	struct drm_device *drm_dev = data;
 	struct device_node *in_bridge_node;
 	struct drm_bridge *in_bridge;
+	struct drm_connector *connector;
 	int ret;
 
 	drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
@@ -1599,12 +1601,22 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 	if (ret < 0)
 		return ret;
 
-	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, 0);
+	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
+				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
 	if (ret) {
 		drm_encoder_cleanup(&dsi->encoder);
 		return ret;
 	}
 
+	connector = drm_bridge_connector_init(drm_dev, &dsi->encoder);
+	if (IS_ERR(connector)) {
+		DRM_DEV_ERROR(dsi->dev, "Unable to create bridge connector\n");
+		drm_encoder_cleanup(&dsi->encoder);
+		return PTR_ERR(connector);
+	}
+
+	drm_connector_attach_encoder(connector, &dsi->encoder);
+
 	in_bridge_node = of_graph_get_remote_node(dev->of_node, DSI_PORT_IN, 0);
 	if (in_bridge_node) {
 		in_bridge = of_drm_find_bridge(in_bridge_node);
-- 
2.25.1


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

* [RFC PATCH 05/17] drm/exynos: dsi: Get the mode from bridge
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (3 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 04/17] drm/exynos: dsi: Create bridge connector for encoder Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-29 13:20   ` Robert Foss
  2021-07-04  9:02 ` [RFC PATCH 06/17] drm/exynos: dsi: Handle exynos specifics via driver_data Jagan Teki
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Now the exynos dsi driver is fully aware of bridge
handling, so get the display mode from bridge, mode_set
API instead of legacy encoder crtc.

This makes bridge usage more efficient instead of relying
on encoder stack.

Add mode_set in drm_bridge_funcs.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index d828be07c325..99a1b8c22313 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -275,6 +275,7 @@ struct exynos_dsi {
 	u32 format;
 
 	int state;
+	struct drm_display_mode mode;
 	struct drm_property *brightness;
 	struct completion completed;
 
@@ -881,7 +882,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
 
 static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)
 {
-	struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode;
+	struct drm_display_mode *m = &dsi->mode;
 	unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;
 	u32 reg;
 
@@ -1411,6 +1412,15 @@ static void exynos_dsi_bridge_disable(struct drm_bridge *bridge)
 	pm_runtime_put_sync(dsi->dev);
 }
 
+static void exynos_dsi_bridge_mode_set(struct drm_bridge *bridge,
+				       const struct drm_display_mode *mode,
+				       const struct drm_display_mode *adjusted_mode)
+{
+	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
+
+	drm_mode_copy(&dsi->mode, adjusted_mode);
+}
+
 static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi,
 				      struct device_node *node)
 {
@@ -1451,6 +1461,7 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
 static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
 	.enable = exynos_dsi_bridge_enable,
 	.disable = exynos_dsi_bridge_disable,
+	.mode_set = exynos_dsi_bridge_mode_set,
 	.attach = exynos_dsi_bridge_attach,
 };
 
-- 
2.25.1


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

* [RFC PATCH 06/17] drm/exynos: dsi: Handle exynos specifics via driver_data
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (4 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 05/17] drm/exynos: dsi: Get the mode from bridge Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
       [not found]   ` <YP2el40V3K4R7ner@ravnborg.org>
  2021-07-04  9:02 ` [RFC PATCH 07/17] drm: bridge: Move exynos_drm_dsi into bridges Jagan Teki
                   ` (11 subsequent siblings)
  17 siblings, 1 reply; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Exynos DSI driver is actually a Samsung MIPI DSIM bridge
IP which is also used in i.MX8MM platforms.

Right now the existing driver has some exynos drm specific
code bases like te_irq, crtc and component_ops.

In order to switch this driver into a common bridge driver
We can see 2 options to handle the exynos specific code.

A. Drop the component_ops, and rework other specifics.
   This may lead to more foundation work as it requires
   more changes in exynos drm drivers stack.

B. Handle the exynos specifics via driver data, and make
   the common bridge work in different platforms and plan
   for option A in future.

So, this patch is trying to add option B) changes to handle
exynos specifics via driver_data.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 37 +++++++++++++++++++------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 99a1b8c22313..53d878d4d2d7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -250,6 +250,7 @@ struct exynos_dsi_driver_data {
 	unsigned int wait_for_reset;
 	unsigned int num_bits_resol;
 	const unsigned int *reg_values;
+	bool exynos_specific;
 };
 
 struct exynos_dsi {
@@ -459,6 +460,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = {
 	.wait_for_reset = 1,
 	.num_bits_resol = 11,
 	.reg_values = reg_values,
+	.exynos_specific = true,
 };
 
 static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
@@ -471,6 +473,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
 	.wait_for_reset = 1,
 	.num_bits_resol = 11,
 	.reg_values = reg_values,
+	.exynos_specific = true,
 };
 
 static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
@@ -481,6 +484,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
 	.wait_for_reset = 1,
 	.num_bits_resol = 11,
 	.reg_values = reg_values,
+	.exynos_specific = true,
 };
 
 static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
@@ -492,6 +496,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
 	.wait_for_reset = 0,
 	.num_bits_resol = 12,
 	.reg_values = exynos5433_reg_values,
+	.exynos_specific = true,
 };
 
 static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
@@ -503,6 +508,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
 	.wait_for_reset = 1,
 	.num_bits_resol = 12,
 	.reg_values = exynos5422_reg_values,
+	.exynos_specific = true,
 };
 
 static const struct of_device_id exynos_dsi_of_match[] = {
@@ -1484,7 +1490,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 	 * If attached panel device is for command mode one, dsi should register
 	 * TE interrupt handler.
 	 */
-	if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
+	if (dsi->driver_data->exynos_specific &&
+	    !(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
 		int ret = exynos_dsi_register_te_irq(dsi, &device->dev);
 		if (ret)
 			return ret;
@@ -1495,8 +1502,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 	dsi->lanes = device->lanes;
 	dsi->format = device->format;
 	dsi->mode_flags = device->mode_flags;
-	exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
-			!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
+	if (dsi->driver_data->exynos_specific)
+		exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
+					    !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
 
 	mutex_unlock(&drm->mode_config.mutex);
 
@@ -1515,7 +1523,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
 	if (drm->mode_config.poll_enabled)
 		drm_kms_helper_hotplug_event(drm);
 
-	exynos_dsi_unregister_te_irq(dsi);
+	if (dsi->driver_data->exynos_specific)
+		exynos_dsi_unregister_te_irq(dsi);
 
 	return 0;
 }
@@ -1737,6 +1746,15 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	if (!dsi->driver_data->exynos_specific) {
+		ret = mipi_dsi_host_register(&dsi->dsi_host);
+		if (ret) {
+			dev_err(dev, "failed to register mipi dsi host: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
 	platform_set_drvdata(pdev, dsi);
 
 	pm_runtime_enable(dev);
@@ -1747,9 +1765,11 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 
 	drm_bridge_add(&dsi->bridge);
 
-	ret = component_add(dev, &exynos_dsi_component_ops);
-	if (ret)
-		goto err_disable_runtime;
+	if (dsi->driver_data->exynos_specific) {
+		ret = component_add(dev, &exynos_dsi_component_ops);
+		if (ret)
+			goto err_disable_runtime;
+	}
 
 	return 0;
 
@@ -1767,7 +1787,8 @@ static int exynos_dsi_remove(struct platform_device *pdev)
 
 	pm_runtime_disable(&pdev->dev);
 
-	component_del(&pdev->dev, &exynos_dsi_component_ops);
+	if (dsi->driver_data->exynos_specific)
+		component_del(&pdev->dev, &exynos_dsi_component_ops);
 
 	return 0;
 }
-- 
2.25.1


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

* [RFC PATCH 07/17] drm: bridge: Move exynos_drm_dsi into bridges
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (5 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 06/17] drm/exynos: dsi: Handle exynos specifics via driver_data Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 08/17] dt-bindings: display: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

The MIPI DSI IP used in Exynos and i.MX8MM are based
Samsung MIPI DSIM bridge.
   
In order to access the common bridge between platforms
the ideal way to push the driver into the bridge area.
   
So, this patch will move the exynos_drm_dsi.c driver
into samsung-dsim.c and do the necessary function name
changes.
   
This would help to improve the bridge driver in future
patches in order to make use of different SoC families
and platforms.

The bridge now support two implementations,

A. With component_ops and exynos specific code exclusively
   for exynos dsi drivers and it's legacy bindings.

B. Without componenet_ops for newly implemented bridges
   and its users like i.MX8MM.

The future plan is to fix the implementation A) by dropping
component_ops and fixing exynos specific code in order to
make the bridge more mature to use.

Updated MAINTAINERS file for this bridge with exynos drm
maintainers along with Andrzej as he is the original author.

Tomasz Figa has been not included in MAINTAINERS as he is
not available via samsung.com.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 MAINTAINERS                                   |  11 +
 drivers/gpu/drm/bridge/Kconfig                |  15 +
 drivers/gpu/drm/bridge/Makefile               |   1 +
 .../samsung-dsim.c}                           | 433 +++++++++---------
 drivers/gpu/drm/exynos/Kconfig                |   9 -
 drivers/gpu/drm/exynos/Makefile               |   1 -
 6 files changed, 246 insertions(+), 224 deletions(-)
 rename drivers/gpu/drm/{exynos/exynos_drm_dsi.c => bridge/samsung-dsim.c} (77%)

diff --git a/MAINTAINERS b/MAINTAINERS
index cae0c6148590..733c2ebc0393 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5864,6 +5864,17 @@ T:	git git://anongit.freedesktop.org/drm/drm-misc
 F:	Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
 F:	drivers/gpu/drm/panel/panel-samsung-db7430.c
 
+DRM DRIVER FOR SAMSUNG MIPI DSIM BRIDGE
+M:	Inki Dae <inki.dae@samsung.com>
+M:	Joonyoung Shim <jy0922.shim@samsung.com>
+M:	Seung-Woo Kim <sw0312.kim@samsung.com>
+M:	Kyungmin Park <kyungmin.park@samsung.com>
+M:	Andrzej Hajda <a.hajda@samsung.com>
+M:	Jagan Teki <jagan@amarulasolutions.com>
+S:	Maintained
+T:	git git://anongit.freedesktop.org/drm/drm-misc
+F:	drivers/gpu/drm/bridge/samsung-dsim.c
+
 DRM DRIVER FOR SITRONIX ST7703 PANELS
 M:	Guido Günther <agx@sigxcpu.org>
 R:	Purism Kernel Team <kernel@puri.sm>
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 4de6dbb8821b..c8a3b13f730b 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -190,6 +190,21 @@ config DRM_PARADE_PS8640
 	  The PS8640 is a high-performance and low-power
 	  MIPI DSI to eDP converter
 
+config DRM_SAMSUNG_DSIM
+	tristate "Samsung MIPI DSIM bridge driver"
+	depends on DRM
+	depends on COMMON_CLK
+	depends on OF && HAS_IOMEM
+	depends on DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || DRM_EXYNOS7_DECON
+	select DRM_KMS_HELPER
+	select DRM_MIPI_DSI
+	select DRM_PANEL_BRIDGE
+	select REGMAP_MMIO
+	help
+	  This enables the Samsung MIPI DSIM bridge controller driver.
+	  This MIPI DSIM bridge can be found it on Exynos and NXP's
+	  i.MX8M Mini and Nano SoC's.
+
 config DRM_SIL_SII8620
 	tristate "Silicon Image SII8620 HDMI/MHL bridge"
 	depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index ec2b9fa2699e..1eb04e4857e5 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
 obj-$(CONFIG_DRM_PARADE_PS8640) += parade-ps8640.o
+obj-$(CONFIG_DRM_SAMSUNG_DSIM) += samsung-dsim.o
 obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
 obj-$(CONFIG_DRM_SII902X) += sii902x.o
 obj-$(CONFIG_DRM_SII9234) += sii9234.o
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/bridge/samsung-dsim.c
similarity index 77%
rename from drivers/gpu/drm/exynos/exynos_drm_dsi.c
rename to drivers/gpu/drm/bridge/samsung-dsim.c
index 53d878d4d2d7..eed6b3ffdea7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1,11 +1,15 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Samsung SoC MIPI DSI Master driver.
+ * Samsung MIPI DSIM bridge driver.
  *
+ * Copyright (C) 2021 Amarula Solutions(India)
  * Copyright (c) 2014 Samsung Electronics Co., Ltd
  *
- * Contacts: Tomasz Figa <t.figa@samsung.com>
-*/
+ * TODO:
+ * - Move or handle exynos specifics in exynos drm drivers stack.
+ * - Try to drop component_ops, but it indeed require to change
+ *   exynos drm drivers stack.
+ */
 
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -33,8 +37,8 @@
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 
-#include "exynos_drm_crtc.h"
-#include "exynos_drm_drv.h"
+#include "../exynos/exynos_drm_crtc.h"
+#include "../exynos/exynos_drm_drv.h"
 
 /* returns true iff both arguments logically differs */
 #define NEQV(a, b) (!(a) ^ !(b))
@@ -217,12 +221,12 @@ static const char *const clk_names[5] = { "bus_clk", "sclk_mipi",
 	"phyclk_mipidphy0_bitclkdiv8", "phyclk_mipidphy0_rxclkesc0",
 	"sclk_rgb_vclk_to_dsim0" };
 
-enum exynos_dsi_transfer_type {
+enum samsung_dsim_transfer_type {
 	EXYNOS_DSI_TX,
 	EXYNOS_DSI_RX,
 };
 
-struct exynos_dsi_transfer {
+struct samsung_dsim_transfer {
 	struct list_head list;
 	struct completion completed;
 	int result;
@@ -240,7 +244,7 @@ struct exynos_dsi_transfer {
 #define DSIM_STATE_CMD_LPM		BIT(2)
 #define DSIM_STATE_VIDOUT_AVAILABLE	BIT(3)
 
-struct exynos_dsi_driver_data {
+struct samsung_dsim_driver_data {
 	const unsigned int *reg_ofs;
 	unsigned int plltmr_reg;
 	unsigned int has_freqband:1;
@@ -253,7 +257,7 @@ struct exynos_dsi_driver_data {
 	bool exynos_specific;
 };
 
-struct exynos_dsi {
+struct samsung_dsim {
 	struct drm_encoder encoder;
 	struct mipi_dsi_host dsi_host;
 	struct drm_bridge bridge;
@@ -283,14 +287,14 @@ struct exynos_dsi {
 	spinlock_t transfer_lock; /* protects transfer_list */
 	struct list_head transfer_list;
 
-	const struct exynos_dsi_driver_data *driver_data;
+	const struct samsung_dsim_driver_data *driver_data;
 };
 
-#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
+#define host_to_dsi(host) container_of(host, struct samsung_dsim, dsi_host)
 
-static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b)
+static inline struct samsung_dsim *bridge_to_dsi(struct drm_bridge *b)
 {
-	return container_of(b, struct exynos_dsi, bridge);
+	return container_of(b, struct samsung_dsim, bridge);
 }
 
 enum reg_idx {
@@ -318,14 +322,14 @@ enum reg_idx {
 	NUM_REGS
 };
 
-static inline void exynos_dsi_write(struct exynos_dsi *dsi, enum reg_idx idx,
-				    u32 val)
+static inline void samsung_dsim_write(struct samsung_dsim *dsi, enum reg_idx idx,
+				      u32 val)
 {
 
 	writel(val, dsi->reg_base + dsi->driver_data->reg_ofs[idx]);
 }
 
-static inline u32 exynos_dsi_read(struct exynos_dsi *dsi, enum reg_idx idx)
+static inline u32 samsung_dsim_read(struct samsung_dsim *dsi, enum reg_idx idx)
 {
 	return readl(dsi->reg_base + dsi->driver_data->reg_ofs[idx]);
 }
@@ -450,7 +454,7 @@ static const unsigned int exynos5433_reg_values[] = {
 	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c),
 };
 
-static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = {
+static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
 	.reg_ofs = exynos_reg_ofs,
 	.plltmr_reg = 0x50,
 	.has_freqband = 1,
@@ -463,7 +467,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = {
 	.exynos_specific = true,
 };
 
-static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
+static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
 	.reg_ofs = exynos_reg_ofs,
 	.plltmr_reg = 0x50,
 	.has_freqband = 1,
@@ -476,7 +480,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
 	.exynos_specific = true,
 };
 
-static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
+static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
 	.reg_ofs = exynos_reg_ofs,
 	.plltmr_reg = 0x58,
 	.num_clks = 2,
@@ -487,7 +491,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
 	.exynos_specific = true,
 };
 
-static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
+static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
 	.reg_ofs = exynos5433_reg_ofs,
 	.plltmr_reg = 0xa0,
 	.has_clklane_stop = 1,
@@ -499,7 +503,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
 	.exynos_specific = true,
 };
 
-static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
+static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
 	.reg_ofs = exynos5433_reg_ofs,
 	.plltmr_reg = 0xa0,
 	.has_clklane_stop = 1,
@@ -511,7 +515,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
 	.exynos_specific = true,
 };
 
-static const struct of_device_id exynos_dsi_of_match[] = {
+static const struct of_device_id samsung_dsim_of_match[] = {
 	{ .compatible = "samsung,exynos3250-mipi-dsi",
 	  .data = &exynos3_dsi_driver_data },
 	{ .compatible = "samsung,exynos4210-mipi-dsi",
@@ -525,7 +529,7 @@ static const struct of_device_id exynos_dsi_of_match[] = {
 	{ }
 };
 
-static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
+static void samsung_dsim_wait_for_reset(struct samsung_dsim *dsi)
 {
 	if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
 		return;
@@ -533,22 +537,22 @@ static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
 	dev_err(dsi->dev, "timeout waiting for reset\n");
 }
 
-static void exynos_dsi_reset(struct exynos_dsi *dsi)
+static void samsung_dsim_reset(struct samsung_dsim *dsi)
 {
 	u32 reset_val = dsi->driver_data->reg_values[RESET_TYPE];
 
 	reinit_completion(&dsi->completed);
-	exynos_dsi_write(dsi, DSIM_SWRST_REG, reset_val);
+	samsung_dsim_write(dsi, DSIM_SWRST_REG, reset_val);
 }
 
 #ifndef MHZ
 #define MHZ	(1000*1000)
 #endif
 
-static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
+static unsigned long samsung_dsim_pll_find_pms(struct samsung_dsim *dsi,
 		unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s)
 {
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
 	unsigned long best_freq = 0;
 	u32 min_delta = 0xffffffff;
 	u8 p_min, p_max;
@@ -599,10 +603,10 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
 	return best_freq;
 }
 
-static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
-					unsigned long freq)
+static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
+					  unsigned long freq)
 {
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
 	unsigned long fin, fout;
 	int timeout;
 	u8 p, s;
@@ -610,7 +614,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
 	u32 reg;
 
 	fin = dsi->pll_clk_rate;
-	fout = exynos_dsi_pll_find_pms(dsi, fin, freq, &p, &m, &s);
+	fout = samsung_dsim_pll_find_pms(dsi, fin, freq, &p, &m, &s);
 	if (!fout) {
 		dev_err(dsi->dev,
 			"failed to find PLL PMS for requested frequency\n");
@@ -641,7 +645,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
 		reg |= DSIM_FREQ_BAND(band);
 	}
 
-	exynos_dsi_write(dsi, DSIM_PLLCTRL_REG, reg);
+	samsung_dsim_write(dsi, DSIM_PLLCTRL_REG, reg);
 
 	timeout = 1000;
 	do {
@@ -649,19 +653,19 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
 			dev_err(dsi->dev, "PLL failed to stabilize\n");
 			return 0;
 		}
-		reg = exynos_dsi_read(dsi, DSIM_STATUS_REG);
+		reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
 	} while ((reg & DSIM_PLL_STABLE) == 0);
 
 	return fout;
 }
 
-static int exynos_dsi_enable_clock(struct exynos_dsi *dsi)
+static int samsung_dsim_enable_clock(struct samsung_dsim *dsi)
 {
 	unsigned long hs_clk, byte_clk, esc_clk;
 	unsigned long esc_div;
 	u32 reg;
 
-	hs_clk = exynos_dsi_set_pll(dsi, dsi->burst_clk_rate);
+	hs_clk = samsung_dsim_set_pll(dsi, dsi->burst_clk_rate);
 	if (!hs_clk) {
 		dev_err(dsi->dev, "failed to configure DSI PLL\n");
 		return -EFAULT;
@@ -679,7 +683,7 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi)
 	dev_dbg(dsi->dev, "hs_clk = %lu, byte_clk = %lu, esc_clk = %lu\n",
 		hs_clk, byte_clk, esc_clk);
 
-	reg = exynos_dsi_read(dsi, DSIM_CLKCTRL_REG);
+	reg = samsung_dsim_read(dsi, DSIM_CLKCTRL_REG);
 	reg &= ~(DSIM_ESC_PRESCALER_MASK | DSIM_LANE_ESC_CLK_EN_CLK
 			| DSIM_LANE_ESC_CLK_EN_DATA_MASK | DSIM_PLL_BYPASS
 			| DSIM_BYTE_CLK_SRC_MASK);
@@ -689,14 +693,14 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi)
 			| DSIM_LANE_ESC_CLK_EN_DATA(BIT(dsi->lanes) - 1)
 			| DSIM_BYTE_CLK_SRC(0)
 			| DSIM_TX_REQUEST_HSCLK;
-	exynos_dsi_write(dsi, DSIM_CLKCTRL_REG, reg);
+	samsung_dsim_write(dsi, DSIM_CLKCTRL_REG, reg);
 
 	return 0;
 }
 
-static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
+static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
 {
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
 	const unsigned int *reg_values = driver_data->reg_values;
 	u32 reg;
 
@@ -706,7 +710,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
 	/* B D-PHY: D-PHY Master & Slave Analog Block control */
 	reg = reg_values[PHYCTRL_ULPS_EXIT] | reg_values[PHYCTRL_VREG_LP] |
 		reg_values[PHYCTRL_SLEW_UP];
-	exynos_dsi_write(dsi, DSIM_PHYCTRL_REG, reg);
+	samsung_dsim_write(dsi, DSIM_PHYCTRL_REG, reg);
 
 	/*
 	 * T LPX: Transmitted length of any Low-Power state period
@@ -714,7 +718,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
 	 *	burst
 	 */
 	reg = reg_values[PHYTIMING_LPX] | reg_values[PHYTIMING_HS_EXIT];
-	exynos_dsi_write(dsi, DSIM_PHYTIMING_REG, reg);
+	samsung_dsim_write(dsi, DSIM_PHYTIMING_REG, reg);
 
 	/*
 	 * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00
@@ -734,7 +738,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
 		reg_values[PHYTIMING_CLK_POST] |
 		reg_values[PHYTIMING_CLK_TRAIL];
 
-	exynos_dsi_write(dsi, DSIM_PHYTIMING1_REG, reg);
+	samsung_dsim_write(dsi, DSIM_PHYTIMING1_REG, reg);
 
 	/*
 	 * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00
@@ -747,47 +751,47 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
 	 */
 	reg = reg_values[PHYTIMING_HS_PREPARE] | reg_values[PHYTIMING_HS_ZERO] |
 		reg_values[PHYTIMING_HS_TRAIL];
-	exynos_dsi_write(dsi, DSIM_PHYTIMING2_REG, reg);
+	samsung_dsim_write(dsi, DSIM_PHYTIMING2_REG, reg);
 }
 
-static void exynos_dsi_disable_clock(struct exynos_dsi *dsi)
+static void samsung_dsim_disable_clock(struct samsung_dsim *dsi)
 {
 	u32 reg;
 
-	reg = exynos_dsi_read(dsi, DSIM_CLKCTRL_REG);
+	reg = samsung_dsim_read(dsi, DSIM_CLKCTRL_REG);
 	reg &= ~(DSIM_LANE_ESC_CLK_EN_CLK | DSIM_LANE_ESC_CLK_EN_DATA_MASK
 			| DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN);
-	exynos_dsi_write(dsi, DSIM_CLKCTRL_REG, reg);
+	samsung_dsim_write(dsi, DSIM_CLKCTRL_REG, reg);
 
-	reg = exynos_dsi_read(dsi, DSIM_PLLCTRL_REG);
+	reg = samsung_dsim_read(dsi, DSIM_PLLCTRL_REG);
 	reg &= ~DSIM_PLL_EN;
-	exynos_dsi_write(dsi, DSIM_PLLCTRL_REG, reg);
+	samsung_dsim_write(dsi, DSIM_PLLCTRL_REG, reg);
 }
 
-static void exynos_dsi_enable_lane(struct exynos_dsi *dsi, u32 lane)
+static void samsung_dsim_enable_lane(struct samsung_dsim *dsi, u32 lane)
 {
-	u32 reg = exynos_dsi_read(dsi, DSIM_CONFIG_REG);
+	u32 reg = samsung_dsim_read(dsi, DSIM_CONFIG_REG);
 	reg |= (DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1) | DSIM_LANE_EN_CLK |
 			DSIM_LANE_EN(lane));
-	exynos_dsi_write(dsi, DSIM_CONFIG_REG, reg);
+	samsung_dsim_write(dsi, DSIM_CONFIG_REG, reg);
 }
 
-static int exynos_dsi_init_link(struct exynos_dsi *dsi)
+static int samsung_dsim_init_link(struct samsung_dsim *dsi)
 {
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
 	int timeout;
 	u32 reg;
 	u32 lanes_mask;
 
 	/* Initialize FIFO pointers */
-	reg = exynos_dsi_read(dsi, DSIM_FIFOCTRL_REG);
+	reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG);
 	reg &= ~0x1f;
-	exynos_dsi_write(dsi, DSIM_FIFOCTRL_REG, reg);
+	samsung_dsim_write(dsi, DSIM_FIFOCTRL_REG, reg);
 
 	usleep_range(9000, 11000);
 
 	reg |= 0x1f;
-	exynos_dsi_write(dsi, DSIM_FIFOCTRL_REG, reg);
+	samsung_dsim_write(dsi, DSIM_FIFOCTRL_REG, reg);
 	usleep_range(9000, 11000);
 
 	/* DSI configuration */
@@ -856,10 +860,10 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
 			dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
 		reg |= DSIM_CLKLANE_STOP;
 	}
-	exynos_dsi_write(dsi, DSIM_CONFIG_REG, reg);
+	samsung_dsim_write(dsi, DSIM_CONFIG_REG, reg);
 
 	lanes_mask = BIT(dsi->lanes) - 1;
-	exynos_dsi_enable_lane(dsi, lanes_mask);
+	samsung_dsim_enable_lane(dsi, lanes_mask);
 
 	/* Check clock and data lane state are stop state */
 	timeout = 100;
@@ -869,24 +873,24 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
 			return -EFAULT;
 		}
 
-		reg = exynos_dsi_read(dsi, DSIM_STATUS_REG);
+		reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
 		if ((reg & DSIM_STOP_STATE_DAT(lanes_mask))
 		    != DSIM_STOP_STATE_DAT(lanes_mask))
 			continue;
 	} while (!(reg & (DSIM_STOP_STATE_CLK | DSIM_TX_READY_HS_CLK)));
 
-	reg = exynos_dsi_read(dsi, DSIM_ESCMODE_REG);
+	reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
 	reg &= ~DSIM_STOP_STATE_CNT_MASK;
 	reg |= DSIM_STOP_STATE_CNT(driver_data->reg_values[STOP_STATE_CNT]);
-	exynos_dsi_write(dsi, DSIM_ESCMODE_REG, reg);
+	samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
 
 	reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff);
-	exynos_dsi_write(dsi, DSIM_TIMEOUT_REG, reg);
+	samsung_dsim_write(dsi, DSIM_TIMEOUT_REG, reg);
 
 	return 0;
 }
 
-static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)
+static void samsung_dsim_set_display_mode(struct samsung_dsim *dsi)
 {
 	struct drm_display_mode *m = &dsi->mode;
 	unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;
@@ -896,42 +900,42 @@ static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)
 		reg = DSIM_CMD_ALLOW(0xf)
 			| DSIM_STABLE_VFP(m->vsync_start - m->vdisplay)
 			| DSIM_MAIN_VBP(m->vtotal - m->vsync_end);
-		exynos_dsi_write(dsi, DSIM_MVPORCH_REG, reg);
+		samsung_dsim_write(dsi, DSIM_MVPORCH_REG, reg);
 
 		reg = DSIM_MAIN_HFP(m->hsync_start - m->hdisplay)
 			| DSIM_MAIN_HBP(m->htotal - m->hsync_end);
-		exynos_dsi_write(dsi, DSIM_MHPORCH_REG, reg);
+		samsung_dsim_write(dsi, DSIM_MHPORCH_REG, reg);
 
 		reg = DSIM_MAIN_VSA(m->vsync_end - m->vsync_start)
 			| DSIM_MAIN_HSA(m->hsync_end - m->hsync_start);
-		exynos_dsi_write(dsi, DSIM_MSYNC_REG, reg);
+		samsung_dsim_write(dsi, DSIM_MSYNC_REG, reg);
 	}
 	reg =  DSIM_MAIN_HRESOL(m->hdisplay, num_bits_resol) |
 		DSIM_MAIN_VRESOL(m->vdisplay, num_bits_resol);
 
-	exynos_dsi_write(dsi, DSIM_MDRESOL_REG, reg);
+	samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg);
 
 	dev_dbg(dsi->dev, "LCD size = %dx%d\n", m->hdisplay, m->vdisplay);
 }
 
-static void exynos_dsi_set_display_enable(struct exynos_dsi *dsi, bool enable)
+static void samsung_dsim_set_display_enable(struct samsung_dsim *dsi, bool enable)
 {
 	u32 reg;
 
-	reg = exynos_dsi_read(dsi, DSIM_MDRESOL_REG);
+	reg = samsung_dsim_read(dsi, DSIM_MDRESOL_REG);
 	if (enable)
 		reg |= DSIM_MAIN_STAND_BY;
 	else
 		reg &= ~DSIM_MAIN_STAND_BY;
-	exynos_dsi_write(dsi, DSIM_MDRESOL_REG, reg);
+	samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg);
 }
 
-static int exynos_dsi_wait_for_hdr_fifo(struct exynos_dsi *dsi)
+static int samsung_dsim_wait_for_hdr_fifo(struct samsung_dsim *dsi)
 {
 	int timeout = 2000;
 
 	do {
-		u32 reg = exynos_dsi_read(dsi, DSIM_FIFOCTRL_REG);
+		u32 reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG);
 
 		if (!(reg & DSIM_SFR_HEADER_FULL))
 			return 0;
@@ -943,27 +947,27 @@ static int exynos_dsi_wait_for_hdr_fifo(struct exynos_dsi *dsi)
 	return -ETIMEDOUT;
 }
 
-static void exynos_dsi_set_cmd_lpm(struct exynos_dsi *dsi, bool lpm)
+static void samsung_dsim_set_cmd_lpm(struct samsung_dsim *dsi, bool lpm)
 {
-	u32 v = exynos_dsi_read(dsi, DSIM_ESCMODE_REG);
+	u32 v = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
 
 	if (lpm)
 		v |= DSIM_CMD_LPDT_LP;
 	else
 		v &= ~DSIM_CMD_LPDT_LP;
 
-	exynos_dsi_write(dsi, DSIM_ESCMODE_REG, v);
+	samsung_dsim_write(dsi, DSIM_ESCMODE_REG, v);
 }
 
-static void exynos_dsi_force_bta(struct exynos_dsi *dsi)
+static void samsung_dsim_force_bta(struct samsung_dsim *dsi)
 {
-	u32 v = exynos_dsi_read(dsi, DSIM_ESCMODE_REG);
+	u32 v = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
 	v |= DSIM_FORCE_BTA;
-	exynos_dsi_write(dsi, DSIM_ESCMODE_REG, v);
+	samsung_dsim_write(dsi, DSIM_ESCMODE_REG, v);
 }
 
-static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi,
-					struct exynos_dsi_transfer *xfer)
+static void samsung_dsim_send_to_fifo(struct samsung_dsim *dsi,
+				      struct samsung_dsim_transfer *xfer)
 {
 	struct device *dev = dsi->dev;
 	struct mipi_dsi_packet *pkt = &xfer->packet;
@@ -983,7 +987,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi,
 	/* Send payload */
 	while (length >= 4) {
 		reg = get_unaligned_le32(payload);
-		exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg);
+		samsung_dsim_write(dsi, DSIM_PAYLOAD_REG, reg);
 		payload += 4;
 		length -= 4;
 	}
@@ -998,7 +1002,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi,
 		fallthrough;
 	case 1:
 		reg |= payload[0];
-		exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg);
+		samsung_dsim_write(dsi, DSIM_PAYLOAD_REG, reg);
 		break;
 	}
 
@@ -1007,25 +1011,25 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi,
 		return;
 
 	reg = get_unaligned_le32(pkt->header);
-	if (exynos_dsi_wait_for_hdr_fifo(dsi)) {
+	if (samsung_dsim_wait_for_hdr_fifo(dsi)) {
 		dev_err(dev, "waiting for header FIFO timed out\n");
 		return;
 	}
 
 	if (NEQV(xfer->flags & MIPI_DSI_MSG_USE_LPM,
 		 dsi->state & DSIM_STATE_CMD_LPM)) {
-		exynos_dsi_set_cmd_lpm(dsi, xfer->flags & MIPI_DSI_MSG_USE_LPM);
+		samsung_dsim_set_cmd_lpm(dsi, xfer->flags & MIPI_DSI_MSG_USE_LPM);
 		dsi->state ^= DSIM_STATE_CMD_LPM;
 	}
 
-	exynos_dsi_write(dsi, DSIM_PKTHDR_REG, reg);
+	samsung_dsim_write(dsi, DSIM_PKTHDR_REG, reg);
 
 	if (xfer->flags & MIPI_DSI_MSG_REQ_ACK)
-		exynos_dsi_force_bta(dsi);
+		samsung_dsim_force_bta(dsi);
 }
 
-static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi,
-					struct exynos_dsi_transfer *xfer)
+static void samsung_dsim_read_from_fifo(struct samsung_dsim *dsi,
+					struct samsung_dsim_transfer *xfer)
 {
 	u8 *payload = xfer->rx_payload + xfer->rx_done;
 	bool first = !xfer->rx_done;
@@ -1034,7 +1038,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi,
 	u32 reg;
 
 	if (first) {
-		reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG);
+		reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG);
 
 		switch (reg & 0x3f) {
 		case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
@@ -1073,7 +1077,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi,
 
 	/* Receive payload */
 	while (length >= 4) {
-		reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG);
+		reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG);
 		payload[0] = (reg >>  0) & 0xff;
 		payload[1] = (reg >>  8) & 0xff;
 		payload[2] = (reg >> 16) & 0xff;
@@ -1083,7 +1087,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi,
 	}
 
 	if (length) {
-		reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG);
+		reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG);
 		switch (length) {
 		case 3:
 			payload[2] = (reg >> 16) & 0xff;
@@ -1102,16 +1106,16 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi,
 clear_fifo:
 	length = DSI_RX_FIFO_SIZE / 4;
 	do {
-		reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG);
+		reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG);
 		if (reg == DSI_RX_FIFO_EMPTY)
 			break;
 	} while (--length);
 }
 
-static void exynos_dsi_transfer_start(struct exynos_dsi *dsi)
+static void samsung_dsim_transfer_start(struct samsung_dsim *dsi)
 {
 	unsigned long flags;
-	struct exynos_dsi_transfer *xfer;
+	struct samsung_dsim_transfer *xfer;
 	bool start = false;
 
 again:
@@ -1123,7 +1127,7 @@ static void exynos_dsi_transfer_start(struct exynos_dsi *dsi)
 	}
 
 	xfer = list_first_entry(&dsi->transfer_list,
-					struct exynos_dsi_transfer, list);
+					struct samsung_dsim_transfer, list);
 
 	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
 
@@ -1132,7 +1136,7 @@ static void exynos_dsi_transfer_start(struct exynos_dsi *dsi)
 		/* waiting for RX */
 		return;
 
-	exynos_dsi_send_to_fifo(dsi, xfer);
+	samsung_dsim_send_to_fifo(dsi, xfer);
 
 	if (xfer->packet.payload_length || xfer->rx_len)
 		return;
@@ -1151,9 +1155,9 @@ static void exynos_dsi_transfer_start(struct exynos_dsi *dsi)
 		goto again;
 }
 
-static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi)
+static bool samsung_dsim_transfer_finish(struct samsung_dsim *dsi)
 {
-	struct exynos_dsi_transfer *xfer;
+	struct samsung_dsim_transfer *xfer;
 	unsigned long flags;
 	bool start = true;
 
@@ -1165,7 +1169,7 @@ static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi)
 	}
 
 	xfer = list_first_entry(&dsi->transfer_list,
-					struct exynos_dsi_transfer, list);
+					struct samsung_dsim_transfer, list);
 
 	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
 
@@ -1178,7 +1182,7 @@ static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi)
 		return true;
 
 	if (xfer->rx_done != xfer->rx_len)
-		exynos_dsi_read_from_fifo(dsi, xfer);
+		samsung_dsim_read_from_fifo(dsi, xfer);
 
 	if (xfer->rx_done != xfer->rx_len)
 		return true;
@@ -1197,8 +1201,8 @@ static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi)
 	return start;
 }
 
-static void exynos_dsi_remove_transfer(struct exynos_dsi *dsi,
-					struct exynos_dsi_transfer *xfer)
+static void samsung_dsim_remove_transfer(struct samsung_dsim *dsi,
+					 struct samsung_dsim_transfer *xfer)
 {
 	unsigned long flags;
 	bool start;
@@ -1207,12 +1211,12 @@ static void exynos_dsi_remove_transfer(struct exynos_dsi *dsi,
 
 	if (!list_empty(&dsi->transfer_list) &&
 	    xfer == list_first_entry(&dsi->transfer_list,
-				     struct exynos_dsi_transfer, list)) {
+				     struct samsung_dsim_transfer, list)) {
 		list_del_init(&xfer->list);
 		start = !list_empty(&dsi->transfer_list);
 		spin_unlock_irqrestore(&dsi->transfer_lock, flags);
 		if (start)
-			exynos_dsi_transfer_start(dsi);
+			samsung_dsim_transfer_start(dsi);
 		return;
 	}
 
@@ -1221,8 +1225,8 @@ static void exynos_dsi_remove_transfer(struct exynos_dsi *dsi,
 	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
 }
 
-static int exynos_dsi_transfer(struct exynos_dsi *dsi,
-					struct exynos_dsi_transfer *xfer)
+static int samsung_dsim_transfer(struct samsung_dsim *dsi,
+				 struct samsung_dsim_transfer *xfer)
 {
 	unsigned long flags;
 	bool stopped;
@@ -1240,13 +1244,13 @@ static int exynos_dsi_transfer(struct exynos_dsi *dsi,
 	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
 
 	if (stopped)
-		exynos_dsi_transfer_start(dsi);
+		samsung_dsim_transfer_start(dsi);
 
 	wait_for_completion_timeout(&xfer->completed,
 				    msecs_to_jiffies(DSI_XFER_TIMEOUT_MS));
 	if (xfer->result == -ETIMEDOUT) {
 		struct mipi_dsi_packet *pkt = &xfer->packet;
-		exynos_dsi_remove_transfer(dsi, xfer);
+		samsung_dsim_remove_transfer(dsi, xfer);
 		dev_err(dsi->dev, "xfer timed out: %*ph %*ph\n", 4, pkt->header,
 			(int)pkt->payload_length, pkt->payload);
 		return -ETIMEDOUT;
@@ -1256,25 +1260,25 @@ static int exynos_dsi_transfer(struct exynos_dsi *dsi,
 	return xfer->result;
 }
 
-static irqreturn_t exynos_dsi_irq(int irq, void *dev_id)
+static irqreturn_t samsung_dsim_irq(int irq, void *dev_id)
 {
-	struct exynos_dsi *dsi = dev_id;
+	struct samsung_dsim *dsi = dev_id;
 	u32 status;
 
-	status = exynos_dsi_read(dsi, DSIM_INTSRC_REG);
+	status = samsung_dsim_read(dsi, DSIM_INTSRC_REG);
 	if (!status) {
 		static unsigned long int j;
 		if (printk_timed_ratelimit(&j, 500))
 			dev_warn(dsi->dev, "spurious interrupt\n");
 		return IRQ_HANDLED;
 	}
-	exynos_dsi_write(dsi, DSIM_INTSRC_REG, status);
+	samsung_dsim_write(dsi, DSIM_INTSRC_REG, status);
 
 	if (status & DSIM_INT_SW_RST_RELEASE) {
 		u32 mask = ~(DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY |
 			DSIM_INT_SFR_HDR_FIFO_EMPTY | DSIM_INT_RX_ECC_ERR |
 			DSIM_INT_SW_RST_RELEASE);
-		exynos_dsi_write(dsi, DSIM_INTMSK_REG, mask);
+		samsung_dsim_write(dsi, DSIM_INTMSK_REG, mask);
 		complete(&dsi->completed);
 		return IRQ_HANDLED;
 	}
@@ -1283,15 +1287,15 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id)
 			DSIM_INT_PLL_STABLE)))
 		return IRQ_HANDLED;
 
-	if (exynos_dsi_transfer_finish(dsi))
-		exynos_dsi_transfer_start(dsi);
+	if (samsung_dsim_transfer_finish(dsi))
+		samsung_dsim_transfer_start(dsi);
 
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id)
+static irqreturn_t samsung_dsim_te_irq_handler(int irq, void *dev_id)
 {
-	struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id;
+	struct samsung_dsim *dsi = (struct samsung_dsim *)dev_id;
 	struct drm_encoder *encoder = &dsi->encoder;
 
 	if (dsi->state & DSIM_STATE_VIDOUT_AVAILABLE)
@@ -1300,7 +1304,7 @@ static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static void exynos_dsi_enable_irq(struct exynos_dsi *dsi)
+static void samsung_dsim_enable_irq(struct samsung_dsim *dsi)
 {
 	enable_irq(dsi->irq);
 
@@ -1308,7 +1312,7 @@ static void exynos_dsi_enable_irq(struct exynos_dsi *dsi)
 		enable_irq(gpio_to_irq(dsi->te_gpio));
 }
 
-static void exynos_dsi_disable_irq(struct exynos_dsi *dsi)
+static void samsung_dsim_disable_irq(struct samsung_dsim *dsi)
 {
 	if (gpio_is_valid(dsi->te_gpio))
 		disable_irq(gpio_to_irq(dsi->te_gpio));
@@ -1316,27 +1320,27 @@ static void exynos_dsi_disable_irq(struct exynos_dsi *dsi)
 	disable_irq(dsi->irq);
 }
 
-static int exynos_dsi_init(struct exynos_dsi *dsi)
+static int samsung_dsim_init(struct samsung_dsim *dsi)
 {
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
 
-	exynos_dsi_reset(dsi);
-	exynos_dsi_enable_irq(dsi);
+	samsung_dsim_reset(dsi);
+	samsung_dsim_enable_irq(dsi);
 
 	if (driver_data->reg_values[RESET_TYPE] == DSIM_FUNCRST)
-		exynos_dsi_enable_lane(dsi, BIT(dsi->lanes) - 1);
+		samsung_dsim_enable_lane(dsi, BIT(dsi->lanes) - 1);
 
-	exynos_dsi_enable_clock(dsi);
+	samsung_dsim_enable_clock(dsi);
 	if (driver_data->wait_for_reset)
-		exynos_dsi_wait_for_reset(dsi);
-	exynos_dsi_set_phy_ctrl(dsi);
-	exynos_dsi_init_link(dsi);
+		samsung_dsim_wait_for_reset(dsi);
+	samsung_dsim_set_phy_ctrl(dsi);
+	samsung_dsim_init_link(dsi);
 
 	return 0;
 }
 
-static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi,
-				      struct device *panel)
+static int samsung_dsim_register_te_irq(struct samsung_dsim *dsi,
+					struct device *panel)
 {
 	int ret;
 	int te_gpio_irq;
@@ -1359,7 +1363,7 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi,
 
 	te_gpio_irq = gpio_to_irq(dsi->te_gpio);
 
-	ret = request_threaded_irq(te_gpio_irq, exynos_dsi_te_irq_handler, NULL,
+	ret = request_threaded_irq(te_gpio_irq, samsung_dsim_te_irq_handler, NULL,
 				   IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN, "TE", dsi);
 	if (ret) {
 		dev_err(dsi->dev, "request interrupt failed with %d\n", ret);
@@ -1371,7 +1375,7 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi,
 	return ret;
 }
 
-static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
+static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi)
 {
 	if (gpio_is_valid(dsi->te_gpio)) {
 		free_irq(gpio_to_irq(dsi->te_gpio), dsi);
@@ -1380,9 +1384,9 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
 	}
 }
 
-static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
+static void samsung_dsim_bridge_enable(struct drm_bridge *bridge)
 {
-	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
 	int ret;
 
 	if (dsi->state & DSIM_STATE_ENABLED)
@@ -1396,39 +1400,39 @@ static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
 
 	dsi->state |= DSIM_STATE_ENABLED;
 
-	exynos_dsi_set_display_mode(dsi);
-	exynos_dsi_set_display_enable(dsi, true);
+	samsung_dsim_set_display_mode(dsi);
+	samsung_dsim_set_display_enable(dsi, true);
 
 	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
 	return;
 }
 
-static void exynos_dsi_bridge_disable(struct drm_bridge *bridge)
+static void samsung_dsim_bridge_disable(struct drm_bridge *bridge)
 {
-	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
 
 	if (!(dsi->state & DSIM_STATE_ENABLED))
 		return;
 
 	dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
 
-	exynos_dsi_set_display_enable(dsi, false);
+	samsung_dsim_set_display_enable(dsi, false);
 
 	dsi->state &= ~DSIM_STATE_ENABLED;
 	pm_runtime_put_sync(dsi->dev);
 }
 
-static void exynos_dsi_bridge_mode_set(struct drm_bridge *bridge,
-				       const struct drm_display_mode *mode,
-				       const struct drm_display_mode *adjusted_mode)
+static void samsung_dsim_bridge_mode_set(struct drm_bridge *bridge,
+					 const struct drm_display_mode *mode,
+					 const struct drm_display_mode *adjusted_mode)
 {
-	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
 
 	drm_mode_copy(&dsi->mode, adjusted_mode);
 }
 
-static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi,
-				      struct device_node *node)
+static int samsung_dsim_panel_or_bridge(struct samsung_dsim *dsi,
+					struct device_node *node)
 {
 	struct drm_bridge *panel_bridge;
 	struct drm_panel *panel;
@@ -1453,10 +1457,10 @@ static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi,
 	return 0;
 }
 
-static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
-				    enum drm_bridge_attach_flags flags)
+static int samsung_dsim_bridge_attach(struct drm_bridge *bridge,
+				      enum drm_bridge_attach_flags flags)
 {
-	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
 
 	dsi->drm = bridge->dev;
 
@@ -1464,23 +1468,23 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
 				 flags);
 }
 
-static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
-	.enable = exynos_dsi_bridge_enable,
-	.disable = exynos_dsi_bridge_disable,
-	.mode_set = exynos_dsi_bridge_mode_set,
-	.attach = exynos_dsi_bridge_attach,
+static const struct drm_bridge_funcs samsung_dsim_bridge_funcs = {
+	.enable = samsung_dsim_bridge_enable,
+	.disable = samsung_dsim_bridge_disable,
+	.mode_set = samsung_dsim_bridge_mode_set,
+	.attach = samsung_dsim_bridge_attach,
 };
 
-MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
+MODULE_DEVICE_TABLE(of, samsung_dsim_of_match);
 
-static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
-				  struct mipi_dsi_device *device)
+static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
+				    struct mipi_dsi_device *device)
 {
-	struct exynos_dsi *dsi = host_to_dsi(host);
+	struct samsung_dsim *dsi = host_to_dsi(host);
 	struct drm_device *drm = dsi->drm;
 	int ret;
 
-	ret = exynos_dsi_panel_or_bridge(dsi, device->dev.of_node);
+	ret = samsung_dsim_panel_or_bridge(dsi, device->dev.of_node);
 	if (ret)
 		return ret;
 
@@ -1492,7 +1496,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 	 */
 	if (dsi->driver_data->exynos_specific &&
 	    !(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
-		int ret = exynos_dsi_register_te_irq(dsi, &device->dev);
+		int ret = samsung_dsim_register_te_irq(dsi, &device->dev);
 		if (ret)
 			return ret;
 	}
@@ -1514,33 +1518,33 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 	return 0;
 }
 
-static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
-				  struct mipi_dsi_device *device)
+static int samsung_dsim_host_detach(struct mipi_dsi_host *host,
+				    struct mipi_dsi_device *device)
 {
-	struct exynos_dsi *dsi = host_to_dsi(host);
+	struct samsung_dsim *dsi = host_to_dsi(host);
 	struct drm_device *drm = dsi->drm;
 
 	if (drm->mode_config.poll_enabled)
 		drm_kms_helper_hotplug_event(drm);
 
 	if (dsi->driver_data->exynos_specific)
-		exynos_dsi_unregister_te_irq(dsi);
+		samsung_dsim_unregister_te_irq(dsi);
 
 	return 0;
 }
 
-static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
-					 const struct mipi_dsi_msg *msg)
+static ssize_t samsung_dsim_host_transfer(struct mipi_dsi_host *host,
+					  const struct mipi_dsi_msg *msg)
 {
-	struct exynos_dsi *dsi = host_to_dsi(host);
-	struct exynos_dsi_transfer xfer;
+	struct samsung_dsim *dsi = host_to_dsi(host);
+	struct samsung_dsim_transfer xfer;
 	int ret;
 
 	if (!(dsi->state & DSIM_STATE_ENABLED))
 		return -EINVAL;
 
 	if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
-		ret = exynos_dsi_init(dsi);
+		ret = samsung_dsim_init(dsi);
 		if (ret)
 			return ret;
 		dsi->state |= DSIM_STATE_INITIALIZED;
@@ -1554,18 +1558,18 @@ static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
 	xfer.rx_payload = msg->rx_buf;
 	xfer.flags = msg->flags;
 
-	ret = exynos_dsi_transfer(dsi, &xfer);
+	ret = samsung_dsim_transfer(dsi, &xfer);
 	return (ret < 0) ? ret : xfer.rx_done;
 }
 
-static const struct mipi_dsi_host_ops exynos_dsi_ops = {
-	.attach = exynos_dsi_host_attach,
-	.detach = exynos_dsi_host_detach,
-	.transfer = exynos_dsi_host_transfer,
+static const struct mipi_dsi_host_ops samsung_dsim_ops = {
+	.attach = samsung_dsim_host_attach,
+	.detach = samsung_dsim_host_detach,
+	.transfer = samsung_dsim_host_transfer,
 };
 
-static int exynos_dsi_of_read_u32(const struct device_node *np,
-				  const char *propname, u32 *out_value)
+static int samsung_dsim_of_read_u32(const struct device_node *np,
+				    const char *propname, u32 *out_value)
 {
 	int ret = of_property_read_u32(np, propname, out_value);
 
@@ -1580,23 +1584,23 @@ enum {
 	DSI_PORT_OUT
 };
 
-static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
+static int samsung_dsim_parse_dt(struct samsung_dsim *dsi)
 {
 	struct device *dev = dsi->dev;
 	struct device_node *node = dev->of_node;
 	int ret;
 
-	ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency",
+	ret = samsung_dsim_of_read_u32(node, "samsung,pll-clock-frequency",
 				     &dsi->pll_clk_rate);
 	if (ret < 0)
 		return ret;
 
-	ret = exynos_dsi_of_read_u32(node, "samsung,burst-clock-frequency",
+	ret = samsung_dsim_of_read_u32(node, "samsung,burst-clock-frequency",
 				     &dsi->burst_clk_rate);
 	if (ret < 0)
 		return ret;
 
-	ret = exynos_dsi_of_read_u32(node, "samsung,esc-clock-frequency",
+	ret = samsung_dsim_of_read_u32(node, "samsung,esc-clock-frequency",
 				     &dsi->esc_clk_rate);
 	if (ret < 0)
 		return ret;
@@ -1604,10 +1608,10 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
 	return 0;
 }
 
-static int exynos_dsi_bind(struct device *dev, struct device *master,
-				void *data)
+static int samsung_dsim_bind(struct device *dev, struct device *master,
+			     void *data)
 {
-	struct exynos_dsi *dsi = dev_get_drvdata(dev);
+	struct samsung_dsim *dsi = dev_get_drvdata(dev);
 	struct drm_encoder *encoder = &dsi->encoder;
 	struct drm_device *drm_dev = data;
 	struct device_node *in_bridge_node;
@@ -1650,26 +1654,26 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 	return mipi_dsi_host_register(&dsi->dsi_host);
 }
 
-static void exynos_dsi_unbind(struct device *dev, struct device *master,
+static void samsung_dsim_unbind(struct device *dev, struct device *master,
 				void *data)
 {
-	struct exynos_dsi *dsi = dev_get_drvdata(dev);
+	struct samsung_dsim *dsi = dev_get_drvdata(dev);
 
-	exynos_dsi_bridge_disable(&dsi->bridge);
+	samsung_dsim_bridge_disable(&dsi->bridge);
 	drm_encoder_cleanup(&dsi->encoder);
 	mipi_dsi_host_unregister(&dsi->dsi_host);
 }
 
-static const struct component_ops exynos_dsi_component_ops = {
-	.bind	= exynos_dsi_bind,
-	.unbind	= exynos_dsi_unbind,
+static const struct component_ops samsung_dsim_component_ops = {
+	.bind	= samsung_dsim_bind,
+	.unbind	= samsung_dsim_unbind,
 };
 
-static int exynos_dsi_probe(struct platform_device *pdev)
+static int samsung_dsim_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct resource *res;
-	struct exynos_dsi *dsi;
+	struct samsung_dsim *dsi;
 	int ret, i;
 
 	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
@@ -1683,7 +1687,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 	spin_lock_init(&dsi->transfer_lock);
 	INIT_LIST_HEAD(&dsi->transfer_list);
 
-	dsi->dsi_host.ops = &exynos_dsi_ops;
+	dsi->dsi_host.ops = &samsung_dsim_ops;
 	dsi->dsi_host.dev = dev;
 
 	dsi->dev = dev;
@@ -1734,7 +1738,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 		return dsi->irq;
 
 	ret = devm_request_threaded_irq(dev, dsi->irq, NULL,
-					exynos_dsi_irq,
+					samsung_dsim_irq,
 					IRQF_ONESHOT | IRQF_NO_AUTOEN,
 					dev_name(dev), dsi);
 	if (ret) {
@@ -1742,7 +1746,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = exynos_dsi_parse_dt(dsi);
+	ret = samsung_dsim_parse_dt(dsi);
 	if (ret)
 		return ret;
 
@@ -1759,14 +1763,14 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(dev);
 
-	dsi->bridge.funcs = &exynos_dsi_bridge_funcs;
+	dsi->bridge.funcs = &samsung_dsim_bridge_funcs;
 	dsi->bridge.of_node = dev->of_node;
 	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 
 	drm_bridge_add(&dsi->bridge);
 
 	if (dsi->driver_data->exynos_specific) {
-		ret = component_add(dev, &exynos_dsi_component_ops);
+		ret = component_add(dev, &samsung_dsim_component_ops);
 		if (ret)
 			goto err_disable_runtime;
 	}
@@ -1779,24 +1783,24 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int exynos_dsi_remove(struct platform_device *pdev)
+static int samsung_dsim_remove(struct platform_device *pdev)
 {
-	struct exynos_dsi *dsi = platform_get_drvdata(pdev);
+	struct samsung_dsim *dsi = platform_get_drvdata(pdev);
 
 	drm_bridge_remove(&dsi->bridge);
 
 	pm_runtime_disable(&pdev->dev);
 
 	if (dsi->driver_data->exynos_specific)
-		component_del(&pdev->dev, &exynos_dsi_component_ops);
+		component_del(&pdev->dev, &samsung_dsim_component_ops);
 
 	return 0;
 }
 
-static int __maybe_unused exynos_dsi_suspend(struct device *dev)
+static int __maybe_unused samsung_dsim_suspend(struct device *dev)
 {
-	struct exynos_dsi *dsi = dev_get_drvdata(dev);
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	struct samsung_dsim *dsi = dev_get_drvdata(dev);
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
 	int ret, i;
 
 	usleep_range(10000, 20000);
@@ -1804,9 +1808,9 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev)
 	if (dsi->state & DSIM_STATE_INITIALIZED) {
 		dsi->state &= ~DSIM_STATE_INITIALIZED;
 
-		exynos_dsi_disable_clock(dsi);
+		samsung_dsim_disable_clock(dsi);
 
-		exynos_dsi_disable_irq(dsi);
+		samsung_dsim_disable_irq(dsi);
 	}
 
 	dsi->state &= ~DSIM_STATE_CMD_LPM;
@@ -1823,10 +1827,10 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev)
 	return 0;
 }
 
-static int __maybe_unused exynos_dsi_resume(struct device *dev)
+static int __maybe_unused samsung_dsim_resume(struct device *dev)
 {
-	struct exynos_dsi *dsi = dev_get_drvdata(dev);
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	struct samsung_dsim *dsi = dev_get_drvdata(dev);
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
 	int ret, i;
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
@@ -1857,24 +1861,25 @@ static int __maybe_unused exynos_dsi_resume(struct device *dev)
 	return ret;
 }
 
-static const struct dev_pm_ops exynos_dsi_pm_ops = {
-	SET_RUNTIME_PM_OPS(exynos_dsi_suspend, exynos_dsi_resume, NULL)
+static const struct dev_pm_ops samsung_dsim_pm_ops = {
+	SET_RUNTIME_PM_OPS(samsung_dsim_suspend, samsung_dsim_resume, NULL)
 	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
 				pm_runtime_force_resume)
 };
 
 struct platform_driver dsi_driver = {
-	.probe = exynos_dsi_probe,
-	.remove = exynos_dsi_remove,
+	.probe = samsung_dsim_probe,
+	.remove = samsung_dsim_remove,
 	.driver = {
-		   .name = "exynos-dsi",
+		   .name = "samsung-dsim",
 		   .owner = THIS_MODULE,
-		   .pm = &exynos_dsi_pm_ops,
-		   .of_match_table = exynos_dsi_of_match,
+		   .pm = &samsung_dsim_pm_ops,
+		   .of_match_table = samsung_dsim_of_match,
 	},
 };
 
 MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC MIPI DSI Master");
+MODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>");
+MODULE_DESCRIPTION("Samsung MIPI DSIM bridge");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 6a251e3aa779..6bcd0fe03c70 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -53,15 +53,6 @@ config DRM_EXYNOS_DPI
 	help
 	  This enables support for Exynos parallel output.
 
-config DRM_EXYNOS_DSI
-	bool "MIPI-DSI host"
-	depends on DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || DRM_EXYNOS7_DECON
-	select DRM_MIPI_DSI
-	select DRM_PANEL
-	default n
-	help
-	  This enables support for Exynos MIPI-DSI device.
-
 config DRM_EXYNOS_DP
 	bool "Exynos specific extensions for Analogix DP driver"
 	depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 2fd2f3ee4fcf..04832f92051d 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -11,7 +11,6 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)	+= exynos_drm_fimd.o
 exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON)	+= exynos5433_drm_decon.o
 exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON)	+= exynos7_drm_decon.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DPI)	+= exynos_drm_dpi.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_DSI)	+= exynos_drm_dsi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DP)	+= exynos_dp.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_MIXER)	+= exynos_mixer.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o
-- 
2.25.1


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

* [RFC PATCH 08/17] dt-bindings: display: bridge: Add Samsung MIPI DSIM bridge
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (6 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 07/17] drm: bridge: Move exynos_drm_dsi into bridges Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-12 15:13   ` Rob Herring
  2021-07-04  9:02 ` [RFC PATCH 09/17] drm: bridge: samsung-dsim: Add module init, exit Jagan Teki
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki, Rob Herring

Samsing MIPI DSIM bridge can be found on Exynos and NXP's
i.MX8M Mini and Nano SoC's.

This dt-bindings replaces legacy exynos_dsim.txt.

Used the example node from latest Exynos SoC instead of
the one used in legacy exynos_dsim.txt.

Add dt-bingings for it.

Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 .../display/bridge/samsung,mipi-dsim.yaml     | 278 ++++++++++++++++++
 .../bindings/display/exynos/exynos_dsim.txt   |  90 ------
 MAINTAINERS                                   |   1 +
 3 files changed, 279 insertions(+), 90 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
 delete mode 100644 Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt

diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
new file mode 100644
index 000000000000..b2970734ffd7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
@@ -0,0 +1,278 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/samsung,mipi-dsim.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung MIPI DSIM bridge controller
+
+maintainers:
+  - Inki Dae <inki.dae@samsung.com>
+  - Joonyoung Shim <jy0922.shim@samsung.com>
+  - Seung-Woo Kim <sw0312.kim@samsung.com>
+  - Kyungmin Park <kyungmin.park@samsung.com>
+  - Andrzej Hajda <a.hajda@samsung.com>
+  - Jagan Teki <jagan@amarulasolutions.com>
+
+description: |
+  Samsung MIPI DSIM bridge controller can be found it on Exynos
+  and i.MX8M Mini and Nano SoC's.
+
+properties:
+  compatible:
+    enum:
+      - samsung,exynos3250-mipi-dsi
+      - samsung,exynos4210-mipi-dsi
+      - samsung,exynos5410-mipi-dsi
+      - samsung,exynos5422-mipi-dsi
+      - samsung,exynos5433-mipi-dsi
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  clocks:
+    minItems: 2
+    maxItems: 5
+
+  clock-names:
+    minItems: 2
+    maxItems: 5
+
+  phys:
+    maxItems: 1
+    description: phandle to the phy module representing the DPHY
+
+  phy-names:
+    items:
+      - const: dsim
+
+  samsung,phy-type:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: phandle to the samsung phy-type
+
+  power-domains:
+    description: phandle to the associated power domain
+    maxItems: 1
+
+  samsung,power-domain:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the associated samsung power domain
+    maxItems: 1
+
+  vddcore-supply:
+    description: MIPI DSIM Core voltage supply (e.g. 1.1V)
+
+  vddio-supply:
+    description: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
+
+  samsung,burst-clock-frequency:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      DSIM high speed burst mode frequency.
+
+  samsung,esc-clock-frequency:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      DSIM escape mode frequency.
+
+  samsung,pll-clock-frequency:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      DSIM oscillator clock frequency.
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        description:
+          Input port node to receive pixel data from the
+          display controller. Exactly one endpoint must be
+          specified.
+        properties:
+          endpoint@0:
+            $ref: /schemas/graph.yaml#/properties/endpoint
+            description: sub-node describing the input from MIC
+
+        unevaluatedProperties: false
+
+      port@1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description:
+          DSI output port node to the panel or the next bridge
+          in the chain
+
+required:
+  - '#address-cells'
+  - '#size-cells'
+  - clock-names
+  - clocks
+  - compatible
+  - interrupts
+  - phy-names
+  - phys
+  - reg
+  - samsung,burst-clock-frequency
+  - samsung,esc-clock-frequency
+  - samsung,pll-clock-frequency
+
+allOf:
+  - $ref: ../dsi-controller.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,exynos5433-mipi-dsi
+
+    then:
+      properties:
+        clocks:
+          minItems: 5
+
+        clock-names:
+          items:
+            - const: bus_clk
+            - const: phyclk_mipidphy0_bitclkdiv8
+            - const: phyclk_mipidphy0_rxclkesc0
+            - const: sclk_rgb_vclk_to_dsim0
+            - const: sclk_mipi
+
+        ports:
+          required:
+            - port@0
+
+      required:
+        - ports
+        - vddcore-supply
+        - vddio-supply
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,exynos5410-mipi-dsi
+
+    then:
+      properties:
+        clocks:
+          minItems: 2
+
+        clock-names:
+          items:
+            - const: bus_clk
+            - const: pll_clk
+
+      required:
+        - vddcore-supply
+        - vddio-supply
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,exynos4210-mipi-dsi
+
+    then:
+      properties:
+        clocks:
+          minItems: 2
+
+        clock-names:
+          items:
+            - const: bus_clk
+            - const: sclk_mipi
+
+      required:
+        - vddcore-supply
+        - vddio-supply
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,exynos3250-mipi-dsi
+
+    then:
+      properties:
+        clocks:
+          minItems: 2
+
+        clock-names:
+          items:
+            - const: bus_clk
+            - const: pll_clk
+
+      required:
+        - vddcore-supply
+        - vddio-supply
+        - samsung,phy-type
+
+additionalProperties:
+  type: object
+
+examples:
+  - |
+    #include <dt-bindings/clock/exynos5433.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    dsi@13900000 {
+       compatible = "samsung,exynos5433-mipi-dsi";
+       reg = <0x13900000 0xC0>;
+       interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
+       phys = <&mipi_phy 1>;
+       phy-names = "dsim";
+       clocks = <&cmu_disp CLK_PCLK_DSIM0>,
+                <&cmu_disp CLK_PHYCLK_MIPIDPHY0_BITCLKDIV8>,
+                <&cmu_disp CLK_PHYCLK_MIPIDPHY0_RXCLKESC0>,
+                <&cmu_disp CLK_SCLK_RGB_VCLK_TO_DSIM0>,
+                <&cmu_disp CLK_SCLK_DSIM0>;
+       clock-names = "bus_clk",
+                     "phyclk_mipidphy0_bitclkdiv8",
+                     "phyclk_mipidphy0_rxclkesc0",
+                     "sclk_rgb_vclk_to_dsim0",
+                     "sclk_mipi";
+       power-domains = <&pd_disp>;
+       vddcore-supply = <&ldo6_reg>;
+       vddio-supply = <&ldo7_reg>;
+       samsung,burst-clock-frequency = <512000000>;
+       samsung,esc-clock-frequency = <16000000>;
+       samsung,pll-clock-frequency = <24000000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&te_irq>;
+       status = "disabled";
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       panel@0 {
+          compatible = "samsung,s6e3ha2";
+          reg = <0>;
+          vdd3-supply = <&ldo27_reg>;
+          vci-supply = <&ldo28_reg>;
+          reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
+          enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
+       };
+
+       ports {
+          #address-cells = <1>;
+          #size-cells = <0>;
+
+          port@0 {
+             reg = <0>;
+
+             dsi_to_mic: endpoint {
+                remote-endpoint = <&mic_to_dsi>;
+             };
+          };
+       };
+    };
diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
deleted file mode 100644
index be377786e8cd..000000000000
--- a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-Exynos MIPI DSI Master
-
-Required properties:
-  - compatible: value should be one of the following
-		"samsung,exynos3250-mipi-dsi" /* for Exynos3250/3472 SoCs */
-		"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
-		"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
-		"samsung,exynos5422-mipi-dsi" /* for Exynos5422/5800 SoCs */
-		"samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
-  - reg: physical base address and length of the registers set for the device
-  - interrupts: should contain DSI interrupt
-  - clocks: list of clock specifiers, must contain an entry for each required
-    entry in clock-names
-  - clock-names: should include "bus_clk"and "sclk_mipi" entries
-		 the use of "pll_clk" is deprecated
-  - phys: list of phy specifiers, must contain an entry for each required
-    entry in phy-names
-  - phy-names: should include "dsim" entry
-  - vddcore-supply: MIPI DSIM Core voltage supply (e.g. 1.1V)
-  - vddio-supply: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
-  - samsung,pll-clock-frequency: specifies frequency of the oscillator clock
-  - #address-cells, #size-cells: should be set respectively to <1> and <0>
-    according to DSI host bindings (see MIPI DSI bindings [1])
-  - samsung,burst-clock-frequency: specifies DSI frequency in high-speed burst
-    mode
-  - samsung,esc-clock-frequency: specifies DSI frequency in escape mode
-
-Optional properties:
-  - power-domains: a phandle to DSIM power domain node
-
-Child nodes:
-  Should contain DSI peripheral nodes (see MIPI DSI bindings [1]).
-
-Video interfaces:
-  Device node can contain following video interface port nodes according to [2]:
-  0: RGB input,
-  1: DSI output
-
-[1]: Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
-[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
-
-Example:
-
-	dsi@11c80000 {
-		compatible = "samsung,exynos4210-mipi-dsi";
-		reg = <0x11C80000 0x10000>;
-		interrupts = <0 79 0>;
-		clocks = <&clock 286>, <&clock 143>;
-		clock-names = "bus_clk", "sclk_mipi";
-		phys = <&mipi_phy 1>;
-		phy-names = "dsim";
-		vddcore-supply = <&vusb_reg>;
-		vddio-supply = <&vmipi_reg>;
-		power-domains = <&pd_lcd0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		samsung,pll-clock-frequency = <24000000>;
-
-		panel@1 {
-			reg = <0>;
-			...
-			port {
-				panel_ep: endpoint {
-					remote-endpoint = <&dsi_ep>;
-				};
-			};
-		};
-
-		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			port@0 {
-				reg = <0>;
-				decon_to_mic: endpoint {
-					remote-endpoint = <&mic_to_decon>;
-				};
-			};
-
-			port@1 {
-				reg = <1>;
-				dsi_ep: endpoint {
-					reg = <0>;
-					samsung,burst-clock-frequency = <500000000>;
-					samsung,esc-clock-frequency = <20000000>;
-					remote-endpoint = <&panel_ep>;
-				};
-			};
-		};
-	};
diff --git a/MAINTAINERS b/MAINTAINERS
index 733c2ebc0393..e571fc7792aa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5873,6 +5873,7 @@ M:	Andrzej Hajda <a.hajda@samsung.com>
 M:	Jagan Teki <jagan@amarulasolutions.com>
 S:	Maintained
 T:	git git://anongit.freedesktop.org/drm/drm-misc
+F:	Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
 F:	drivers/gpu/drm/bridge/samsung-dsim.c
 
 DRM DRIVER FOR SITRONIX ST7703 PANELS
-- 
2.25.1


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

* [RFC PATCH 09/17] drm: bridge: samsung-dsim: Add module init, exit
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (7 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 08/17] dt-bindings: display: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 10/17] drm: bridge: samsung-dsim: Update the of_node for port(s) Jagan Teki
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Add module init and exit functions for the bridge to
register and unregister dsi_driver.

Exynos drm driver stack will register the platform_driver
separately in the common of it's exynos_drm_drv.c including
dsi_driver. Register again would return -EBUSY, so return 0
for such cases as dsi_driver is already registered.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index eed6b3ffdea7..627580abd6df 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1878,6 +1878,28 @@ struct platform_driver dsi_driver = {
 	},
 };
 
+static int __init samsung_mipi_dsim_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&dsi_driver);
+
+	/**
+	 * Exynos drm driver stack will register the platform_driver
+	 * separately in the common of it's exynos_drm_drv.c including
+	 * dsi_driver. Register again would return -EBUSY, so return 0
+	 * for such cases as dsi_driver is already registered.
+	 */
+	return ret == -EBUSY ? 0 : ret;
+}
+module_init(samsung_mipi_dsim_init);
+
+static void __exit samsung_mipi_dsim_exit(void)
+{
+	platform_driver_unregister(&dsi_driver);
+}
+module_exit(samsung_mipi_dsim_exit);
+
 MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
 MODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>");
-- 
2.25.1


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

* [RFC PATCH 10/17] drm: bridge: samsung-dsim: Update the of_node for port(s)
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (8 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 09/17] drm: bridge: samsung-dsim: Add module init, exit Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 11/17] drm: bridge: samsung-dsim: Find the possible DSI devices Jagan Teki
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Existing bridge driver is able to find the panel or bridge
if of_node isn't a port(s). This is how the exynos dsi
node handling has been done so far.

However in order to make use of this bridge in other or
new supported platforms like i.MX8MM it is required to
have a port based of_node.

So, this patch will check if node is a port based and
then update of_node.

This way we can support the platforms which are using
legacy or new DSI bindings.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 627580abd6df..2222c27feffd 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -226,6 +226,11 @@ enum samsung_dsim_transfer_type {
 	EXYNOS_DSI_RX,
 };
 
+enum {
+	DSI_PORT_IN,
+	DSI_PORT_OUT
+};
+
 struct samsung_dsim_transfer {
 	struct list_head list;
 	struct completion completed;
@@ -1436,6 +1441,15 @@ static int samsung_dsim_panel_or_bridge(struct samsung_dsim *dsi,
 {
 	struct drm_bridge *panel_bridge;
 	struct drm_panel *panel;
+	struct device_node *remote;
+
+	if (of_graph_is_present(node)) {
+		remote = of_graph_get_remote_node(node, DSI_PORT_OUT, 0);
+		if (!remote)
+			return -ENODEV;
+
+		node = remote;
+	}
 
 	panel_bridge = of_drm_find_bridge(node);
 	if (!panel_bridge) {
@@ -1579,11 +1593,6 @@ static int samsung_dsim_of_read_u32(const struct device_node *np,
 	return ret;
 }
 
-enum {
-	DSI_PORT_IN,
-	DSI_PORT_OUT
-};
-
 static int samsung_dsim_parse_dt(struct samsung_dsim *dsi)
 {
 	struct device *dev = dsi->dev;
-- 
2.25.1


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

* [RFC PATCH 11/17] drm: bridge: samsung-dsim: Find the possible DSI devices
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (9 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 10/17] drm: bridge: samsung-dsim: Update the of_node for port(s) Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 12/17] dt-bindings: display: bridge: samsung,mipi-dsim: Add i.MX8MM support Jagan Teki
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Finding panel_or_bridge might vary based on associated
DSI device drivers like DSI panel, bridge, and I2C based
DSI bridge.

All of these DSI drivers will invoke the DSI host in order
to find the panel_or_bridge from probe to host attach and
bridge_attach to host bridge attach.

So, in order to handle all these cases of finding the
panel_or_bridge invoke the finding API in host attach and
bridge attach with the DSIM_STATE_DEVICE_FOUND flag.

This way we can handle all possible cases of finding the
DSI devices.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 2222c27feffd..9a2df1212d0f 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -248,6 +248,7 @@ struct samsung_dsim_transfer {
 #define DSIM_STATE_INITIALIZED		BIT(1)
 #define DSIM_STATE_CMD_LPM		BIT(2)
 #define DSIM_STATE_VIDOUT_AVAILABLE	BIT(3)
+#define DSIM_STATE_DEVICE_FOUND		BIT(4)
 
 struct samsung_dsim_driver_data {
 	const unsigned int *reg_ofs;
@@ -1475,6 +1476,15 @@ static int samsung_dsim_bridge_attach(struct drm_bridge *bridge,
 				      enum drm_bridge_attach_flags flags)
 {
 	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
+	int ret;
+
+	if (!(dsi->state & DSIM_STATE_DEVICE_FOUND)) {
+		ret = samsung_dsim_panel_or_bridge(dsi, dsi->dev->of_node);
+		if (ret)
+			return ret;
+
+		dsi->state |= DSIM_STATE_DEVICE_FOUND;
+	}
 
 	dsi->drm = bridge->dev;
 
@@ -1498,9 +1508,13 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
 	struct drm_device *drm = dsi->drm;
 	int ret;
 
-	ret = samsung_dsim_panel_or_bridge(dsi, device->dev.of_node);
-	if (ret)
-		return ret;
+	if (!(dsi->state & DSIM_STATE_DEVICE_FOUND)) {
+		ret = samsung_dsim_panel_or_bridge(dsi, device->dev.of_node);
+		if (ret)
+			return ret;
+
+		dsi->state |= DSIM_STATE_DEVICE_FOUND;
+	}
 
 	/*
 	 * This is a temporary solution and should be made by more generic way.
-- 
2.25.1


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

* [RFC PATCH 12/17] dt-bindings: display: bridge: samsung,mipi-dsim: Add i.MX8MM support
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (10 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 11/17] drm: bridge: samsung-dsim: Find the possible DSI devices Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-14 22:59   ` Rob Herring
  2021-07-04  9:02 ` [RFC PATCH 13/17] drm: bridge: samsung-dsim: " Jagan Teki
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki, Rob Herring

Samsung MIPI DSIM bridge can also be found in i.MX8MM SoC.

Add dt-bingings for it.

Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 .../display/bridge/samsung,mipi-dsim.yaml     | 84 ++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
index b2970734ffd7..bd12d5706291 100644
--- a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
@@ -26,6 +26,7 @@ properties:
       - samsung,exynos5410-mipi-dsi
       - samsung,exynos5422-mipi-dsi
       - samsung,exynos5433-mipi-dsi
+      - fsl,imx8mm-mipi-dsim
 
   reg:
     maxItems: 1
@@ -39,6 +40,10 @@ properties:
   '#size-cells':
     const: 0
 
+  assigned-clock-parents: true
+  assigned-clock-rates: true
+  assigned-clocks: true
+
   clocks:
     minItems: 2
     maxItems: 5
@@ -102,7 +107,7 @@ properties:
         properties:
           endpoint@0:
             $ref: /schemas/graph.yaml#/properties/endpoint
-            description: sub-node describing the input from MIC
+            description: sub-node describing the input from MIC or LCDIF
 
         unevaluatedProperties: false
 
@@ -128,6 +133,30 @@ required:
 
 allOf:
   - $ref: ../dsi-controller.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: fsl,imx8mm-mipi-dsim
+
+    then:
+      properties:
+        clocks:
+          minItems: 2
+
+        clock-names:
+          items:
+            - const: bus_clk
+            - const: sclk_mipi
+
+        ports:
+          required:
+            - port@0
+            - port@1
+
+      required:
+        - ports
+
   - if:
       properties:
         compatible:
@@ -221,6 +250,59 @@ additionalProperties:
   type: object
 
 examples:
+  - |
+    #include <dt-bindings/clock/imx8mm-clock.h>
+    #include <dt-bindings/power/imx8mm-power.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    dsi@32e10000 {
+       compatible = "fsl,imx8mm-mipi-dsim";
+       reg = <0x32e10000 0x400>;
+       clocks = <&clk IMX8MM_CLK_DSI_CORE>,
+                <&clk IMX8MM_CLK_DSI_PHY_REF>;
+       clock-names = "bus_clk", "sclk_mipi";
+       assigned-clocks = <&clk IMX8MM_CLK_DSI_CORE>,
+                         <&clk IMX8MM_VIDEO_PLL1_OUT>,
+                         <&clk IMX8MM_CLK_DSI_PHY_REF>;
+       assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_266M>,
+                         <&clk IMX8MM_VIDEO_PLL1_BYPASS>,
+                         <&clk IMX8MM_VIDEO_PLL1_OUT>;
+       assigned-clock-rates = <266000000>, <594000000>, <27000000>;
+       interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+       phys = <&mipi_phy 0>;
+       phy-names = "dsim";
+       power-domains = <&dispmix_blk_ctl IMX8MM_BLK_CTL_PD_DISPMIX_MIPI_DSI>;
+       samsung,burst-clock-frequency = <891000000>;
+       samsung,esc-clock-frequency = <54000000>;
+       samsung,pll-clock-frequency = <27000000>;
+       status = "disabled";
+
+       ports {
+          #address-cells = <1>;
+          #size-cells = <0>;
+
+          port@0 {
+             reg = <0>;
+             #address-cells = <1>;
+             #size-cells = <0>;
+
+             dsi_in_lcdif: endpoint@0 {
+                reg = <0>;
+                remote-endpoint = <&lcdif_out_dsi>;
+             };
+          };
+
+          port@1 {
+             reg = <1>;
+
+             dsi_out_panel: endpoint {
+                remote-endpoint = <&panel_in_dsi>;
+             };
+          };
+       };
+    };
+
   - |
     #include <dt-bindings/clock/exynos5433.h>
     #include <dt-bindings/gpio/gpio.h>
-- 
2.25.1


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

* [RFC PATCH 13/17] drm: bridge: samsung-dsim: Add i.MX8MM support
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (11 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 12/17] dt-bindings: display: bridge: samsung,mipi-dsim: Add i.MX8MM support Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 14/17] drm: bridge: samsung-dsim: Add input_bus_flags Jagan Teki
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Samsung MIPI DSIM bridge can also be found in i.MX8MM SoC.

Add compatible and associated driver_data it.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 31 +++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 9a2df1212d0f..ea379cb0cc32 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -460,6 +460,24 @@ static const unsigned int exynos5433_reg_values[] = {
 	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c),
 };
 
+static const unsigned int imx8mm_dsim_reg_values[] = {
+	[RESET_TYPE] = DSIM_SWRST,
+	[PLL_TIMER] = 500,
+	[STOP_STATE_CNT] = 0xf,
+	[PHYCTRL_ULPS_EXIT] = 0,
+	[PHYCTRL_VREG_LP] = 0,
+	[PHYCTRL_SLEW_UP] = 0,
+	[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x06),
+	[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0b),
+	[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x07),
+	[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x26),
+	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0d),
+	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x08),
+	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x08),
+	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x0d),
+	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b),
+};
+
 static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
 	.reg_ofs = exynos_reg_ofs,
 	.plltmr_reg = 0x50,
@@ -521,6 +539,17 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
 	.exynos_specific = true,
 };
 
+static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
+	.reg_ofs = exynos5433_reg_ofs,
+	.plltmr_reg = 0xa0,
+	.has_clklane_stop = 1,
+	.num_clks = 2,
+	.max_freq = 2100,
+	.wait_for_reset = 0,
+	.num_bits_resol = 12,
+	.reg_values = imx8mm_dsim_reg_values,
+};
+
 static const struct of_device_id samsung_dsim_of_match[] = {
 	{ .compatible = "samsung,exynos3250-mipi-dsi",
 	  .data = &exynos3_dsi_driver_data },
@@ -532,6 +561,8 @@ static const struct of_device_id samsung_dsim_of_match[] = {
 	  .data = &exynos5422_dsi_driver_data },
 	{ .compatible = "samsung,exynos5433-mipi-dsi",
 	  .data = &exynos5433_dsi_driver_data },
+	{ .compatible = "fsl,imx8mm-mipi-dsim",
+	  .data = &imx8mm_dsi_driver_data },
 	{ }
 };
 
-- 
2.25.1


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

* [RFC PATCH 14/17] drm: bridge: samsung-dsim: Add input_bus_flags
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (12 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 13/17] drm: bridge: samsung-dsim: " Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 15/17] drm: bridge: samsung-dsim: Move DSI init in bridge enable Jagan Teki
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

eLCDIF is expecting to have input_bus_flags as DE_LOW
in order to set active low during valid data transfer
on each horizontal line.

Add DE_LOW flag via drm bridge timings.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index ea379cb0cc32..bc845ae100d4 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1723,6 +1723,10 @@ static const struct component_ops samsung_dsim_component_ops = {
 	.unbind	= samsung_dsim_unbind,
 };
 
+static const struct drm_bridge_timings samsung_dsim_bridge_timings = {
+	.input_bus_flags = DRM_BUS_FLAG_DE_LOW,
+};
+
 static int samsung_dsim_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1819,6 +1823,7 @@ static int samsung_dsim_probe(struct platform_device *pdev)
 
 	dsi->bridge.funcs = &samsung_dsim_bridge_funcs;
 	dsi->bridge.of_node = dev->of_node;
+	dsi->bridge.timings = &samsung_dsim_bridge_timings;
 	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 
 	drm_bridge_add(&dsi->bridge);
-- 
2.25.1


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

* [RFC PATCH 15/17] drm: bridge: samsung-dsim: Move DSI init in bridge enable
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (13 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 14/17] drm: bridge: samsung-dsim: Add input_bus_flags Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 16/17] drm: bridge: samsung-dsim: Fix PLL_P offset Jagan Teki
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Host transfer in DSI master will invoke only when the DSI
commands sent from DSI devices like DSI Panel or DSI bridges
and this host transfer wouldn't invoke I2C based DSI
bridge drivers.

Handling DSI host initialization in transfer calls might miss
the controller setup for I2C based DSI bridges.

So, move the DSI initialization from transfer to bridge enable
as the bridge enable API as it is common across all classes
of DSI device drivers.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index bc845ae100d4..54767cbf231c 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1437,6 +1437,13 @@ static void samsung_dsim_bridge_enable(struct drm_bridge *bridge)
 
 	dsi->state |= DSIM_STATE_ENABLED;
 
+	if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
+		ret = samsung_dsim_init(dsi);
+		if (ret)
+			return;
+		dsi->state |= DSIM_STATE_INITIALIZED;
+	}
+
 	samsung_dsim_set_display_mode(dsi);
 	samsung_dsim_set_display_enable(dsi, true);
 
@@ -1602,13 +1609,6 @@ static ssize_t samsung_dsim_host_transfer(struct mipi_dsi_host *host,
 	if (!(dsi->state & DSIM_STATE_ENABLED))
 		return -EINVAL;
 
-	if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
-		ret = samsung_dsim_init(dsi);
-		if (ret)
-			return ret;
-		dsi->state |= DSIM_STATE_INITIALIZED;
-	}
-
 	ret = mipi_dsi_create_packet(&xfer.packet, msg);
 	if (ret < 0)
 		return ret;
-- 
2.25.1


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

* [RFC PATCH 16/17] drm: bridge: samsung-dsim: Fix PLL_P offset
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (14 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 15/17] drm: bridge: samsung-dsim: Move DSI init in bridge enable Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
  2021-07-04  9:02 ` [RFC PATCH 17/17] drm: bridge: samsung-dsim: Add bridge mode_fixup Jagan Teki
       [not found] ` <YP2ZvoVQyvwTXP++@ravnborg.org>
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

PMS_P offset value in existing driver is not compatible
with i.MX8MM.

However the i.MX8M Mini Application Reference manual shows
the PMS_P offset is the same in the driver, but the i.MX8MM
downstream driver uses a different one.

So, handle the PMS_P offset via driver_data and use the
offset value for i.MX8MM from the downstream driver.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 54767cbf231c..0ed218f5eefc 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -184,7 +184,7 @@
 /* DSIM_PLLCTRL */
 #define DSIM_FREQ_BAND(x)		((x) << 24)
 #define DSIM_PLL_EN			(1 << 23)
-#define DSIM_PLL_P(x)			((x) << 13)
+#define DSIM_PLL_P(x, offset)		((x) << (offset))
 #define DSIM_PLL_M(x)			((x) << 4)
 #define DSIM_PLL_S(x)			((x) << 1)
 
@@ -259,6 +259,7 @@ struct samsung_dsim_driver_data {
 	unsigned int max_freq;
 	unsigned int wait_for_reset;
 	unsigned int num_bits_resol;
+	unsigned int pll_p_offset;
 	const unsigned int *reg_values;
 	bool exynos_specific;
 };
@@ -487,6 +488,7 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
 	.max_freq = 1000,
 	.wait_for_reset = 1,
 	.num_bits_resol = 11,
+	.pll_p_offset = 13,
 	.reg_values = reg_values,
 	.exynos_specific = true,
 };
@@ -500,6 +502,7 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
 	.max_freq = 1000,
 	.wait_for_reset = 1,
 	.num_bits_resol = 11,
+	.pll_p_offset = 13,
 	.reg_values = reg_values,
 	.exynos_specific = true,
 };
@@ -511,6 +514,7 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
 	.max_freq = 1000,
 	.wait_for_reset = 1,
 	.num_bits_resol = 11,
+	.pll_p_offset = 13,
 	.reg_values = reg_values,
 	.exynos_specific = true,
 };
@@ -523,6 +527,7 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
 	.max_freq = 1500,
 	.wait_for_reset = 0,
 	.num_bits_resol = 12,
+	.pll_p_offset = 13,
 	.reg_values = exynos5433_reg_values,
 	.exynos_specific = true,
 };
@@ -535,6 +540,7 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
 	.max_freq = 1500,
 	.wait_for_reset = 1,
 	.num_bits_resol = 12,
+	.pll_p_offset = 13,
 	.reg_values = exynos5422_reg_values,
 	.exynos_specific = true,
 };
@@ -547,6 +553,7 @@ static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
 	.max_freq = 2100,
 	.wait_for_reset = 0,
 	.num_bits_resol = 12,
+	.pll_p_offset = 14,
 	.reg_values = imx8mm_dsim_reg_values,
 };
 
@@ -662,7 +669,8 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
 	writel(driver_data->reg_values[PLL_TIMER],
 			dsi->reg_base + driver_data->plltmr_reg);
 
-	reg = DSIM_PLL_EN | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
+	reg = DSIM_PLL_EN | DSIM_PLL_P(p, driver_data->pll_p_offset) |
+	      DSIM_PLL_M(m) | DSIM_PLL_S(s);
 
 	if (driver_data->has_freqband) {
 		static const unsigned long freq_bands[] = {
-- 
2.25.1


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

* [RFC PATCH 17/17] drm: bridge: samsung-dsim: Add bridge mode_fixup
  2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
                   ` (15 preceding siblings ...)
  2021-07-04  9:02 ` [RFC PATCH 16/17] drm: bridge: samsung-dsim: Fix PLL_P offset Jagan Teki
@ 2021-07-04  9:02 ` Jagan Teki
       [not found] ` <YP2ZvoVQyvwTXP++@ravnborg.org>
  17 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-04  9:02 UTC (permalink / raw)
  To: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula, Jagan Teki

Fixing up the mode flags are required in order to correlate
the correct sync flags in i.MX8MM eLCDIF.

So, handle the mode flags via bridge, mode_fixup.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 0ed218f5eefc..c2a76ee5ac4e 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1474,6 +1474,16 @@ static void samsung_dsim_bridge_disable(struct drm_bridge *bridge)
 	pm_runtime_put_sync(dsi->dev);
 }
 
+static bool samsung_dsim_bridge_mode_fixup(struct drm_bridge *bridge,
+					   const struct drm_display_mode *mode,
+					   struct drm_display_mode *adjusted_mode)
+{
+	adjusted_mode->flags |= (DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
+	adjusted_mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
+
+	return true;
+}
+
 static void samsung_dsim_bridge_mode_set(struct drm_bridge *bridge,
 					 const struct drm_display_mode *mode,
 					 const struct drm_display_mode *adjusted_mode)
@@ -1542,6 +1552,7 @@ static const struct drm_bridge_funcs samsung_dsim_bridge_funcs = {
 	.enable = samsung_dsim_bridge_enable,
 	.disable = samsung_dsim_bridge_disable,
 	.mode_set = samsung_dsim_bridge_mode_set,
+	.mode_fixup = samsung_dsim_bridge_mode_fixup,
 	.attach = samsung_dsim_bridge_attach,
 };
 
-- 
2.25.1


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

* Re: [RFC PATCH 03/17] drm/exynos: dsi: Use the drm_panel_bridge API
  2021-07-04  9:02 ` [RFC PATCH 03/17] drm/exynos: dsi: Use the drm_panel_bridge API Jagan Teki
@ 2021-07-05 11:47   ` Marek Szyprowski
  2021-07-05 12:00     ` Jagan Teki
  0 siblings, 1 reply; 31+ messages in thread
From: Marek Szyprowski @ 2021-07-05 11:47 UTC (permalink / raw)
  To: Jagan Teki, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam
  Cc: dri-devel, devicetree, linux-samsung-soc, linux-arm-kernel,
	NXP Linux Team, linux-amarula

On 04.07.2021 11:02, Jagan Teki wrote:
> Use drm_panel_bridge to replace manual panel and
> bridge_chain handling code.
>
> This makes the driver simpler to allow all components
> in the display pipeline to be treated as bridges by
> cleaning the way to generic connector handling.
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>

This breaks Exysos DSI driver operation (Trats board worked fine with 
only patches 1-2):

[    2.540066] exynos4-fb 11c00000.fimd: Adding to iommu group 0
[    2.554733] OF: graph: no port node found in /soc/fimd@11c00000
[    2.602819] [drm] Exynos DRM: using 11c00000.fimd device for DMA 
mapping operations
[    2.609649] exynos-drm exynos-drm: bound 11c00000.fimd (ops 
fimd_component_ops)
[    2.632558] exynos-drm exynos-drm: failed to bind 11c80000.dsi (ops 
exynos_dsi_component_ops): -22
[    2.642263] exynos-drm exynos-drm: master bind failed: -22
[    2.651017] exynos-drm: probe of exynos-drm failed with error -22

> ---
>   drivers/gpu/drm/exynos/exynos_drm_dsi.c | 167 ++++--------------------
>   1 file changed, 23 insertions(+), 144 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index d7d60aee465b..24f0b082ac6d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -254,9 +254,6 @@ struct exynos_dsi_driver_data {
>   struct exynos_dsi {
>   	struct drm_encoder encoder;
>   	struct mipi_dsi_host dsi_host;
> -	struct drm_connector connector;
> -	struct drm_panel *panel;
> -	struct list_head bridge_chain;
>   	struct drm_bridge bridge;
>   	struct drm_bridge *out_bridge;
>   	struct drm_device *drm;
> @@ -287,7 +284,6 @@ struct exynos_dsi {
>   };
>   
>   #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
> -#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
>   
>   static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b)
>   {
> @@ -1379,7 +1375,6 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
>   static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
>   {
>   	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
> -	struct drm_bridge *iter;
>   	int ret;
>   
>   	if (dsi->state & DSIM_STATE_ENABLED)
> @@ -1393,134 +1388,51 @@ static void exynos_dsi_bridge_enable(struct drm_bridge *bridge)
>   
>   	dsi->state |= DSIM_STATE_ENABLED;
>   
> -	if (dsi->panel) {
> -		ret = drm_panel_prepare(dsi->panel);
> -		if (ret < 0)
> -			goto err_put_sync;
> -	} else {
> -		list_for_each_entry_reverse(iter, &dsi->bridge_chain,
> -					    chain_node) {
> -			if (iter->funcs->pre_enable)
> -				iter->funcs->pre_enable(iter);
> -		}
> -	}
> -
>   	exynos_dsi_set_display_mode(dsi);
>   	exynos_dsi_set_display_enable(dsi, true);
>   
> -	if (dsi->panel) {
> -		ret = drm_panel_enable(dsi->panel);
> -		if (ret < 0)
> -			goto err_display_disable;
> -	} else {
> -		list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
> -			if (iter->funcs->enable)
> -				iter->funcs->enable(iter);
> -		}
> -	}
> -
>   	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
>   	return;
> -
> -err_display_disable:
> -	exynos_dsi_set_display_enable(dsi, false);
> -	drm_panel_unprepare(dsi->panel);
> -
> -err_put_sync:
> -	dsi->state &= ~DSIM_STATE_ENABLED;
> -	pm_runtime_put(dsi->dev);
>   }
>   
>   static void exynos_dsi_bridge_disable(struct drm_bridge *bridge)
>   {
>   	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
> -	struct drm_bridge *iter;
>   
>   	if (!(dsi->state & DSIM_STATE_ENABLED))
>   		return;
>   
>   	dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
>   
> -	drm_panel_disable(dsi->panel);
> -
> -	list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
> -		if (iter->funcs->disable)
> -			iter->funcs->disable(iter);
> -	}
> -
>   	exynos_dsi_set_display_enable(dsi, false);
> -	drm_panel_unprepare(dsi->panel);
> -
> -	list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
> -		if (iter->funcs->post_disable)
> -			iter->funcs->post_disable(iter);
> -	}
>   
>   	dsi->state &= ~DSIM_STATE_ENABLED;
>   	pm_runtime_put_sync(dsi->dev);
>   }
>   
> -static enum drm_connector_status
> -exynos_dsi_detect(struct drm_connector *connector, bool force)
> -{
> -	return connector->status;
> -}
> -
> -static void exynos_dsi_connector_destroy(struct drm_connector *connector)
> +static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi,
> +				      struct device_node *node)
>   {
> -	drm_connector_unregister(connector);
> -	drm_connector_cleanup(connector);
> -	connector->dev = NULL;
> -}
> -
> -static const struct drm_connector_funcs exynos_dsi_connector_funcs = {
> -	.detect = exynos_dsi_detect,
> -	.fill_modes = drm_helper_probe_single_connector_modes,
> -	.destroy = exynos_dsi_connector_destroy,
> -	.reset = drm_atomic_helper_connector_reset,
> -	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> -	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> -};
> -
> -static int exynos_dsi_get_modes(struct drm_connector *connector)
> -{
> -	struct exynos_dsi *dsi = connector_to_dsi(connector);
> -
> -	if (dsi->panel)
> -		return drm_panel_get_modes(dsi->panel, connector);
> -
> -	return 0;
> -}
> +	struct drm_bridge *panel_bridge;
> +	struct drm_panel *panel;
>   
> -static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = {
> -	.get_modes = exynos_dsi_get_modes,
> -};
> +	panel_bridge = of_drm_find_bridge(node);
> +	if (!panel_bridge) {
> +		panel = of_drm_find_panel(node);
> +		if (!IS_ERR(panel)) {
> +			panel_bridge = drm_panel_bridge_add(panel);
> +			if (IS_ERR(panel_bridge))
> +				return PTR_ERR(panel_bridge);
> +		}
> +	}
>   
> -static int exynos_dsi_create_connector(struct exynos_dsi *dsi,
> -				       struct drm_device *drm)
> -{
> -	struct drm_encoder *encoder = &dsi->encoder;
> -	struct drm_connector *connector = &dsi->connector;
> -	int ret;
> +	of_node_put(node);
>   
> -	connector->polled = DRM_CONNECTOR_POLL_HPD;
> +	dsi->out_bridge = panel_bridge;
>   
> -	ret = drm_connector_init(drm, connector, &exynos_dsi_connector_funcs,
> -				 DRM_MODE_CONNECTOR_DSI);
> -	if (ret) {
> -		DRM_DEV_ERROR(dsi->dev,
> -			      "Failed to initialize connector with drm\n");
> -		return ret;
> -	}
> +	if (!dsi->out_bridge)
> +		return -EPROBE_DEFER;
>   
> -	connector->status = connector_status_disconnected;
> -	drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
> -	drm_connector_attach_encoder(connector, encoder);
> -	if (!drm->registered)
> -		return 0;
> -
> -	connector->funcs->reset(connector);
> -	drm_connector_register(connector);
>   	return 0;
>   }
>   
> @@ -1531,7 +1443,8 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
>   
>   	dsi->drm = bridge->dev;
>   
> -	return 0;
> +	return drm_bridge_attach(bridge->encoder, dsi->out_bridge, bridge,
> +				 flags);
>   }
>   
>   static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
> @@ -1546,32 +1459,12 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
>   				  struct mipi_dsi_device *device)
>   {
>   	struct exynos_dsi *dsi = host_to_dsi(host);
> -	struct drm_encoder *encoder = &dsi->encoder;
>   	struct drm_device *drm = dsi->drm;
> -	struct drm_bridge *out_bridge;
> -
> -	out_bridge  = of_drm_find_bridge(device->dev.of_node);
> -	if (out_bridge) {
> -		drm_bridge_attach(encoder, out_bridge, NULL, 0);
> -		dsi->out_bridge = out_bridge;
> -		list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
> -	} else {
> -		int ret = exynos_dsi_create_connector(dsi, drm);
> -
> -		if (ret) {
> -			DRM_DEV_ERROR(dsi->dev,
> -				      "failed to create connector ret = %d\n",
> -				      ret);
> -			drm_encoder_cleanup(encoder);
> -			return ret;
> -		}
> +	int ret;
>   
> -		dsi->panel = of_drm_find_panel(device->dev.of_node);
> -		if (IS_ERR(dsi->panel))
> -			dsi->panel = NULL;
> -		else
> -			dsi->connector.status = connector_status_connected;
> -	}
> +	ret = exynos_dsi_panel_or_bridge(dsi, device->dev.of_node);
> +	if (ret)
> +		return ret;
>   
>   	/*
>   	 * This is a temporary solution and should be made by more generic way.
> @@ -1607,19 +1500,6 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
>   	struct exynos_dsi *dsi = host_to_dsi(host);
>   	struct drm_device *drm = dsi->drm;
>   
> -	if (dsi->panel) {
> -		mutex_lock(&drm->mode_config.mutex);
> -		exynos_dsi_bridge_disable(&dsi->bridge);
> -		dsi->panel = NULL;
> -		dsi->connector.status = connector_status_disconnected;
> -		mutex_unlock(&drm->mode_config.mutex);
> -	} else {
> -		if (dsi->out_bridge->funcs->detach)
> -			dsi->out_bridge->funcs->detach(dsi->out_bridge);
> -		dsi->out_bridge = NULL;
> -		INIT_LIST_HEAD(&dsi->bridge_chain);
> -	}
> -
>   	if (drm->mode_config.poll_enabled)
>   		drm_kms_helper_hotplug_event(drm);
>   
> @@ -1770,7 +1650,6 @@ static int exynos_dsi_probe(struct platform_device *pdev)
>   	init_completion(&dsi->completed);
>   	spin_lock_init(&dsi->transfer_lock);
>   	INIT_LIST_HEAD(&dsi->transfer_list);
> -	INIT_LIST_HEAD(&dsi->bridge_chain);
>   
>   	dsi->dsi_host.ops = &exynos_dsi_ops;
>   	dsi->dsi_host.dev = dev;

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


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

* Re: [RFC PATCH 03/17] drm/exynos: dsi: Use the drm_panel_bridge API
  2021-07-05 11:47   ` Marek Szyprowski
@ 2021-07-05 12:00     ` Jagan Teki
  2021-07-05 12:13       ` Marek Szyprowski
  0 siblings, 1 reply; 31+ messages in thread
From: Jagan Teki @ 2021-07-05 12:00 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, dri-devel, devicetree,
	linux-samsung-soc, linux-arm-kernel, NXP Linux Team,
	linux-amarula

On Mon, Jul 5, 2021 at 5:18 PM Marek Szyprowski
<m.szyprowski@samsung.com> wrote:
>
> On 04.07.2021 11:02, Jagan Teki wrote:
> > Use drm_panel_bridge to replace manual panel and
> > bridge_chain handling code.
> >
> > This makes the driver simpler to allow all components
> > in the display pipeline to be treated as bridges by
> > cleaning the way to generic connector handling.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>
> This breaks Exysos DSI driver operation (Trats board worked fine with
> only patches 1-2):
>
> [    2.540066] exynos4-fb 11c00000.fimd: Adding to iommu group 0
> [    2.554733] OF: graph: no port node found in /soc/fimd@11c00000
> [    2.602819] [drm] Exynos DRM: using 11c00000.fimd device for DMA
> mapping operations
> [    2.609649] exynos-drm exynos-drm: bound 11c00000.fimd (ops
> fimd_component_ops)
> [    2.632558] exynos-drm exynos-drm: failed to bind 11c80000.dsi (ops
> exynos_dsi_component_ops): -22
> [    2.642263] exynos-drm exynos-drm: master bind failed: -22
> [    2.651017] exynos-drm: probe of exynos-drm failed with error -22

Thanks for testing it.

Can you check Squash of 3,4 or 3,4,5 will work or not?

Thanks,
Jagan.

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

* Re: [RFC PATCH 03/17] drm/exynos: dsi: Use the drm_panel_bridge API
  2021-07-05 12:00     ` Jagan Teki
@ 2021-07-05 12:13       ` Marek Szyprowski
  2021-07-05 12:34         ` Jagan Teki
  0 siblings, 1 reply; 31+ messages in thread
From: Marek Szyprowski @ 2021-07-05 12:13 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, dri-devel, devicetree,
	linux-samsung-soc, linux-arm-kernel, NXP Linux Team,
	linux-amarula

On 05.07.2021 14:00, Jagan Teki wrote:
> On Mon, Jul 5, 2021 at 5:18 PM Marek Szyprowski
> <m.szyprowski@samsung.com> wrote:
>> On 04.07.2021 11:02, Jagan Teki wrote:
>>> Use drm_panel_bridge to replace manual panel and
>>> bridge_chain handling code.
>>>
>>> This makes the driver simpler to allow all components
>>> in the display pipeline to be treated as bridges by
>>> cleaning the way to generic connector handling.
>>>
>>> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>> This breaks Exysos DSI driver operation (Trats board worked fine with
>> only patches 1-2):
>>
>> [    2.540066] exynos4-fb 11c00000.fimd: Adding to iommu group 0
>> [    2.554733] OF: graph: no port node found in /soc/fimd@11c00000
>> [    2.602819] [drm] Exynos DRM: using 11c00000.fimd device for DMA
>> mapping operations
>> [    2.609649] exynos-drm exynos-drm: bound 11c00000.fimd (ops
>> fimd_component_ops)
>> [    2.632558] exynos-drm exynos-drm: failed to bind 11c80000.dsi (ops
>> exynos_dsi_component_ops): -22
>> [    2.642263] exynos-drm exynos-drm: master bind failed: -22
>> [    2.651017] exynos-drm: probe of exynos-drm failed with error -22
> Thanks for testing it.
>
> Can you check Squash of 3,4 or 3,4,5 will work or not?

I've check both sets: 1-4 and 1-5 and none of them works. The result is 
same as above. If I remember correctly, last time when I played with 
that code, there was a problem with DRM core calling bridge ops in 
different order than when they are used by the Exynos DSI driver.

Best regards

-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


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

* Re: [RFC PATCH 03/17] drm/exynos: dsi: Use the drm_panel_bridge API
  2021-07-05 12:13       ` Marek Szyprowski
@ 2021-07-05 12:34         ` Jagan Teki
  0 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-05 12:34 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, dri-devel, devicetree,
	linux-samsung-soc, linux-arm-kernel, NXP Linux Team,
	linux-amarula

On Mon, Jul 5, 2021 at 5:43 PM Marek Szyprowski
<m.szyprowski@samsung.com> wrote:
>
> On 05.07.2021 14:00, Jagan Teki wrote:
> > On Mon, Jul 5, 2021 at 5:18 PM Marek Szyprowski
> > <m.szyprowski@samsung.com> wrote:
> >> On 04.07.2021 11:02, Jagan Teki wrote:
> >>> Use drm_panel_bridge to replace manual panel and
> >>> bridge_chain handling code.
> >>>
> >>> This makes the driver simpler to allow all components
> >>> in the display pipeline to be treated as bridges by
> >>> cleaning the way to generic connector handling.
> >>>
> >>> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> >> This breaks Exysos DSI driver operation (Trats board worked fine with
> >> only patches 1-2):
> >>
> >> [    2.540066] exynos4-fb 11c00000.fimd: Adding to iommu group 0
> >> [    2.554733] OF: graph: no port node found in /soc/fimd@11c00000
> >> [    2.602819] [drm] Exynos DRM: using 11c00000.fimd device for DMA
> >> mapping operations
> >> [    2.609649] exynos-drm exynos-drm: bound 11c00000.fimd (ops
> >> fimd_component_ops)
> >> [    2.632558] exynos-drm exynos-drm: failed to bind 11c80000.dsi (ops
> >> exynos_dsi_component_ops): -22
> >> [    2.642263] exynos-drm exynos-drm: master bind failed: -22
> >> [    2.651017] exynos-drm: probe of exynos-drm failed with error -22
> > Thanks for testing it.
> >
> > Can you check Squash of 3,4 or 3,4,5 will work or not?
>
> I've check both sets: 1-4 and 1-5 and none of them works. The result is
> same as above. If I remember correctly, last time when I played with
> that code, there was a problem with DRM core calling bridge ops in
> different order than when they are used by the Exynos DSI driver.

Okay. Let me check with sun6i-mipi-dsi as it is component_ops based.

Jagan.

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

* Re: [RFC PATCH 08/17] dt-bindings: display: bridge: Add Samsung MIPI DSIM bridge
  2021-07-04  9:02 ` [RFC PATCH 08/17] dt-bindings: display: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
@ 2021-07-12 15:13   ` Rob Herring
  2021-07-12 15:23     ` Jagan Teki
  0 siblings, 1 reply; 31+ messages in thread
From: Rob Herring @ 2021-07-12 15:13 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, dri-devel, devicetree,
	linux-samsung-soc, linux-arm-kernel, NXP Linux Team,
	linux-amarula

On Sun, Jul 04, 2021 at 02:32:21PM +0530, Jagan Teki wrote:
> Samsing MIPI DSIM bridge can be found on Exynos and NXP's
> i.MX8M Mini and Nano SoC's.
> 
> This dt-bindings replaces legacy exynos_dsim.txt.
> 
> Used the example node from latest Exynos SoC instead of
> the one used in legacy exynos_dsim.txt.
> 
> Add dt-bingings for it.

typo

> 
> Cc: Rob Herring <robh+dt@kernel.org>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  .../display/bridge/samsung,mipi-dsim.yaml     | 278 ++++++++++++++++++
>  .../bindings/display/exynos/exynos_dsim.txt   |  90 ------
>  MAINTAINERS                                   |   1 +
>  3 files changed, 279 insertions(+), 90 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
>  delete mode 100644 Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
> new file mode 100644
> index 000000000000..b2970734ffd7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
> @@ -0,0 +1,278 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/bridge/samsung,mipi-dsim.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Samsung MIPI DSIM bridge controller
> +
> +maintainers:
> +  - Inki Dae <inki.dae@samsung.com>
> +  - Joonyoung Shim <jy0922.shim@samsung.com>
> +  - Seung-Woo Kim <sw0312.kim@samsung.com>
> +  - Kyungmin Park <kyungmin.park@samsung.com>
> +  - Andrzej Hajda <a.hajda@samsung.com>
> +  - Jagan Teki <jagan@amarulasolutions.com>
> +
> +description: |
> +  Samsung MIPI DSIM bridge controller can be found it on Exynos
> +  and i.MX8M Mini and Nano SoC's.
> +
> +properties:
> +  compatible:
> +    enum:
> +      - samsung,exynos3250-mipi-dsi
> +      - samsung,exynos4210-mipi-dsi
> +      - samsung,exynos5410-mipi-dsi
> +      - samsung,exynos5422-mipi-dsi
> +      - samsung,exynos5433-mipi-dsi

What about i.MX compatibles?

> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 0
> +
> +  clocks:
> +    minItems: 2
> +    maxItems: 5
> +
> +  clock-names:
> +    minItems: 2
> +    maxItems: 5
> +
> +  phys:
> +    maxItems: 1
> +    description: phandle to the phy module representing the DPHY

Drop

> +
> +  phy-names:
> +    items:
> +      - const: dsim
> +
> +  samsung,phy-type:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: phandle to the samsung phy-type
> +
> +  power-domains:
> +    description: phandle to the associated power domain

Drop

> +    maxItems: 1
> +
> +  samsung,power-domain:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: phandle to the associated samsung power domain
> +    maxItems: 1
> +
> +  vddcore-supply:
> +    description: MIPI DSIM Core voltage supply (e.g. 1.1V)
> +
> +  vddio-supply:
> +    description: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
> +
> +  samsung,burst-clock-frequency:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description:
> +      DSIM high speed burst mode frequency.
> +
> +  samsung,esc-clock-frequency:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description:
> +      DSIM escape mode frequency.
> +
> +  samsung,pll-clock-frequency:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description:
> +      DSIM oscillator clock frequency.
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +
> +    properties:
> +      port@0:
> +        $ref: /schemas/graph.yaml#/$defs/port-base

If there are no extra endpoint properties, then use 
'/schemas/graph.yaml#/properties/port'.

> +        description:
> +          Input port node to receive pixel data from the
> +          display controller. Exactly one endpoint must be
> +          specified.
> +        properties:
> +          endpoint@0:
> +            $ref: /schemas/graph.yaml#/properties/endpoint
> +            description: sub-node describing the input from MIC

I'd assume i.MX has a different input than MIC?

> +
> +        unevaluatedProperties: false
> +
> +      port@1:
> +        $ref: /schemas/graph.yaml#/properties/port
> +        description:
> +          DSI output port node to the panel or the next bridge
> +          in the chain
> +
> +required:
> +  - '#address-cells'
> +  - '#size-cells'
> +  - clock-names
> +  - clocks
> +  - compatible
> +  - interrupts
> +  - phy-names
> +  - phys
> +  - reg
> +  - samsung,burst-clock-frequency
> +  - samsung,esc-clock-frequency
> +  - samsung,pll-clock-frequency
> +
> +allOf:
> +  - $ref: ../dsi-controller.yaml#
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: samsung,exynos5433-mipi-dsi
> +
> +    then:
> +      properties:
> +        clocks:
> +          minItems: 5
> +
> +        clock-names:
> +          items:
> +            - const: bus_clk
> +            - const: phyclk_mipidphy0_bitclkdiv8
> +            - const: phyclk_mipidphy0_rxclkesc0
> +            - const: sclk_rgb_vclk_to_dsim0
> +            - const: sclk_mipi
> +
> +        ports:
> +          required:
> +            - port@0
> +
> +      required:
> +        - ports
> +        - vddcore-supply
> +        - vddio-supply
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: samsung,exynos5410-mipi-dsi
> +
> +    then:
> +      properties:
> +        clocks:
> +          minItems: 2
> +
> +        clock-names:
> +          items:
> +            - const: bus_clk
> +            - const: pll_clk
> +
> +      required:
> +        - vddcore-supply
> +        - vddio-supply
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: samsung,exynos4210-mipi-dsi
> +
> +    then:
> +      properties:
> +        clocks:
> +          minItems: 2
> +
> +        clock-names:
> +          items:
> +            - const: bus_clk
> +            - const: sclk_mipi
> +
> +      required:
> +        - vddcore-supply
> +        - vddio-supply
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: samsung,exynos3250-mipi-dsi
> +
> +    then:
> +      properties:
> +        clocks:
> +          minItems: 2
> +
> +        clock-names:
> +          items:
> +            - const: bus_clk
> +            - const: pll_clk
> +
> +      required:
> +        - vddcore-supply
> +        - vddio-supply
> +        - samsung,phy-type
> +
> +additionalProperties:
> +  type: object
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/exynos5433.h>
> +    #include <dt-bindings/gpio/gpio.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    dsi@13900000 {
> +       compatible = "samsung,exynos5433-mipi-dsi";
> +       reg = <0x13900000 0xC0>;
> +       interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
> +       phys = <&mipi_phy 1>;
> +       phy-names = "dsim";
> +       clocks = <&cmu_disp CLK_PCLK_DSIM0>,
> +                <&cmu_disp CLK_PHYCLK_MIPIDPHY0_BITCLKDIV8>,
> +                <&cmu_disp CLK_PHYCLK_MIPIDPHY0_RXCLKESC0>,
> +                <&cmu_disp CLK_SCLK_RGB_VCLK_TO_DSIM0>,
> +                <&cmu_disp CLK_SCLK_DSIM0>;
> +       clock-names = "bus_clk",
> +                     "phyclk_mipidphy0_bitclkdiv8",
> +                     "phyclk_mipidphy0_rxclkesc0",
> +                     "sclk_rgb_vclk_to_dsim0",
> +                     "sclk_mipi";
> +       power-domains = <&pd_disp>;
> +       vddcore-supply = <&ldo6_reg>;
> +       vddio-supply = <&ldo7_reg>;
> +       samsung,burst-clock-frequency = <512000000>;
> +       samsung,esc-clock-frequency = <16000000>;
> +       samsung,pll-clock-frequency = <24000000>;
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&te_irq>;
> +       status = "disabled";
> +       #address-cells = <1>;
> +       #size-cells = <0>;
> +
> +       panel@0 {
> +          compatible = "samsung,s6e3ha2";
> +          reg = <0>;
> +          vdd3-supply = <&ldo27_reg>;
> +          vci-supply = <&ldo28_reg>;
> +          reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
> +          enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
> +       };
> +
> +       ports {
> +          #address-cells = <1>;
> +          #size-cells = <0>;
> +
> +          port@0 {
> +             reg = <0>;
> +
> +             dsi_to_mic: endpoint {
> +                remote-endpoint = <&mic_to_dsi>;
> +             };
> +          };
> +       };
> +    };
> diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> deleted file mode 100644
> index be377786e8cd..000000000000
> --- a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> +++ /dev/null
> @@ -1,90 +0,0 @@
> -Exynos MIPI DSI Master
> -
> -Required properties:
> -  - compatible: value should be one of the following
> -		"samsung,exynos3250-mipi-dsi" /* for Exynos3250/3472 SoCs */
> -		"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
> -		"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
> -		"samsung,exynos5422-mipi-dsi" /* for Exynos5422/5800 SoCs */
> -		"samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
> -  - reg: physical base address and length of the registers set for the device
> -  - interrupts: should contain DSI interrupt
> -  - clocks: list of clock specifiers, must contain an entry for each required
> -    entry in clock-names
> -  - clock-names: should include "bus_clk"and "sclk_mipi" entries
> -		 the use of "pll_clk" is deprecated
> -  - phys: list of phy specifiers, must contain an entry for each required
> -    entry in phy-names
> -  - phy-names: should include "dsim" entry
> -  - vddcore-supply: MIPI DSIM Core voltage supply (e.g. 1.1V)
> -  - vddio-supply: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
> -  - samsung,pll-clock-frequency: specifies frequency of the oscillator clock
> -  - #address-cells, #size-cells: should be set respectively to <1> and <0>
> -    according to DSI host bindings (see MIPI DSI bindings [1])
> -  - samsung,burst-clock-frequency: specifies DSI frequency in high-speed burst
> -    mode
> -  - samsung,esc-clock-frequency: specifies DSI frequency in escape mode
> -
> -Optional properties:
> -  - power-domains: a phandle to DSIM power domain node
> -
> -Child nodes:
> -  Should contain DSI peripheral nodes (see MIPI DSI bindings [1]).
> -
> -Video interfaces:
> -  Device node can contain following video interface port nodes according to [2]:
> -  0: RGB input,
> -  1: DSI output
> -
> -[1]: Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
> -[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
> -
> -Example:
> -
> -	dsi@11c80000 {
> -		compatible = "samsung,exynos4210-mipi-dsi";
> -		reg = <0x11C80000 0x10000>;
> -		interrupts = <0 79 0>;
> -		clocks = <&clock 286>, <&clock 143>;
> -		clock-names = "bus_clk", "sclk_mipi";
> -		phys = <&mipi_phy 1>;
> -		phy-names = "dsim";
> -		vddcore-supply = <&vusb_reg>;
> -		vddio-supply = <&vmipi_reg>;
> -		power-domains = <&pd_lcd0>;
> -		#address-cells = <1>;
> -		#size-cells = <0>;
> -		samsung,pll-clock-frequency = <24000000>;
> -
> -		panel@1 {
> -			reg = <0>;
> -			...
> -			port {
> -				panel_ep: endpoint {
> -					remote-endpoint = <&dsi_ep>;
> -				};
> -			};
> -		};
> -
> -		ports {
> -			#address-cells = <1>;
> -			#size-cells = <0>;
> -
> -			port@0 {
> -				reg = <0>;
> -				decon_to_mic: endpoint {
> -					remote-endpoint = <&mic_to_decon>;
> -				};
> -			};
> -
> -			port@1 {
> -				reg = <1>;
> -				dsi_ep: endpoint {
> -					reg = <0>;
> -					samsung,burst-clock-frequency = <500000000>;
> -					samsung,esc-clock-frequency = <20000000>;
> -					remote-endpoint = <&panel_ep>;
> -				};
> -			};
> -		};
> -	};
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 733c2ebc0393..e571fc7792aa 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5873,6 +5873,7 @@ M:	Andrzej Hajda <a.hajda@samsung.com>
>  M:	Jagan Teki <jagan@amarulasolutions.com>
>  S:	Maintained
>  T:	git git://anongit.freedesktop.org/drm/drm-misc
> +F:	Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
>  F:	drivers/gpu/drm/bridge/samsung-dsim.c
>  
>  DRM DRIVER FOR SITRONIX ST7703 PANELS
> -- 
> 2.25.1
> 
> 

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

* Re: [RFC PATCH 08/17] dt-bindings: display: bridge: Add Samsung MIPI DSIM bridge
  2021-07-12 15:13   ` Rob Herring
@ 2021-07-12 15:23     ` Jagan Teki
  0 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-12 15:23 UTC (permalink / raw)
  To: Rob Herring
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, dri-devel, devicetree,
	linux-samsung-soc, linux-arm-kernel, NXP Linux Team,
	linux-amarula

On Mon, Jul 12, 2021 at 8:43 PM Rob Herring <robh@kernel.org> wrote:
>
> On Sun, Jul 04, 2021 at 02:32:21PM +0530, Jagan Teki wrote:
> > Samsing MIPI DSIM bridge can be found on Exynos and NXP's
> > i.MX8M Mini and Nano SoC's.
> >
> > This dt-bindings replaces legacy exynos_dsim.txt.
> >
> > Used the example node from latest Exynos SoC instead of
> > the one used in legacy exynos_dsim.txt.
> >
> > Add dt-bingings for it.
>
> typo
>
> >
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  .../display/bridge/samsung,mipi-dsim.yaml     | 278 ++++++++++++++++++
> >  .../bindings/display/exynos/exynos_dsim.txt   |  90 ------
> >  MAINTAINERS                                   |   1 +
> >  3 files changed, 279 insertions(+), 90 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
> >  delete mode 100644 Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> >
> > diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
> > new file mode 100644
> > index 000000000000..b2970734ffd7
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
> > @@ -0,0 +1,278 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/bridge/samsung,mipi-dsim.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Samsung MIPI DSIM bridge controller
> > +
> > +maintainers:
> > +  - Inki Dae <inki.dae@samsung.com>
> > +  - Joonyoung Shim <jy0922.shim@samsung.com>
> > +  - Seung-Woo Kim <sw0312.kim@samsung.com>
> > +  - Kyungmin Park <kyungmin.park@samsung.com>
> > +  - Andrzej Hajda <a.hajda@samsung.com>
> > +  - Jagan Teki <jagan@amarulasolutions.com>
> > +
> > +description: |
> > +  Samsung MIPI DSIM bridge controller can be found it on Exynos
> > +  and i.MX8M Mini and Nano SoC's.
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - samsung,exynos3250-mipi-dsi
> > +      - samsung,exynos4210-mipi-dsi
> > +      - samsung,exynos5410-mipi-dsi
> > +      - samsung,exynos5422-mipi-dsi
> > +      - samsung,exynos5433-mipi-dsi
>
> What about i.MX compatibles?

I have added in the next patch since this is yml conversation for
existing .txt bindings.

>
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  interrupts:
> > +    maxItems: 1
> > +
> > +  '#address-cells':
> > +    const: 1
> > +
> > +  '#size-cells':
> > +    const: 0
> > +
> > +  clocks:
> > +    minItems: 2
> > +    maxItems: 5
> > +
> > +  clock-names:
> > +    minItems: 2
> > +    maxItems: 5
> > +
> > +  phys:
> > +    maxItems: 1
> > +    description: phandle to the phy module representing the DPHY
>
> Drop
>
> > +
> > +  phy-names:
> > +    items:
> > +      - const: dsim
> > +
> > +  samsung,phy-type:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: phandle to the samsung phy-type
> > +
> > +  power-domains:
> > +    description: phandle to the associated power domain
>
> Drop
>
> > +    maxItems: 1
> > +
> > +  samsung,power-domain:
> > +    $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: phandle to the associated samsung power domain
> > +    maxItems: 1
> > +
> > +  vddcore-supply:
> > +    description: MIPI DSIM Core voltage supply (e.g. 1.1V)
> > +
> > +  vddio-supply:
> > +    description: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
> > +
> > +  samsung,burst-clock-frequency:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description:
> > +      DSIM high speed burst mode frequency.
> > +
> > +  samsung,esc-clock-frequency:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description:
> > +      DSIM escape mode frequency.
> > +
> > +  samsung,pll-clock-frequency:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description:
> > +      DSIM oscillator clock frequency.
> > +
> > +  ports:
> > +    $ref: /schemas/graph.yaml#/properties/ports
> > +
> > +    properties:
> > +      port@0:
> > +        $ref: /schemas/graph.yaml#/$defs/port-base
>
> If there are no extra endpoint properties, then use
> '/schemas/graph.yaml#/properties/port'.

Okay.

>
> > +        description:
> > +          Input port node to receive pixel data from the
> > +          display controller. Exactly one endpoint must be
> > +          specified.
> > +        properties:
> > +          endpoint@0:
> > +            $ref: /schemas/graph.yaml#/properties/endpoint
> > +            description: sub-node describing the input from MIC
>
> I'd assume i.MX has a different input than MIC?

Yes, updated in next patch.

Thanks,
Jagan.

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

* Re: [RFC PATCH 12/17] dt-bindings: display: bridge: samsung,mipi-dsim: Add i.MX8MM support
  2021-07-04  9:02 ` [RFC PATCH 12/17] dt-bindings: display: bridge: samsung,mipi-dsim: Add i.MX8MM support Jagan Teki
@ 2021-07-14 22:59   ` Rob Herring
  0 siblings, 0 replies; 31+ messages in thread
From: Rob Herring @ 2021-07-14 22:59 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, dri-devel, devicetree,
	linux-samsung-soc, linux-arm-kernel, NXP Linux Team,
	linux-amarula

On Sun, Jul 04, 2021 at 02:32:25PM +0530, Jagan Teki wrote:
> Samsung MIPI DSIM bridge can also be found in i.MX8MM SoC.
> 
> Add dt-bingings for it.
> 
> Cc: Rob Herring <robh+dt@kernel.org>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  .../display/bridge/samsung,mipi-dsim.yaml     | 84 ++++++++++++++++++-
>  1 file changed, 83 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
> index b2970734ffd7..bd12d5706291 100644
> --- a/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
> @@ -26,6 +26,7 @@ properties:
>        - samsung,exynos5410-mipi-dsi
>        - samsung,exynos5422-mipi-dsi
>        - samsung,exynos5433-mipi-dsi
> +      - fsl,imx8mm-mipi-dsim
>  
>    reg:
>      maxItems: 1
> @@ -39,6 +40,10 @@ properties:
>    '#size-cells':
>      const: 0
>  
> +  assigned-clock-parents: true
> +  assigned-clock-rates: true
> +  assigned-clocks: true

You don't need these. They are always allowed if 'clocks' is present.

> +
>    clocks:
>      minItems: 2
>      maxItems: 5
> @@ -102,7 +107,7 @@ properties:
>          properties:
>            endpoint@0:
>              $ref: /schemas/graph.yaml#/properties/endpoint
> -            description: sub-node describing the input from MIC
> +            description: sub-node describing the input from MIC or LCDIF
>  
>          unevaluatedProperties: false
>  
> @@ -128,6 +133,30 @@ required:
>  
>  allOf:
>    - $ref: ../dsi-controller.yaml#
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: fsl,imx8mm-mipi-dsim
> +
> +    then:
> +      properties:
> +        clocks:
> +          minItems: 2
> +
> +        clock-names:
> +          items:
> +            - const: bus_clk
> +            - const: sclk_mipi
> +
> +        ports:
> +          required:
> +            - port@0
> +            - port@1
> +
> +      required:
> +        - ports
> +
>    - if:
>        properties:
>          compatible:
> @@ -221,6 +250,59 @@ additionalProperties:
>    type: object
>  
>  examples:
> +  - |
> +    #include <dt-bindings/clock/imx8mm-clock.h>
> +    #include <dt-bindings/power/imx8mm-power.h>
> +    #include <dt-bindings/gpio/gpio.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    dsi@32e10000 {
> +       compatible = "fsl,imx8mm-mipi-dsim";
> +       reg = <0x32e10000 0x400>;
> +       clocks = <&clk IMX8MM_CLK_DSI_CORE>,
> +                <&clk IMX8MM_CLK_DSI_PHY_REF>;
> +       clock-names = "bus_clk", "sclk_mipi";
> +       assigned-clocks = <&clk IMX8MM_CLK_DSI_CORE>,
> +                         <&clk IMX8MM_VIDEO_PLL1_OUT>,
> +                         <&clk IMX8MM_CLK_DSI_PHY_REF>;
> +       assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_266M>,
> +                         <&clk IMX8MM_VIDEO_PLL1_BYPASS>,
> +                         <&clk IMX8MM_VIDEO_PLL1_OUT>;
> +       assigned-clock-rates = <266000000>, <594000000>, <27000000>;
> +       interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
> +       phys = <&mipi_phy 0>;
> +       phy-names = "dsim";
> +       power-domains = <&dispmix_blk_ctl IMX8MM_BLK_CTL_PD_DISPMIX_MIPI_DSI>;
> +       samsung,burst-clock-frequency = <891000000>;
> +       samsung,esc-clock-frequency = <54000000>;
> +       samsung,pll-clock-frequency = <27000000>;
> +       status = "disabled";
> +
> +       ports {
> +          #address-cells = <1>;
> +          #size-cells = <0>;
> +
> +          port@0 {
> +             reg = <0>;
> +             #address-cells = <1>;
> +             #size-cells = <0>;
> +
> +             dsi_in_lcdif: endpoint@0 {
> +                reg = <0>;
> +                remote-endpoint = <&lcdif_out_dsi>;
> +             };
> +          };
> +
> +          port@1 {
> +             reg = <1>;
> +
> +             dsi_out_panel: endpoint {
> +                remote-endpoint = <&panel_in_dsi>;
> +             };
> +          };
> +       };
> +    };
> +
>    - |
>      #include <dt-bindings/clock/exynos5433.h>
>      #include <dt-bindings/gpio/gpio.h>
> -- 
> 2.25.1
> 
> 

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

* Re: [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge
       [not found] ` <YP2ZvoVQyvwTXP++@ravnborg.org>
@ 2021-07-25 17:13   ` Jagan Teki
  0 siblings, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-25 17:13 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, devicetree,
	linux-samsung-soc, dri-devel, NXP Linux Team, linux-amarula,
	linux-arm-kernel

Hi Sam,

On Sun, Jul 25, 2021 at 10:35 PM Sam Ravnborg <sam@ravnborg.org> wrote:
>
> Hi Jagan,
>
> On Sun, Jul 04, 2021 at 02:32:13PM +0530, Jagan Teki wrote:
> > This series supports common bridge support for Samsung MIPI DSIM
> > which is used in Exynos and i.MX8MM SoC's.
> >
> > The final bridge supports both the Exynos and i.MX8MM DSI devices.
> >
> > Right now bridge offers two sets of implementations.
> >
> > A. With component_ops and exynos specific code exclusively for
> >    exynos dsi drivers and it's legacy bindings.
> >
> > B. Without componenet_ops for newly implemented bridges and its
> >    users like i.MX8MM.
> >
> > The future plan is to fix the implementation A) by dropping
> > component_ops and fixing exynos specific code in order to make
> > the bridge more mature to use and the same is mentioned in
> > drivers TODO.
> >
> > Patch 0001 - 0006: Bridge conversion
> > Patch 0007 - 0017: Samsung MIPI DSIM bridge fixes, additions
> >
> > Tested in Engicam i.Core MX8M Mini SoM.
> >
> > Anyone interest, please have a look on this repo
> > https://github.com/openedev/linux/tree/070421-imx8mm-dsim
> >
> > Would appreciate anyone from the exynos team to test it on
> > the exynos platform?
> >
> > Any inputs?
>
> I really like where you are headign with this!
> No testing - sorry. But I will try to provide a bit of feedback on the
> individual patches.
>
> I hope you find a way to move forward with this.

Thanks for the response.

We have found some issues with Bridge conversion on existing exynos
drivers. The component based DSI drivers(like exynos) are difficult to
attach if it involves kms hotplug. kms hotplug would require drm
pointer and that pointer would only available after the bind call
finishes. But the bridge attach in bind call will defer till it find
the attached bridge.

Right now I'm trying to find the proper way to attach the bridges for
component based DSI drivers which involves kms hot-plug.

If you have any ideas on this, please let me know.

Thanks,
Jagan.

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

* Re: [RFC PATCH 06/17] drm/exynos: dsi: Handle exynos specifics via driver_data
       [not found]   ` <YP2el40V3K4R7ner@ravnborg.org>
@ 2021-07-25 17:31     ` Jagan Teki
  2021-08-13  6:50     ` Inki Dae
  1 sibling, 0 replies; 31+ messages in thread
From: Jagan Teki @ 2021-07-25 17:31 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, devicetree,
	linux-samsung-soc, dri-devel, NXP Linux Team, linux-amarula,
	linux-arm-kernel

On Sun, Jul 25, 2021 at 10:55 PM Sam Ravnborg <sam@ravnborg.org> wrote:
>
> On Sun, Jul 04, 2021 at 02:32:19PM +0530, Jagan Teki wrote:
> > Exynos DSI driver is actually a Samsung MIPI DSIM bridge
> > IP which is also used in i.MX8MM platforms.
> >
> > Right now the existing driver has some exynos drm specific
> > code bases like te_irq, crtc and component_ops.
> >
> > In order to switch this driver into a common bridge driver
> > We can see 2 options to handle the exynos specific code.
> >
> > A. Drop the component_ops, and rework other specifics.
> >    This may lead to more foundation work as it requires
> >    more changes in exynos drm drivers stack.
> >
> > B. Handle the exynos specifics via driver data, and make
> >    the common bridge work in different platforms and plan
> >    for option A in future.
> >
> > So, this patch is trying to add option B) changes to handle
> > exynos specifics via driver_data.
>
> We really should find someone that has the time, energy, knowledge and
> hardware that can include device_link support once anf for all for
> bridges.
> Then we would avoid hacks like this.
>
> I see no other options at the moment, but look forward for a better
> solution.

The real key problem here is hardware, unfortunately I'm unable to
find any proper exynos DSI hardware for myself to proceed atleast.

Thanks,
Jagan.

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

* Re: [RFC PATCH 05/17] drm/exynos: dsi: Get the mode from bridge
  2021-07-04  9:02 ` [RFC PATCH 05/17] drm/exynos: dsi: Get the mode from bridge Jagan Teki
@ 2021-07-29 13:20   ` Robert Foss
  0 siblings, 0 replies; 31+ messages in thread
From: Robert Foss @ 2021-07-29 13:20 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Andrzej Hajda, Neil Armstrong, Laurent Pinchart,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, dri-devel,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-samsung-soc,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	NXP Linux Team, linux-amarula

Hey Jagan,

On Sun, 4 Jul 2021 at 11:04, Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> Now the exynos dsi driver is fully aware of bridge
> handling, so get the display mode from bridge, mode_set
> API instead of legacy encoder crtc.
>
> This makes bridge usage more efficient instead of relying
> on encoder stack.
>
> Add mode_set in drm_bridge_funcs.
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index d828be07c325..99a1b8c22313 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -275,6 +275,7 @@ struct exynos_dsi {
>         u32 format;
>
>         int state;
> +       struct drm_display_mode mode;
>         struct drm_property *brightness;
>         struct completion completed;
>
> @@ -881,7 +882,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
>
>  static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)
>  {
> -       struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode;
> +       struct drm_display_mode *m = &dsi->mode;
>         unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;
>         u32 reg;
>
> @@ -1411,6 +1412,15 @@ static void exynos_dsi_bridge_disable(struct drm_bridge *bridge)
>         pm_runtime_put_sync(dsi->dev);
>  }
>
> +static void exynos_dsi_bridge_mode_set(struct drm_bridge *bridge,
> +                                      const struct drm_display_mode *mode,
> +                                      const struct drm_display_mode *adjusted_mode)
> +{
> +       struct exynos_dsi *dsi = bridge_to_dsi(bridge);
> +
> +       drm_mode_copy(&dsi->mode, adjusted_mode);
> +}
> +
>  static int exynos_dsi_panel_or_bridge(struct exynos_dsi *dsi,
>                                       struct device_node *node)
>  {
> @@ -1451,6 +1461,7 @@ static int exynos_dsi_bridge_attach(struct drm_bridge *bridge,
>  static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
>         .enable = exynos_dsi_bridge_enable,
>         .disable = exynos_dsi_bridge_disable,
> +       .mode_set = exynos_dsi_bridge_mode_set,

As far as I understand it, .enable(), .disable() &.mode_set() are
deprecated[1] and should be replaced by atomic_enable(),
atomic_disable() & atomic_enable() respectively.

[1] https://lore.kernel.org/dri-devel/20210722062246.2512666-8-sam@ravnborg.org/

>         .attach = exynos_dsi_bridge_attach,
>  };
>
> --
> 2.25.1
>

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

* Re: [RFC PATCH 06/17] drm/exynos: dsi: Handle exynos specifics via driver_data
       [not found]   ` <YP2el40V3K4R7ner@ravnborg.org>
  2021-07-25 17:31     ` Jagan Teki
@ 2021-08-13  6:50     ` Inki Dae
  2021-08-13 12:16       ` Laurent Pinchart
  1 sibling, 1 reply; 31+ messages in thread
From: Inki Dae @ 2021-08-13  6:50 UTC (permalink / raw)
  To: Sam Ravnborg, Jagan Teki
  Cc: Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Frieder Schrempf,
	Daniel Vetter, Marek Vasut, Krzysztof Kozlowski, Fabio Estevam,
	devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel

Hi,

21. 7. 26. 오전 2:25에 Sam Ravnborg 이(가) 쓴 글:
> On Sun, Jul 04, 2021 at 02:32:19PM +0530, Jagan Teki wrote:
>> Exynos DSI driver is actually a Samsung MIPI DSIM bridge
>> IP which is also used in i.MX8MM platforms.
>>
>> Right now the existing driver has some exynos drm specific
>> code bases like te_irq, crtc and component_ops.
>>
>> In order to switch this driver into a common bridge driver
>> We can see 2 options to handle the exynos specific code.
>>
>> A. Drop the component_ops, and rework other specifics.
>>    This may lead to more foundation work as it requires
>>    more changes in exynos drm drivers stack.
>>
>> B. Handle the exynos specifics via driver data, and make
>>    the common bridge work in different platforms and plan
>>    for option A in future.
>>
>> So, this patch is trying to add option B) changes to handle
>> exynos specifics via driver_data.
> 
> We really should find someone that has the time, energy, knowledge and
> hardware that can include device_link support once anf for all for
> bridges.
> Then we would avoid hacks like this.
> 
> I see no other options at the moment, but look forward for a better
> solution.
> 
> 	Sam
> 

I'm not sure that it's correct to share this mipi dsi driver with I.MX8MM SoC even though it's a same IP because this MIPI DSI device isn't peripheral device but in SoC.
It would mean that Exynos MIPI DSI device depends on SoC architecture, and Exynos and I.MX series are totally different SoC. So if we share the same driver for the MIPI DSI device then many things we didn't predict may happen in the future. I don't want to make Jagan's efforts in vain for the community but clarify whether this is correct way or not. If this is only the way we have to go then we could more focus on actual solution not such hack. Impossible work with Jagan alone I think.

So let's get started with a question,
- Is MIPI-DSI bridge device or Encoder device? I think that MIPI-DSI is a Encoder device managed by atomic KMS. If MIPI-DSI should be handled as bridge device then does now drm bridge framework provide everything to share one driver with one more SoC? I mean something that drm bridge has to consider for such driver support, which is shared with one more SoC.  


And Display mode - VIDEO and COMMAND mode - is generic type of MIPI DSI, and also componentised subsystem is a generic solution to resolve probing order issue not Exynos specific feature. These are driver specific ones not Exynos SoC I think. As SoC specific things should be considered, I think MIPI DSI Driver - interrupt handler and probing order things are really specific to device driver - should be separated but we could share the control part of the device.

I was busy with other projects so didn't care of Linux DRM world so there may be my missing something.

Thanks,
Inki Dae

> 
>>
>> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>> ---
>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 37 +++++++++++++++++++------
>>  1 file changed, 29 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>> index 99a1b8c22313..53d878d4d2d7 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>> @@ -250,6 +250,7 @@ struct exynos_dsi_driver_data {
>>  	unsigned int wait_for_reset;
>>  	unsigned int num_bits_resol;
>>  	const unsigned int *reg_values;
>> +	bool exynos_specific;
>>  };
>>  
>>  struct exynos_dsi {
>> @@ -459,6 +460,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = {
>>  	.wait_for_reset = 1,
>>  	.num_bits_resol = 11,
>>  	.reg_values = reg_values,
>> +	.exynos_specific = true,
>>  };
>>  
>>  static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
>> @@ -471,6 +473,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
>>  	.wait_for_reset = 1,
>>  	.num_bits_resol = 11,
>>  	.reg_values = reg_values,
>> +	.exynos_specific = true,
>>  };
>>  
>>  static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
>> @@ -481,6 +484,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
>>  	.wait_for_reset = 1,
>>  	.num_bits_resol = 11,
>>  	.reg_values = reg_values,
>> +	.exynos_specific = true,
>>  };
>>  
>>  static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
>> @@ -492,6 +496,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
>>  	.wait_for_reset = 0,
>>  	.num_bits_resol = 12,
>>  	.reg_values = exynos5433_reg_values,
>> +	.exynos_specific = true,
>>  };
>>  
>>  static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
>> @@ -503,6 +508,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
>>  	.wait_for_reset = 1,
>>  	.num_bits_resol = 12,
>>  	.reg_values = exynos5422_reg_values,
>> +	.exynos_specific = true,
>>  };
>>  
>>  static const struct of_device_id exynos_dsi_of_match[] = {
>> @@ -1484,7 +1490,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
>>  	 * If attached panel device is for command mode one, dsi should register
>>  	 * TE interrupt handler.
>>  	 */
>> -	if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
>> +	if (dsi->driver_data->exynos_specific &&
>> +	    !(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
>>  		int ret = exynos_dsi_register_te_irq(dsi, &device->dev);
>>  		if (ret)
>>  			return ret;
>> @@ -1495,8 +1502,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
>>  	dsi->lanes = device->lanes;
>>  	dsi->format = device->format;
>>  	dsi->mode_flags = device->mode_flags;
>> -	exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
>> -			!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
>> +	if (dsi->driver_data->exynos_specific)
>> +		exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
>> +					    !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
>>  
>>  	mutex_unlock(&drm->mode_config.mutex);
>>  
>> @@ -1515,7 +1523,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
>>  	if (drm->mode_config.poll_enabled)
>>  		drm_kms_helper_hotplug_event(drm);
>>  
>> -	exynos_dsi_unregister_te_irq(dsi);
>> +	if (dsi->driver_data->exynos_specific)
>> +		exynos_dsi_unregister_te_irq(dsi);
>>  
>>  	return 0;
>>  }
>> @@ -1737,6 +1746,15 @@ static int exynos_dsi_probe(struct platform_device *pdev)
>>  	if (ret)
>>  		return ret;
>>  
>> +	if (!dsi->driver_data->exynos_specific) {
>> +		ret = mipi_dsi_host_register(&dsi->dsi_host);
>> +		if (ret) {
>> +			dev_err(dev, "failed to register mipi dsi host: %d\n",
>> +				ret);
>> +			return ret;
>> +		}
>> +	}
>> +
>>  	platform_set_drvdata(pdev, dsi);
>>  
>>  	pm_runtime_enable(dev);
>> @@ -1747,9 +1765,11 @@ static int exynos_dsi_probe(struct platform_device *pdev)
>>  
>>  	drm_bridge_add(&dsi->bridge);
>>  
>> -	ret = component_add(dev, &exynos_dsi_component_ops);
>> -	if (ret)
>> -		goto err_disable_runtime;
>> +	if (dsi->driver_data->exynos_specific) {
>> +		ret = component_add(dev, &exynos_dsi_component_ops);
>> +		if (ret)
>> +			goto err_disable_runtime;
>> +	}
>>  
>>  	return 0;
>>  
>> @@ -1767,7 +1787,8 @@ static int exynos_dsi_remove(struct platform_device *pdev)
>>  
>>  	pm_runtime_disable(&pdev->dev);
>>  
>> -	component_del(&pdev->dev, &exynos_dsi_component_ops);
>> +	if (dsi->driver_data->exynos_specific)
>> +		component_del(&pdev->dev, &exynos_dsi_component_ops);
>>  
>>  	return 0;
>>  }
>> -- 
>> 2.25.1
> 

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

* Re: [RFC PATCH 06/17] drm/exynos: dsi: Handle exynos specifics via driver_data
  2021-08-13  6:50     ` Inki Dae
@ 2021-08-13 12:16       ` Laurent Pinchart
  2021-08-18  6:09         ` Inki Dae
  0 siblings, 1 reply; 31+ messages in thread
From: Laurent Pinchart @ 2021-08-13 12:16 UTC (permalink / raw)
  To: Inki Dae
  Cc: Sam Ravnborg, Jagan Teki, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, devicetree,
	linux-samsung-soc, dri-devel, NXP Linux Team, linux-amarula,
	linux-arm-kernel

Hi Inki,

On Fri, Aug 13, 2021 at 03:50:56PM +0900, Inki Dae wrote:
> 21. 7. 26. 오전 2:25에 Sam Ravnborg 이(가) 쓴 글:
> > On Sun, Jul 04, 2021 at 02:32:19PM +0530, Jagan Teki wrote:
> >> Exynos DSI driver is actually a Samsung MIPI DSIM bridge
> >> IP which is also used in i.MX8MM platforms.
> >>
> >> Right now the existing driver has some exynos drm specific
> >> code bases like te_irq, crtc and component_ops.
> >>
> >> In order to switch this driver into a common bridge driver
> >> We can see 2 options to handle the exynos specific code.
> >>
> >> A. Drop the component_ops, and rework other specifics.
> >>    This may lead to more foundation work as it requires
> >>    more changes in exynos drm drivers stack.
> >>
> >> B. Handle the exynos specifics via driver data, and make
> >>    the common bridge work in different platforms and plan
> >>    for option A in future.
> >>
> >> So, this patch is trying to add option B) changes to handle
> >> exynos specifics via driver_data.
> > 
> > We really should find someone that has the time, energy, knowledge and
> > hardware that can include device_link support once anf for all for
> > bridges.
> > Then we would avoid hacks like this.
> > 
> > I see no other options at the moment, but look forward for a better
> > solution.
> 
> I'm not sure that it's correct to share this mipi dsi driver with
> I.MX8MM SoC even though it's a same IP because this MIPI DSI device
> isn't peripheral device but in SoC.
>
> It would mean that Exynos MIPI DSI device depends on SoC architecture,
> and Exynos and I.MX series are totally different SoC. So if we share
> the same driver for the MIPI DSI device then many things we didn't
> predict may happen in the future.

Isn't that true for external components true thought ? Any driver shared
by multiple systems will face this issue, where it will be developed
with some use cases in mind, and regressions may happen when the driver
is then extended to support other use cases not required for the
original platform.

In general we don't want multiple drivers for the same IP core unless
there are valid technical reasons for that. It's the whole point of the
device tree, being able to describe how IP cores are integrated, so that
code can be reused across platforms. Of course, integration differences
between SoCs can sometimes vary wildly and require some amount of glue
code.

> I don't want to make Jagan's efforts
> in vain for the community but clarify whether this is correct way or
> not. If this is only the way we have to go then we could more focus on
> actual solution not such hack. Impossible work with Jagan alone I
> think.

I do agree that we need more correct solutions and less hacks in general
:-) The issues faced on Exynos also exist on other platforms, so it
would be much better to solve them well once that duplicating
implementations with less test coverage and reviews. There have been
efforts in the past to address some of these issues, which have resulted
in solutions such as the component framework. However, I'd argued that
we've never taken it to the last step, and have always stopped with half
solutions. The component framework, for instance, is painful to use, and
the handling of .remove() in most drivers is completely broken because
of that (not just because of that though, we have issues in the DRM core
that make hot-unplug just impossible to handle safetly).

> So let's get started with a question,
> - Is MIPI-DSI bridge device or Encoder device? I think that MIPI-DSI
> is a Encoder device managed by atomic KMS. If MIPI-DSI should be
> handled as bridge device then does now drm bridge framework provide
> everything to share one driver with one more SoC? I mean something
> that drm bridge has to consider for such driver support, which is
> shared with one more SoC.

The DRM "encoder" concept was a bit of a historical mistake that we are
stuck with as drm_encoder is exposed to userspace. It comes from a time
where nobody was envisioning chaining multiple encoders. DRM is moving
to modelling every component after the CRTC as a bridge. This brings
much more flexibility, and in that model, the drm_encoder becomes more
or less a stub.

The DRM bridge API has been extended in the past to support more
features, and if anything is still missing that makes it difficult to
move away from drm_encoder, we can of course address the issues in
drm_bridge.

> And Display mode - VIDEO and COMMAND mode - is generic type of MIPI
> DSI, and also componentised subsystem is a generic solution to resolve
> probing order issue not Exynos specific feature. These are driver
> specific ones not Exynos SoC I think. As SoC specific things should be
> considered, I think MIPI DSI Driver - interrupt handler and probing
> order things are really specific to device driver - should be
> separated but we could share the control part of the device.
> 
> I was busy with other projects so didn't care of Linux DRM world so
> there may be my missing something.
> 
> >> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> >> ---
> >>  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 37 +++++++++++++++++++------
> >>  1 file changed, 29 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> >> index 99a1b8c22313..53d878d4d2d7 100644
> >> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> >> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> >> @@ -250,6 +250,7 @@ struct exynos_dsi_driver_data {
> >>  	unsigned int wait_for_reset;
> >>  	unsigned int num_bits_resol;
> >>  	const unsigned int *reg_values;
> >> +	bool exynos_specific;
> >>  };
> >>  
> >>  struct exynos_dsi {
> >> @@ -459,6 +460,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = {
> >>  	.wait_for_reset = 1,
> >>  	.num_bits_resol = 11,
> >>  	.reg_values = reg_values,
> >> +	.exynos_specific = true,
> >>  };
> >>  
> >>  static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
> >> @@ -471,6 +473,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
> >>  	.wait_for_reset = 1,
> >>  	.num_bits_resol = 11,
> >>  	.reg_values = reg_values,
> >> +	.exynos_specific = true,
> >>  };
> >>  
> >>  static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
> >> @@ -481,6 +484,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
> >>  	.wait_for_reset = 1,
> >>  	.num_bits_resol = 11,
> >>  	.reg_values = reg_values,
> >> +	.exynos_specific = true,
> >>  };
> >>  
> >>  static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
> >> @@ -492,6 +496,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
> >>  	.wait_for_reset = 0,
> >>  	.num_bits_resol = 12,
> >>  	.reg_values = exynos5433_reg_values,
> >> +	.exynos_specific = true,
> >>  };
> >>  
> >>  static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
> >> @@ -503,6 +508,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
> >>  	.wait_for_reset = 1,
> >>  	.num_bits_resol = 12,
> >>  	.reg_values = exynos5422_reg_values,
> >> +	.exynos_specific = true,
> >>  };
> >>  
> >>  static const struct of_device_id exynos_dsi_of_match[] = {
> >> @@ -1484,7 +1490,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
> >>  	 * If attached panel device is for command mode one, dsi should register
> >>  	 * TE interrupt handler.
> >>  	 */
> >> -	if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
> >> +	if (dsi->driver_data->exynos_specific &&
> >> +	    !(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
> >>  		int ret = exynos_dsi_register_te_irq(dsi, &device->dev);
> >>  		if (ret)
> >>  			return ret;
> >> @@ -1495,8 +1502,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
> >>  	dsi->lanes = device->lanes;
> >>  	dsi->format = device->format;
> >>  	dsi->mode_flags = device->mode_flags;
> >> -	exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
> >> -			!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
> >> +	if (dsi->driver_data->exynos_specific)
> >> +		exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
> >> +					    !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
> >>  
> >>  	mutex_unlock(&drm->mode_config.mutex);
> >>  
> >> @@ -1515,7 +1523,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
> >>  	if (drm->mode_config.poll_enabled)
> >>  		drm_kms_helper_hotplug_event(drm);
> >>  
> >> -	exynos_dsi_unregister_te_irq(dsi);
> >> +	if (dsi->driver_data->exynos_specific)
> >> +		exynos_dsi_unregister_te_irq(dsi);
> >>  
> >>  	return 0;
> >>  }
> >> @@ -1737,6 +1746,15 @@ static int exynos_dsi_probe(struct platform_device *pdev)
> >>  	if (ret)
> >>  		return ret;
> >>  
> >> +	if (!dsi->driver_data->exynos_specific) {
> >> +		ret = mipi_dsi_host_register(&dsi->dsi_host);
> >> +		if (ret) {
> >> +			dev_err(dev, "failed to register mipi dsi host: %d\n",
> >> +				ret);
> >> +			return ret;
> >> +		}
> >> +	}
> >> +
> >>  	platform_set_drvdata(pdev, dsi);
> >>  
> >>  	pm_runtime_enable(dev);
> >> @@ -1747,9 +1765,11 @@ static int exynos_dsi_probe(struct platform_device *pdev)
> >>  
> >>  	drm_bridge_add(&dsi->bridge);
> >>  
> >> -	ret = component_add(dev, &exynos_dsi_component_ops);
> >> -	if (ret)
> >> -		goto err_disable_runtime;
> >> +	if (dsi->driver_data->exynos_specific) {
> >> +		ret = component_add(dev, &exynos_dsi_component_ops);
> >> +		if (ret)
> >> +			goto err_disable_runtime;
> >> +	}
> >>  
> >>  	return 0;
> >>  
> >> @@ -1767,7 +1787,8 @@ static int exynos_dsi_remove(struct platform_device *pdev)
> >>  
> >>  	pm_runtime_disable(&pdev->dev);
> >>  
> >> -	component_del(&pdev->dev, &exynos_dsi_component_ops);
> >> +	if (dsi->driver_data->exynos_specific)
> >> +		component_del(&pdev->dev, &exynos_dsi_component_ops);
> >>  
> >>  	return 0;
> >>  }

-- 
Regards,

Laurent Pinchart

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

* Re: [RFC PATCH 06/17] drm/exynos: dsi: Handle exynos specifics via driver_data
  2021-08-13 12:16       ` Laurent Pinchart
@ 2021-08-18  6:09         ` Inki Dae
  0 siblings, 0 replies; 31+ messages in thread
From: Inki Dae @ 2021-08-18  6:09 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Sam Ravnborg, Jagan Teki, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Frieder Schrempf, Daniel Vetter, Marek Vasut,
	Krzysztof Kozlowski, Fabio Estevam, devicetree,
	linux-samsung-soc, dri-devel, NXP Linux Team, linux-amarula,
	linux-arm-kernel

Hi Laurent,

21. 8. 13. 오후 9:16에 Laurent Pinchart 이(가) 쓴 글:
> Hi Inki,
> 
> On Fri, Aug 13, 2021 at 03:50:56PM +0900, Inki Dae wrote:
>> 21. 7. 26. 오전 2:25에 Sam Ravnborg 이(가) 쓴 글:
>>> On Sun, Jul 04, 2021 at 02:32:19PM +0530, Jagan Teki wrote:
>>>> Exynos DSI driver is actually a Samsung MIPI DSIM bridge
>>>> IP which is also used in i.MX8MM platforms.
>>>>
>>>> Right now the existing driver has some exynos drm specific
>>>> code bases like te_irq, crtc and component_ops.
>>>>
>>>> In order to switch this driver into a common bridge driver
>>>> We can see 2 options to handle the exynos specific code.
>>>>
>>>> A. Drop the component_ops, and rework other specifics.
>>>>    This may lead to more foundation work as it requires
>>>>    more changes in exynos drm drivers stack.
>>>>
>>>> B. Handle the exynos specifics via driver data, and make
>>>>    the common bridge work in different platforms and plan
>>>>    for option A in future.
>>>>
>>>> So, this patch is trying to add option B) changes to handle
>>>> exynos specifics via driver_data.
>>>
>>> We really should find someone that has the time, energy, knowledge and
>>> hardware that can include device_link support once anf for all for
>>> bridges.
>>> Then we would avoid hacks like this.
>>>
>>> I see no other options at the moment, but look forward for a better
>>> solution.
>>
>> I'm not sure that it's correct to share this mipi dsi driver with
>> I.MX8MM SoC even though it's a same IP because this MIPI DSI device
>> isn't peripheral device but in SoC.
>>
>> It would mean that Exynos MIPI DSI device depends on SoC architecture,
>> and Exynos and I.MX series are totally different SoC. So if we share
>> the same driver for the MIPI DSI device then many things we didn't
>> predict may happen in the future.
> 
> Isn't that true for external components true thought ? Any driver shared
> by multiple systems will face this issue, where it will be developed
> with some use cases in mind, and regressions may happen when the driver
> is then extended to support other use cases not required for the
> original platform.
> 
> In general we don't want multiple drivers for the same IP core unless
> there are valid technical reasons for that. It's the whole point of the
> device tree, being able to describe how IP cores are integrated, so that
> code can be reused across platforms. Of course, integration differences
> between SoCs can sometimes vary wildly and require some amount of glue
> code.

Agree with you. It would be a good chance to clarify what we need to share same device driver without any regress in this time.

> 
>> I don't want to make Jagan's efforts
>> in vain for the community but clarify whether this is correct way or
>> not. If this is only the way we have to go then we could more focus on
>> actual solution not such hack. Impossible work with Jagan alone I
>> think.
> 
> I do agree that we need more correct solutions and less hacks in general
> :-) The issues faced on Exynos also exist on other platforms, so it
> would be much better to solve them well once that duplicating
> implementations with less test coverage and reviews. There have been
> efforts in the past to address some of these issues, which have resulted
> in solutions such as the component framework. However, I'd argued that

Yeah, most of ARM systems have various separate devices but DRM subsytem wanted each ARM driver to work like one device driver for all of them. And the component framework has been adopted by several ARM DRM drivers for it including Exynos.

> we've never taken it to the last step, and have always stopped with half
> solutions. The component framework, for instance, is painful to use, and
> the handling of .remove() in most drivers is completely broken because
> of that (not just because of that though, we have issues in the DRM core
> that make hot-unplug just impossible to handle safetly).

This may be one of what we have to clarify. I think ARM DRM drivers need component framework or similar thing to address probing order issue.
So would we need to enhance existing compoent framework to be suitable for DRM subsystem, or introducing an alternative solution?

Otherwise, would there be some way to address the probing order issue without the compoment framework?

> 
>> So let's get started with a question,
>> - Is MIPI-DSI bridge device or Encoder device? I think that MIPI-DSI
>> is a Encoder device managed by atomic KMS. If MIPI-DSI should be
>> handled as bridge device then does now drm bridge framework provide
>> everything to share one driver with one more SoC? I mean something
>> that drm bridge has to consider for such driver support, which is
>> shared with one more SoC.
> 
> The DRM "encoder" concept was a bit of a historical mistake that we are
> stuck with as drm_encoder is exposed to userspace. It comes from a time
> where nobody was envisioning chaining multiple encoders. DRM is moving
> to modelling every component after the CRTC as a bridge. This brings

Thanks for explanation and seems correct direction. :) However, there would be something we have to address before changing the existing modeling because any regress shouldn't be allowed.

Thanks,
Inki Dae

> much more flexibility, and in that model, the drm_encoder becomes more
> or less a stub.
> 
> The DRM bridge API has been extended in the past to support more
> features, and if anything is still missing that makes it difficult to
> move away from drm_encoder, we can of course address the issues in
> drm_bridge.
> 
>> And Display mode - VIDEO and COMMAND mode - is generic type of MIPI
>> DSI, and also componentised subsystem is a generic solution to resolve
>> probing order issue not Exynos specific feature. These are driver
>> specific ones not Exynos SoC I think. As SoC specific things should be
>> considered, I think MIPI DSI Driver - interrupt handler and probing
>> order things are really specific to device driver - should be
>> separated but we could share the control part of the device.
>>
>> I was busy with other projects so didn't care of Linux DRM world so
>> there may be my missing something.
>>
>>>> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>>>> ---
>>>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 37 +++++++++++++++++++------
>>>>  1 file changed, 29 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>>>> index 99a1b8c22313..53d878d4d2d7 100644
>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
>>>> @@ -250,6 +250,7 @@ struct exynos_dsi_driver_data {
>>>>  	unsigned int wait_for_reset;
>>>>  	unsigned int num_bits_resol;
>>>>  	const unsigned int *reg_values;
>>>> +	bool exynos_specific;
>>>>  };
>>>>  
>>>>  struct exynos_dsi {
>>>> @@ -459,6 +460,7 @@ static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = {
>>>>  	.wait_for_reset = 1,
>>>>  	.num_bits_resol = 11,
>>>>  	.reg_values = reg_values,
>>>> +	.exynos_specific = true,
>>>>  };
>>>>  
>>>>  static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
>>>> @@ -471,6 +473,7 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
>>>>  	.wait_for_reset = 1,
>>>>  	.num_bits_resol = 11,
>>>>  	.reg_values = reg_values,
>>>> +	.exynos_specific = true,
>>>>  };
>>>>  
>>>>  static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
>>>> @@ -481,6 +484,7 @@ static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
>>>>  	.wait_for_reset = 1,
>>>>  	.num_bits_resol = 11,
>>>>  	.reg_values = reg_values,
>>>> +	.exynos_specific = true,
>>>>  };
>>>>  
>>>>  static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
>>>> @@ -492,6 +496,7 @@ static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
>>>>  	.wait_for_reset = 0,
>>>>  	.num_bits_resol = 12,
>>>>  	.reg_values = exynos5433_reg_values,
>>>> +	.exynos_specific = true,
>>>>  };
>>>>  
>>>>  static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
>>>> @@ -503,6 +508,7 @@ static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
>>>>  	.wait_for_reset = 1,
>>>>  	.num_bits_resol = 12,
>>>>  	.reg_values = exynos5422_reg_values,
>>>> +	.exynos_specific = true,
>>>>  };
>>>>  
>>>>  static const struct of_device_id exynos_dsi_of_match[] = {
>>>> @@ -1484,7 +1490,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
>>>>  	 * If attached panel device is for command mode one, dsi should register
>>>>  	 * TE interrupt handler.
>>>>  	 */
>>>> -	if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
>>>> +	if (dsi->driver_data->exynos_specific &&
>>>> +	    !(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
>>>>  		int ret = exynos_dsi_register_te_irq(dsi, &device->dev);
>>>>  		if (ret)
>>>>  			return ret;
>>>> @@ -1495,8 +1502,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
>>>>  	dsi->lanes = device->lanes;
>>>>  	dsi->format = device->format;
>>>>  	dsi->mode_flags = device->mode_flags;
>>>> -	exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
>>>> -			!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
>>>> +	if (dsi->driver_data->exynos_specific)
>>>> +		exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
>>>> +					    !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
>>>>  
>>>>  	mutex_unlock(&drm->mode_config.mutex);
>>>>  
>>>> @@ -1515,7 +1523,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
>>>>  	if (drm->mode_config.poll_enabled)
>>>>  		drm_kms_helper_hotplug_event(drm);
>>>>  
>>>> -	exynos_dsi_unregister_te_irq(dsi);
>>>> +	if (dsi->driver_data->exynos_specific)
>>>> +		exynos_dsi_unregister_te_irq(dsi);
>>>>  
>>>>  	return 0;
>>>>  }
>>>> @@ -1737,6 +1746,15 @@ static int exynos_dsi_probe(struct platform_device *pdev)
>>>>  	if (ret)
>>>>  		return ret;
>>>>  
>>>> +	if (!dsi->driver_data->exynos_specific) {
>>>> +		ret = mipi_dsi_host_register(&dsi->dsi_host);
>>>> +		if (ret) {
>>>> +			dev_err(dev, "failed to register mipi dsi host: %d\n",
>>>> +				ret);
>>>> +			return ret;
>>>> +		}
>>>> +	}
>>>> +
>>>>  	platform_set_drvdata(pdev, dsi);
>>>>  
>>>>  	pm_runtime_enable(dev);
>>>> @@ -1747,9 +1765,11 @@ static int exynos_dsi_probe(struct platform_device *pdev)
>>>>  
>>>>  	drm_bridge_add(&dsi->bridge);
>>>>  
>>>> -	ret = component_add(dev, &exynos_dsi_component_ops);
>>>> -	if (ret)
>>>> -		goto err_disable_runtime;
>>>> +	if (dsi->driver_data->exynos_specific) {
>>>> +		ret = component_add(dev, &exynos_dsi_component_ops);
>>>> +		if (ret)
>>>> +			goto err_disable_runtime;
>>>> +	}
>>>>  
>>>>  	return 0;
>>>>  
>>>> @@ -1767,7 +1787,8 @@ static int exynos_dsi_remove(struct platform_device *pdev)
>>>>  
>>>>  	pm_runtime_disable(&pdev->dev);
>>>>  
>>>> -	component_del(&pdev->dev, &exynos_dsi_component_ops);
>>>> +	if (dsi->driver_data->exynos_specific)
>>>> +		component_del(&pdev->dev, &exynos_dsi_component_ops);
>>>>  
>>>>  	return 0;
>>>>  }
> 

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

end of thread, other threads:[~2021-08-18  5:59 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-04  9:02 [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 01/17] drm/exynos: dsi: Convert to bridge driver Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 02/17] drm/exynos: dsi: Handle drm_device for bridge Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 03/17] drm/exynos: dsi: Use the drm_panel_bridge API Jagan Teki
2021-07-05 11:47   ` Marek Szyprowski
2021-07-05 12:00     ` Jagan Teki
2021-07-05 12:13       ` Marek Szyprowski
2021-07-05 12:34         ` Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 04/17] drm/exynos: dsi: Create bridge connector for encoder Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 05/17] drm/exynos: dsi: Get the mode from bridge Jagan Teki
2021-07-29 13:20   ` Robert Foss
2021-07-04  9:02 ` [RFC PATCH 06/17] drm/exynos: dsi: Handle exynos specifics via driver_data Jagan Teki
     [not found]   ` <YP2el40V3K4R7ner@ravnborg.org>
2021-07-25 17:31     ` Jagan Teki
2021-08-13  6:50     ` Inki Dae
2021-08-13 12:16       ` Laurent Pinchart
2021-08-18  6:09         ` Inki Dae
2021-07-04  9:02 ` [RFC PATCH 07/17] drm: bridge: Move exynos_drm_dsi into bridges Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 08/17] dt-bindings: display: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
2021-07-12 15:13   ` Rob Herring
2021-07-12 15:23     ` Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 09/17] drm: bridge: samsung-dsim: Add module init, exit Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 10/17] drm: bridge: samsung-dsim: Update the of_node for port(s) Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 11/17] drm: bridge: samsung-dsim: Find the possible DSI devices Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 12/17] dt-bindings: display: bridge: samsung,mipi-dsim: Add i.MX8MM support Jagan Teki
2021-07-14 22:59   ` Rob Herring
2021-07-04  9:02 ` [RFC PATCH 13/17] drm: bridge: samsung-dsim: " Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 14/17] drm: bridge: samsung-dsim: Add input_bus_flags Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 15/17] drm: bridge: samsung-dsim: Move DSI init in bridge enable Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 16/17] drm: bridge: samsung-dsim: Fix PLL_P offset Jagan Teki
2021-07-04  9:02 ` [RFC PATCH 17/17] drm: bridge: samsung-dsim: Add bridge mode_fixup Jagan Teki
     [not found] ` <YP2ZvoVQyvwTXP++@ravnborg.org>
2021-07-25 17:13   ` [RFC PATCH 00/17] drm: bridge: Samsung MIPI DSIM bridge Jagan Teki

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