dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge
@ 2022-04-08 16:20 ` Jagan Teki
  2022-04-08 16:20   ` [PATCH 01/11] drm: bridge: Add Samsung DSIM bridge driver Jagan Teki
                     ` (13 more replies)
  0 siblings, 14 replies; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:20 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

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

Previous RFC can be available here [1].

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

On, summary this patch-set break the entire DSIM driver into
- platform specific glue code for platform ops, component_ops.
- common bridge driver which handle platform glue init and invoke.

Patch 0000: 	Samsung DSIM bridge

Patch 0001: 	platform init flag via driver_data

Patch 0002/9:   bridge fixes, atomic API's

Patch 0010:	document fsl,imx8mm-mipi-dsim

Patch 0011:	add i.MX8MM DSIM support

Tested in Engicam i.Core MX8M Mini SoM.

Anyone interested, please have a look on this repo [2]

[2] https://github.com/openedev/kernel/tree/imx8mm-dsi-v1 
[1] https://lore.kernel.org/linux-arm-kernel/YP2j9k5SrZ2%2Fo2%2F5@ravnborg.org/T/

Any inputs?
Jagan.

Jagan Teki (11):
  drm: bridge: Add Samsung DSIM bridge driver
  drm: bridge: samsung-dsim: Handle platform init via driver_data
  drm: bridge: samsung-dsim: Mark PHY as optional
  drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable()
  drm: bridge: samsung-dsim: Fix PLL_P (PMS_P) offset
  drm: bridge: samsung-dsim: Add module init, exit
  drm: bridge: samsung-dsim: Add atomic_check
  drm: bridge: samsung-dsim: Add atomic_get_input_bus_fmts
  drm: bridge: samsung-dsim: Add input_bus_flags
  dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support
  drm: bridge: samsung-dsim: Add i.MX8MM support

 .../bindings/display/exynos/exynos_dsim.txt   |    1 +
 MAINTAINERS                                   |   12 +
 drivers/gpu/drm/bridge/Kconfig                |   12 +
 drivers/gpu/drm/bridge/Makefile               |    1 +
 drivers/gpu/drm/bridge/samsung-dsim.c         | 1803 +++++++++++++++++
 drivers/gpu/drm/exynos/Kconfig                |    1 +
 drivers/gpu/drm/exynos/exynos_drm_dsi.c       | 1704 +---------------
 include/drm/bridge/samsung-dsim.h             |   97 +
 8 files changed, 1982 insertions(+), 1649 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/samsung-dsim.c
 create mode 100644 include/drm/bridge/samsung-dsim.h

-- 
2.25.1


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

* [PATCH 01/11] drm: bridge: Add Samsung DSIM bridge driver
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
@ 2022-04-08 16:20   ` Jagan Teki
  2022-04-12  9:45     ` Marek Szyprowski
  2022-04-08 16:20   ` [PATCH 02/11] drm: bridge: samsung-dsim: Handle platform init via driver_data Jagan Teki
                     ` (12 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:20 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

Samsung MIPI DSIM controller is common DSI IP that can be used in various
SoCs like Exynos, i.MX8M Mini/Nano.

In order to access this DSI controller between various platform SoCs, the
ideal way to incorporate this in the drm stack is via the drm bridge driver.

This patch is trying to differentiate platform-specific and bridge driver
code and keep maintaining the exynos_drm_dsi.c code as platform-specific
glue code and samsung-dsim.c as a common bridge driver code.

- Exynos specific glue code is exynos specific te_irq, host_attach, and
  detach code along with conventional component_ops.

- Samsung DSIM is a bridge driver which is common across all platforms and
  the respective platform-specific glue will initialize at the end of the
  probe. The platform-specific operations and other glue calls will invoke
  on associate code areas.

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.

v1:
* Don't maintain component_ops in bridge driver
* Don't maintain platform glue code in bridge driver
* Add platform-specific glue code and make a common bridge

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 MAINTAINERS                             |   12 +
 drivers/gpu/drm/bridge/Kconfig          |   12 +
 drivers/gpu/drm/bridge/Makefile         |    1 +
 drivers/gpu/drm/bridge/samsung-dsim.c   | 1676 ++++++++++++++++++++++
 drivers/gpu/drm/exynos/Kconfig          |    1 +
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 1704 +----------------------
 include/drm/bridge/samsung-dsim.h       |   95 ++
 7 files changed, 1852 insertions(+), 1649 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/samsung-dsim.c
 create mode 100644 include/drm/bridge/samsung-dsim.h

diff --git a/MAINTAINERS b/MAINTAINERS
index db7fe53643c2..281d0f351854 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6227,6 +6227,18 @@ 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 <andrzej.hajda@intel.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
+F:	include/drm/bridge/samsung-dsim.h
+
 DRM DRIVER FOR SAMSUNG S6D27A1 PANELS
 M:	Markuss Broks <markuss.broks@gmail.com>
 S:	Maintained
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index e4cbf31797c5..10f839154e63 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -202,6 +202,18 @@ 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 COMMON_CLK
+	depends on OF && HAS_IOMEM
+	select DRM_KMS_HELPER
+	select DRM_MIPI_DSI
+	select DRM_PANEL_BRIDGE
+	help
+	  The Samsung MIPI DSIM bridge controller driver.
+	  This MIPI DSIM bridge can be found it on Exynos SoCs and
+	  NXP's i.MX8M Mini/Nano.
+
 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 425844c30495..d1d2e6414fc5 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -13,6 +13,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/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
new file mode 100644
index 000000000000..ee5d7e5518a6
--- /dev/null
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -0,0 +1,1676 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Samsung MIPI DSIM bridge driver.
+ *
+ * Copyright (C) 2021 Amarula Solutions(India)
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ *
+ * Based on exynos_drm_dsi from
+ * Tomasz Figa <t.figa@samsung.com>
+ */
+
+#include <asm/unaligned.h>
+
+#include <drm/bridge/samsung-dsim.h>
+#include <drm/drm_print.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/irq.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+/* returns true iff both arguments logically differs */
+#define NEQV(a, b) (!(a) ^ !(b))
+
+/* DSIM_STATUS */
+#define DSIM_STOP_STATE_DAT(x)		(((x) & 0xf) << 0)
+#define DSIM_STOP_STATE_CLK		(1 << 8)
+#define DSIM_TX_READY_HS_CLK		(1 << 10)
+#define DSIM_PLL_STABLE			(1 << 31)
+
+/* DSIM_SWRST */
+#define DSIM_FUNCRST			(1 << 16)
+#define DSIM_SWRST			(1 << 0)
+
+/* DSIM_TIMEOUT */
+#define DSIM_LPDR_TIMEOUT(x)		((x) << 0)
+#define DSIM_BTA_TIMEOUT(x)		((x) << 16)
+
+/* DSIM_CLKCTRL */
+#define DSIM_ESC_PRESCALER(x)		(((x) & 0xffff) << 0)
+#define DSIM_ESC_PRESCALER_MASK		(0xffff << 0)
+#define DSIM_LANE_ESC_CLK_EN_CLK	(1 << 19)
+#define DSIM_LANE_ESC_CLK_EN_DATA(x)	(((x) & 0xf) << 20)
+#define DSIM_LANE_ESC_CLK_EN_DATA_MASK	(0xf << 20)
+#define DSIM_BYTE_CLKEN			(1 << 24)
+#define DSIM_BYTE_CLK_SRC(x)		(((x) & 0x3) << 25)
+#define DSIM_BYTE_CLK_SRC_MASK		(0x3 << 25)
+#define DSIM_PLL_BYPASS			(1 << 27)
+#define DSIM_ESC_CLKEN			(1 << 28)
+#define DSIM_TX_REQUEST_HSCLK		(1 << 31)
+
+/* DSIM_CONFIG */
+#define DSIM_LANE_EN_CLK		(1 << 0)
+#define DSIM_LANE_EN(x)			(((x) & 0xf) << 1)
+#define DSIM_NUM_OF_DATA_LANE(x)	(((x) & 0x3) << 5)
+#define DSIM_SUB_PIX_FORMAT(x)		(((x) & 0x7) << 8)
+#define DSIM_MAIN_PIX_FORMAT_MASK	(0x7 << 12)
+#define DSIM_MAIN_PIX_FORMAT_RGB888	(0x7 << 12)
+#define DSIM_MAIN_PIX_FORMAT_RGB666	(0x6 << 12)
+#define DSIM_MAIN_PIX_FORMAT_RGB666_P	(0x5 << 12)
+#define DSIM_MAIN_PIX_FORMAT_RGB565	(0x4 << 12)
+#define DSIM_SUB_VC			(((x) & 0x3) << 16)
+#define DSIM_MAIN_VC			(((x) & 0x3) << 18)
+#define DSIM_HSA_MODE			(1 << 20)
+#define DSIM_HBP_MODE			(1 << 21)
+#define DSIM_HFP_MODE			(1 << 22)
+#define DSIM_HSE_MODE			(1 << 23)
+#define DSIM_AUTO_MODE			(1 << 24)
+#define DSIM_VIDEO_MODE			(1 << 25)
+#define DSIM_BURST_MODE			(1 << 26)
+#define DSIM_SYNC_INFORM		(1 << 27)
+#define DSIM_EOT_DISABLE		(1 << 28)
+#define DSIM_MFLUSH_VS			(1 << 29)
+/* This flag is valid only for exynos3250/3472/5260/5430 */
+#define DSIM_CLKLANE_STOP		(1 << 30)
+
+/* DSIM_ESCMODE */
+#define DSIM_TX_TRIGGER_RST		(1 << 4)
+#define DSIM_TX_LPDT_LP			(1 << 6)
+#define DSIM_CMD_LPDT_LP		(1 << 7)
+#define DSIM_FORCE_BTA			(1 << 16)
+#define DSIM_FORCE_STOP_STATE		(1 << 20)
+#define DSIM_STOP_STATE_CNT(x)		(((x) & 0x7ff) << 21)
+#define DSIM_STOP_STATE_CNT_MASK	(0x7ff << 21)
+
+/* DSIM_MDRESOL */
+#define DSIM_MAIN_STAND_BY		(1 << 31)
+#define DSIM_MAIN_VRESOL(x, num_bits)	(((x) & ((1 << (num_bits)) - 1)) << 16)
+#define DSIM_MAIN_HRESOL(x, num_bits)	(((x) & ((1 << (num_bits)) - 1)) << 0)
+
+/* DSIM_MVPORCH */
+#define DSIM_CMD_ALLOW(x)		((x) << 28)
+#define DSIM_STABLE_VFP(x)		((x) << 16)
+#define DSIM_MAIN_VBP(x)		((x) << 0)
+#define DSIM_CMD_ALLOW_MASK		(0xf << 28)
+#define DSIM_STABLE_VFP_MASK		(0x7ff << 16)
+#define DSIM_MAIN_VBP_MASK		(0x7ff << 0)
+
+/* DSIM_MHPORCH */
+#define DSIM_MAIN_HFP(x)		((x) << 16)
+#define DSIM_MAIN_HBP(x)		((x) << 0)
+#define DSIM_MAIN_HFP_MASK		((0xffff) << 16)
+#define DSIM_MAIN_HBP_MASK		((0xffff) << 0)
+
+/* DSIM_MSYNC */
+#define DSIM_MAIN_VSA(x)		((x) << 22)
+#define DSIM_MAIN_HSA(x)		((x) << 0)
+#define DSIM_MAIN_VSA_MASK		((0x3ff) << 22)
+#define DSIM_MAIN_HSA_MASK		((0xffff) << 0)
+
+/* DSIM_SDRESOL */
+#define DSIM_SUB_STANDY(x)		((x) << 31)
+#define DSIM_SUB_VRESOL(x)		((x) << 16)
+#define DSIM_SUB_HRESOL(x)		((x) << 0)
+#define DSIM_SUB_STANDY_MASK		((0x1) << 31)
+#define DSIM_SUB_VRESOL_MASK		((0x7ff) << 16)
+#define DSIM_SUB_HRESOL_MASK		((0x7ff) << 0)
+
+/* DSIM_INTSRC */
+#define DSIM_INT_PLL_STABLE		(1 << 31)
+#define DSIM_INT_SW_RST_RELEASE		(1 << 30)
+#define DSIM_INT_SFR_FIFO_EMPTY		(1 << 29)
+#define DSIM_INT_SFR_HDR_FIFO_EMPTY	(1 << 28)
+#define DSIM_INT_BTA			(1 << 25)
+#define DSIM_INT_FRAME_DONE		(1 << 24)
+#define DSIM_INT_RX_TIMEOUT		(1 << 21)
+#define DSIM_INT_BTA_TIMEOUT		(1 << 20)
+#define DSIM_INT_RX_DONE		(1 << 18)
+#define DSIM_INT_RX_TE			(1 << 17)
+#define DSIM_INT_RX_ACK			(1 << 16)
+#define DSIM_INT_RX_ECC_ERR		(1 << 15)
+#define DSIM_INT_RX_CRC_ERR		(1 << 14)
+
+/* DSIM_FIFOCTRL */
+#define DSIM_RX_DATA_FULL		(1 << 25)
+#define DSIM_RX_DATA_EMPTY		(1 << 24)
+#define DSIM_SFR_HEADER_FULL		(1 << 23)
+#define DSIM_SFR_HEADER_EMPTY		(1 << 22)
+#define DSIM_SFR_PAYLOAD_FULL		(1 << 21)
+#define DSIM_SFR_PAYLOAD_EMPTY		(1 << 20)
+#define DSIM_I80_HEADER_FULL		(1 << 19)
+#define DSIM_I80_HEADER_EMPTY		(1 << 18)
+#define DSIM_I80_PAYLOAD_FULL		(1 << 17)
+#define DSIM_I80_PAYLOAD_EMPTY		(1 << 16)
+#define DSIM_SD_HEADER_FULL		(1 << 15)
+#define DSIM_SD_HEADER_EMPTY		(1 << 14)
+#define DSIM_SD_PAYLOAD_FULL		(1 << 13)
+#define DSIM_SD_PAYLOAD_EMPTY		(1 << 12)
+#define DSIM_MD_HEADER_FULL		(1 << 11)
+#define DSIM_MD_HEADER_EMPTY		(1 << 10)
+#define DSIM_MD_PAYLOAD_FULL		(1 << 9)
+#define DSIM_MD_PAYLOAD_EMPTY		(1 << 8)
+#define DSIM_RX_FIFO			(1 << 4)
+#define DSIM_SFR_FIFO			(1 << 3)
+#define DSIM_I80_FIFO			(1 << 2)
+#define DSIM_SD_FIFO			(1 << 1)
+#define DSIM_MD_FIFO			(1 << 0)
+
+/* DSIM_PHYACCHR */
+#define DSIM_AFC_EN			(1 << 14)
+#define DSIM_AFC_CTL(x)			(((x) & 0x7) << 5)
+
+/* 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_M(x)			((x) << 4)
+#define DSIM_PLL_S(x)			((x) << 1)
+
+/* DSIM_PHYCTRL */
+#define DSIM_PHYCTRL_ULPS_EXIT(x)	(((x) & 0x1ff) << 0)
+#define DSIM_PHYCTRL_B_DPHYCTL_VREG_LP	(1 << 30)
+#define DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP	(1 << 14)
+
+/* DSIM_PHYTIMING */
+#define DSIM_PHYTIMING_LPX(x)		((x) << 8)
+#define DSIM_PHYTIMING_HS_EXIT(x)	((x) << 0)
+
+/* DSIM_PHYTIMING1 */
+#define DSIM_PHYTIMING1_CLK_PREPARE(x)	((x) << 24)
+#define DSIM_PHYTIMING1_CLK_ZERO(x)	((x) << 16)
+#define DSIM_PHYTIMING1_CLK_POST(x)	((x) << 8)
+#define DSIM_PHYTIMING1_CLK_TRAIL(x)	((x) << 0)
+
+/* DSIM_PHYTIMING2 */
+#define DSIM_PHYTIMING2_HS_PREPARE(x)	((x) << 16)
+#define DSIM_PHYTIMING2_HS_ZERO(x)	((x) << 8)
+#define DSIM_PHYTIMING2_HS_TRAIL(x)	((x) << 0)
+
+#define DSI_MAX_BUS_WIDTH		4
+#define DSI_NUM_VIRTUAL_CHANNELS	4
+#define DSI_TX_FIFO_SIZE		2048
+#define DSI_RX_FIFO_SIZE		256
+#define DSI_XFER_TIMEOUT_MS		100
+#define DSI_RX_FIFO_EMPTY		0x30800002
+
+#define OLD_SCLK_MIPI_CLK_NAME		"pll_clk"
+
+static const char *const clk_names[5] = {
+	"bus_clk",
+	"sclk_mipi",
+	"phyclk_mipidphy0_bitclkdiv8",
+	"phyclk_mipidphy0_rxclkesc0",
+	"sclk_rgb_vclk_to_dsim0"
+};
+
+enum samsung_dsim_transfer_type {
+	EXYNOS_DSI_TX,
+	EXYNOS_DSI_RX,
+};
+
+enum reg_idx {
+	DSIM_STATUS_REG,	/* Status register */
+	DSIM_SWRST_REG,		/* Software reset register */
+	DSIM_CLKCTRL_REG,	/* Clock control register */
+	DSIM_TIMEOUT_REG,	/* Time out register */
+	DSIM_CONFIG_REG,	/* Configuration register */
+	DSIM_ESCMODE_REG,	/* Escape mode register */
+	DSIM_MDRESOL_REG,
+	DSIM_MVPORCH_REG,	/* Main display Vporch register */
+	DSIM_MHPORCH_REG,	/* Main display Hporch register */
+	DSIM_MSYNC_REG,		/* Main display sync area register */
+	DSIM_INTSRC_REG,	/* Interrupt source register */
+	DSIM_INTMSK_REG,	/* Interrupt mask register */
+	DSIM_PKTHDR_REG,	/* Packet Header FIFO register */
+	DSIM_PAYLOAD_REG,	/* Payload FIFO register */
+	DSIM_RXFIFO_REG,	/* Read FIFO register */
+	DSIM_FIFOCTRL_REG,	/* FIFO status and control register */
+	DSIM_PLLCTRL_REG,	/* PLL control register */
+	DSIM_PHYCTRL_REG,
+	DSIM_PHYTIMING_REG,
+	DSIM_PHYTIMING1_REG,
+	DSIM_PHYTIMING2_REG,
+	NUM_REGS
+};
+
+static const unsigned int exynos_reg_ofs[] = {
+	[DSIM_STATUS_REG] =  0x00,
+	[DSIM_SWRST_REG] =  0x04,
+	[DSIM_CLKCTRL_REG] =  0x08,
+	[DSIM_TIMEOUT_REG] =  0x0c,
+	[DSIM_CONFIG_REG] =  0x10,
+	[DSIM_ESCMODE_REG] =  0x14,
+	[DSIM_MDRESOL_REG] =  0x18,
+	[DSIM_MVPORCH_REG] =  0x1c,
+	[DSIM_MHPORCH_REG] =  0x20,
+	[DSIM_MSYNC_REG] =  0x24,
+	[DSIM_INTSRC_REG] =  0x2c,
+	[DSIM_INTMSK_REG] =  0x30,
+	[DSIM_PKTHDR_REG] =  0x34,
+	[DSIM_PAYLOAD_REG] =  0x38,
+	[DSIM_RXFIFO_REG] =  0x3c,
+	[DSIM_FIFOCTRL_REG] =  0x44,
+	[DSIM_PLLCTRL_REG] =  0x4c,
+	[DSIM_PHYCTRL_REG] =  0x5c,
+	[DSIM_PHYTIMING_REG] =  0x64,
+	[DSIM_PHYTIMING1_REG] =  0x68,
+	[DSIM_PHYTIMING2_REG] =  0x6c,
+};
+
+static const unsigned int exynos5433_reg_ofs[] = {
+	[DSIM_STATUS_REG] = 0x04,
+	[DSIM_SWRST_REG] = 0x0C,
+	[DSIM_CLKCTRL_REG] = 0x10,
+	[DSIM_TIMEOUT_REG] = 0x14,
+	[DSIM_CONFIG_REG] = 0x18,
+	[DSIM_ESCMODE_REG] = 0x1C,
+	[DSIM_MDRESOL_REG] = 0x20,
+	[DSIM_MVPORCH_REG] = 0x24,
+	[DSIM_MHPORCH_REG] = 0x28,
+	[DSIM_MSYNC_REG] = 0x2C,
+	[DSIM_INTSRC_REG] = 0x34,
+	[DSIM_INTMSK_REG] = 0x38,
+	[DSIM_PKTHDR_REG] = 0x3C,
+	[DSIM_PAYLOAD_REG] = 0x40,
+	[DSIM_RXFIFO_REG] = 0x44,
+	[DSIM_FIFOCTRL_REG] = 0x4C,
+	[DSIM_PLLCTRL_REG] = 0x94,
+	[DSIM_PHYCTRL_REG] = 0xA4,
+	[DSIM_PHYTIMING_REG] = 0xB4,
+	[DSIM_PHYTIMING1_REG] = 0xB8,
+	[DSIM_PHYTIMING2_REG] = 0xBC,
+};
+
+enum reg_value_idx {
+	RESET_TYPE,
+	PLL_TIMER,
+	STOP_STATE_CNT,
+	PHYCTRL_ULPS_EXIT,
+	PHYCTRL_VREG_LP,
+	PHYCTRL_SLEW_UP,
+	PHYTIMING_LPX,
+	PHYTIMING_HS_EXIT,
+	PHYTIMING_CLK_PREPARE,
+	PHYTIMING_CLK_ZERO,
+	PHYTIMING_CLK_POST,
+	PHYTIMING_CLK_TRAIL,
+	PHYTIMING_HS_PREPARE,
+	PHYTIMING_HS_ZERO,
+	PHYTIMING_HS_TRAIL
+};
+
+static const unsigned int reg_values[] = {
+	[RESET_TYPE] = DSIM_SWRST,
+	[PLL_TIMER] = 500,
+	[STOP_STATE_CNT] = 0xf,
+	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0x0af),
+	[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(0x27),
+	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0d),
+	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x08),
+	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x09),
+	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x0d),
+	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b),
+};
+
+static const unsigned int exynos5422_reg_values[] = {
+	[RESET_TYPE] = DSIM_SWRST,
+	[PLL_TIMER] = 500,
+	[STOP_STATE_CNT] = 0xf,
+	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0xaf),
+	[PHYCTRL_VREG_LP] = 0,
+	[PHYCTRL_SLEW_UP] = 0,
+	[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x08),
+	[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0d),
+	[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x09),
+	[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x30),
+	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0e),
+	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x0a),
+	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x0c),
+	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x11),
+	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0d),
+};
+
+static const unsigned int exynos5433_reg_values[] = {
+	[RESET_TYPE] = DSIM_FUNCRST,
+	[PLL_TIMER] = 22200,
+	[STOP_STATE_CNT] = 0xa,
+	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0x190),
+	[PHYCTRL_VREG_LP] = DSIM_PHYCTRL_B_DPHYCTL_VREG_LP,
+	[PHYCTRL_SLEW_UP] = DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP,
+	[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x07),
+	[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0c),
+	[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x09),
+	[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x2d),
+	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0e),
+	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x09),
+	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x0b),
+	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x10),
+	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c),
+};
+
+static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
+	.reg_ofs = exynos_reg_ofs,
+	.plltmr_reg = 0x50,
+	.has_freqband = 1,
+	.has_clklane_stop = 1,
+	.num_clks = 2,
+	.max_freq = 1000,
+	.wait_for_reset = 1,
+	.num_bits_resol = 11,
+	.reg_values = reg_values,
+};
+
+static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
+	.reg_ofs = exynos_reg_ofs,
+	.plltmr_reg = 0x50,
+	.has_freqband = 1,
+	.has_clklane_stop = 1,
+	.num_clks = 2,
+	.max_freq = 1000,
+	.wait_for_reset = 1,
+	.num_bits_resol = 11,
+	.reg_values = reg_values,
+};
+
+static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
+	.reg_ofs = exynos_reg_ofs,
+	.plltmr_reg = 0x58,
+	.num_clks = 2,
+	.max_freq = 1000,
+	.wait_for_reset = 1,
+	.num_bits_resol = 11,
+	.reg_values = reg_values,
+};
+
+static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
+	.reg_ofs = exynos5433_reg_ofs,
+	.plltmr_reg = 0xa0,
+	.has_clklane_stop = 1,
+	.num_clks = 5,
+	.max_freq = 1500,
+	.wait_for_reset = 0,
+	.num_bits_resol = 12,
+	.reg_values = exynos5433_reg_values,
+};
+
+static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
+	.reg_ofs = exynos5433_reg_ofs,
+	.plltmr_reg = 0xa0,
+	.has_clklane_stop = 1,
+	.num_clks = 2,
+	.max_freq = 1500,
+	.wait_for_reset = 1,
+	.num_bits_resol = 12,
+	.reg_values = exynos5422_reg_values,
+};
+
+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",
+		.data = &exynos4_dsi_driver_data
+	},
+	{
+		.compatible = "samsung,exynos5410-mipi-dsi",
+		.data = &exynos5_dsi_driver_data
+	},
+	{
+		.compatible = "samsung,exynos5422-mipi-dsi",
+		.data = &exynos5422_dsi_driver_data
+	},
+	{
+		.compatible = "samsung,exynos5433-mipi-dsi",
+		.data = &exynos5433_dsi_driver_data
+	},
+	{ /* sentinel. */ }
+};
+
+static inline struct samsung_dsim *host_to_dsi(struct mipi_dsi_host *h)
+{
+	return container_of(h, struct samsung_dsim, dsi_host);
+}
+
+static inline struct samsung_dsim *bridge_to_dsi(struct drm_bridge *b)
+{
+	return container_of(b, struct samsung_dsim, bridge);
+}
+
+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 samsung_dsim_read(struct samsung_dsim *dsi, enum reg_idx idx)
+{
+	return readl(dsi->reg_base + dsi->driver_data->reg_ofs[idx]);
+}
+
+static void samsung_dsim_wait_for_reset(struct samsung_dsim *dsi)
+{
+	if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
+		return;
+
+	dev_err(dsi->dev, "timeout waiting for reset\n");
+}
+
+static void samsung_dsim_reset(struct samsung_dsim *dsi)
+{
+	u32 reset_val = dsi->driver_data->reg_values[RESET_TYPE];
+
+	reinit_completion(&dsi->completed);
+	samsung_dsim_write(dsi, DSIM_SWRST_REG, reset_val);
+}
+
+#ifndef MHZ
+#define MHZ	(1000*1000)
+#endif
+
+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 samsung_dsim_driver_data *driver_data = dsi->driver_data;
+	unsigned long best_freq = 0;
+	u32 min_delta = 0xffffffff;
+	u8 p_min, p_max;
+	u8 _p, best_p;
+	u16 _m, best_m;
+	u8 _s, best_s;
+
+	p_min = DIV_ROUND_UP(fin, (12 * MHZ));
+	p_max = fin / (6 * MHZ);
+
+	for (_p = p_min; _p <= p_max; ++_p) {
+		for (_s = 0; _s <= 5; ++_s) {
+			u64 tmp;
+			u32 delta;
+
+			tmp = (u64)fout * (_p << _s);
+			do_div(tmp, fin);
+			_m = tmp;
+			if (_m < 41 || _m > 125)
+				continue;
+
+			tmp = (u64)_m * fin;
+			do_div(tmp, _p);
+			if (tmp < 500 * MHZ ||
+					tmp > driver_data->max_freq * MHZ)
+				continue;
+
+			tmp = (u64)_m * fin;
+			do_div(tmp, _p << _s);
+
+			delta = abs(fout - tmp);
+			if (delta < min_delta) {
+				best_p = _p;
+				best_m = _m;
+				best_s = _s;
+				min_delta = delta;
+				best_freq = tmp;
+			}
+		}
+	}
+
+	if (best_freq) {
+		*p = best_p;
+		*m = best_m;
+		*s = best_s;
+	}
+
+	return best_freq;
+}
+
+static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
+					  unsigned long freq)
+{
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
+	unsigned long fin, fout;
+	int timeout;
+	u8 p, s;
+	u16 m;
+	u32 reg;
+
+	fin = dsi->pll_clk_rate;
+	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");
+		return 0;
+	}
+	dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d)\n", fout, p, m, s);
+
+	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);
+
+	if (driver_data->has_freqband) {
+		static const unsigned long freq_bands[] = {
+			100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
+			270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
+			510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
+			770 * MHZ, 870 * MHZ, 950 * MHZ,
+		};
+		int band;
+
+		for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
+			if (fout < freq_bands[band])
+				break;
+
+		dev_dbg(dsi->dev, "band %d\n", band);
+
+		reg |= DSIM_FREQ_BAND(band);
+	}
+
+	samsung_dsim_write(dsi, DSIM_PLLCTRL_REG, reg);
+
+	timeout = 1000;
+	do {
+		if (timeout-- == 0) {
+			dev_err(dsi->dev, "PLL failed to stabilize\n");
+			return 0;
+		}
+		reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
+	} while ((reg & DSIM_PLL_STABLE) == 0);
+
+	return fout;
+}
+
+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 = samsung_dsim_set_pll(dsi, dsi->burst_clk_rate);
+	if (!hs_clk) {
+		dev_err(dsi->dev, "failed to configure DSI PLL\n");
+		return -EFAULT;
+	}
+
+	byte_clk = hs_clk / 8;
+	esc_div = DIV_ROUND_UP(byte_clk, dsi->esc_clk_rate);
+	esc_clk = byte_clk / esc_div;
+
+	if (esc_clk > 20 * MHZ) {
+		++esc_div;
+		esc_clk = byte_clk / esc_div;
+	}
+
+	dev_dbg(dsi->dev, "hs_clk = %lu, byte_clk = %lu, esc_clk = %lu\n",
+		hs_clk, byte_clk, esc_clk);
+
+	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);
+	reg |= DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN
+			| DSIM_ESC_PRESCALER(esc_div)
+			| DSIM_LANE_ESC_CLK_EN_CLK
+			| DSIM_LANE_ESC_CLK_EN_DATA(BIT(dsi->lanes) - 1)
+			| DSIM_BYTE_CLK_SRC(0)
+			| DSIM_TX_REQUEST_HSCLK;
+	samsung_dsim_write(dsi, DSIM_CLKCTRL_REG, reg);
+
+	return 0;
+}
+
+static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
+{
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
+	const unsigned int *reg_values = driver_data->reg_values;
+	u32 reg;
+
+	if (driver_data->has_freqband)
+		return;
+
+	/* 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];
+	samsung_dsim_write(dsi, DSIM_PHYCTRL_REG, reg);
+
+	/*
+	 * T LPX: Transmitted length of any Low-Power state period
+	 * T HS-EXIT: Time that the transmitter drives LP-11 following a HS
+	 *	burst
+	 */
+	reg = reg_values[PHYTIMING_LPX] | reg_values[PHYTIMING_HS_EXIT];
+	samsung_dsim_write(dsi, DSIM_PHYTIMING_REG, reg);
+
+	/*
+	 * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00
+	 *	Line state immediately before the HS-0 Line state starting the
+	 *	HS transmission
+	 * T CLK-ZERO: Time that the transmitter drives the HS-0 state prior to
+	 *	transmitting the Clock.
+	 * T CLK_POST: Time that the transmitter continues to send HS clock
+	 *	after the last associated Data Lane has transitioned to LP Mode
+	 *	Interval is defined as the period from the end of T HS-TRAIL to
+	 *	the beginning of T CLK-TRAIL
+	 * T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
+	 *	the last payload clock bit of a HS transmission burst
+	 */
+	reg = reg_values[PHYTIMING_CLK_PREPARE] |
+		reg_values[PHYTIMING_CLK_ZERO] |
+		reg_values[PHYTIMING_CLK_POST] |
+		reg_values[PHYTIMING_CLK_TRAIL];
+
+	samsung_dsim_write(dsi, DSIM_PHYTIMING1_REG, reg);
+
+	/*
+	 * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00
+	 *	Line state immediately before the HS-0 Line state starting the
+	 *	HS transmission
+	 * T HS-ZERO: Time that the transmitter drives the HS-0 state prior to
+	 *	transmitting the Sync sequence.
+	 * T HS-TRAIL: Time that the transmitter drives the flipped differential
+	 *	state after last payload data bit of a HS transmission burst
+	 */
+	reg = reg_values[PHYTIMING_HS_PREPARE] | reg_values[PHYTIMING_HS_ZERO] |
+		reg_values[PHYTIMING_HS_TRAIL];
+	samsung_dsim_write(dsi, DSIM_PHYTIMING2_REG, reg);
+}
+
+static void samsung_dsim_disable_clock(struct samsung_dsim *dsi)
+{
+	u32 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);
+	samsung_dsim_write(dsi, DSIM_CLKCTRL_REG, reg);
+
+	reg = samsung_dsim_read(dsi, DSIM_PLLCTRL_REG);
+	reg &= ~DSIM_PLL_EN;
+	samsung_dsim_write(dsi, DSIM_PLLCTRL_REG, reg);
+}
+
+static void samsung_dsim_enable_lane(struct samsung_dsim *dsi, u32 lane)
+{
+	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));
+	samsung_dsim_write(dsi, DSIM_CONFIG_REG, reg);
+}
+
+static int samsung_dsim_init_link(struct samsung_dsim *dsi)
+{
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
+	int timeout;
+	u32 reg;
+	u32 lanes_mask;
+
+	/* Initialize FIFO pointers */
+	reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG);
+	reg &= ~0x1f;
+	samsung_dsim_write(dsi, DSIM_FIFOCTRL_REG, reg);
+
+	usleep_range(9000, 11000);
+
+	reg |= 0x1f;
+	samsung_dsim_write(dsi, DSIM_FIFOCTRL_REG, reg);
+	usleep_range(9000, 11000);
+
+	/* DSI configuration */
+	reg = 0;
+
+	/*
+	 * The first bit of mode_flags specifies display configuration.
+	 * If this bit is set[= MIPI_DSI_MODE_VIDEO], dsi will support video
+	 * mode, otherwise it will support command mode.
+	 */
+	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		reg |= DSIM_VIDEO_MODE;
+
+		/*
+		 * The user manual describes that following bits are ignored in
+		 * command mode.
+		 */
+		if (!(dsi->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH))
+			reg |= DSIM_MFLUSH_VS;
+		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+			reg |= DSIM_SYNC_INFORM;
+		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+			reg |= DSIM_BURST_MODE;
+		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_AUTO_VERT)
+			reg |= DSIM_AUTO_MODE;
+		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSE)
+			reg |= DSIM_HSE_MODE;
+		if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HFP))
+			reg |= DSIM_HFP_MODE;
+		if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HBP))
+			reg |= DSIM_HBP_MODE;
+		if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HSA))
+			reg |= DSIM_HSA_MODE;
+	}
+
+	if (!(dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
+		reg |= DSIM_EOT_DISABLE;
+
+	switch (dsi->format) {
+	case MIPI_DSI_FMT_RGB888:
+		reg |= DSIM_MAIN_PIX_FORMAT_RGB888;
+		break;
+	case MIPI_DSI_FMT_RGB666:
+		reg |= DSIM_MAIN_PIX_FORMAT_RGB666;
+		break;
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		reg |= DSIM_MAIN_PIX_FORMAT_RGB666_P;
+		break;
+	case MIPI_DSI_FMT_RGB565:
+		reg |= DSIM_MAIN_PIX_FORMAT_RGB565;
+		break;
+	default:
+		dev_err(dsi->dev, "invalid pixel format\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Use non-continuous clock mode if the periparal wants and
+	 * host controller supports
+	 *
+	 * In non-continous clock mode, host controller will turn off
+	 * the HS clock between high-speed transmissions to reduce
+	 * power consumption.
+	 */
+	if (driver_data->has_clklane_stop &&
+			dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
+		reg |= DSIM_CLKLANE_STOP;
+	}
+	samsung_dsim_write(dsi, DSIM_CONFIG_REG, reg);
+
+	lanes_mask = BIT(dsi->lanes) - 1;
+	samsung_dsim_enable_lane(dsi, lanes_mask);
+
+	/* Check clock and data lane state are stop state */
+	timeout = 100;
+	do {
+		if (timeout-- == 0) {
+			dev_err(dsi->dev, "waiting for bus lanes timed out\n");
+			return -EFAULT;
+		}
+
+		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 = 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]);
+	samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
+
+	reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff);
+	samsung_dsim_write(dsi, DSIM_TIMEOUT_REG, reg);
+
+	return 0;
+}
+
+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;
+	u32 reg;
+
+	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		reg = DSIM_CMD_ALLOW(0xf)
+			| DSIM_STABLE_VFP(m->vsync_start - m->vdisplay)
+			| DSIM_MAIN_VBP(m->vtotal - m->vsync_end);
+		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);
+		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);
+		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);
+
+	samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg);
+
+	dev_dbg(dsi->dev, "LCD size = %dx%d\n", m->hdisplay, m->vdisplay);
+}
+
+static void samsung_dsim_set_display_enable(struct samsung_dsim *dsi, bool enable)
+{
+	u32 reg;
+
+	reg = samsung_dsim_read(dsi, DSIM_MDRESOL_REG);
+	if (enable)
+		reg |= DSIM_MAIN_STAND_BY;
+	else
+		reg &= ~DSIM_MAIN_STAND_BY;
+	samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg);
+}
+
+static int samsung_dsim_wait_for_hdr_fifo(struct samsung_dsim *dsi)
+{
+	int timeout = 2000;
+
+	do {
+		u32 reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG);
+
+		if (!(reg & DSIM_SFR_HEADER_FULL))
+			return 0;
+
+		if (!cond_resched())
+			usleep_range(950, 1050);
+	} while (--timeout);
+
+	return -ETIMEDOUT;
+}
+
+static void samsung_dsim_set_cmd_lpm(struct samsung_dsim *dsi, bool lpm)
+{
+	u32 v = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
+
+	if (lpm)
+		v |= DSIM_CMD_LPDT_LP;
+	else
+		v &= ~DSIM_CMD_LPDT_LP;
+
+	samsung_dsim_write(dsi, DSIM_ESCMODE_REG, v);
+}
+
+static void samsung_dsim_force_bta(struct samsung_dsim *dsi)
+{
+	u32 v = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
+
+	v |= DSIM_FORCE_BTA;
+	samsung_dsim_write(dsi, DSIM_ESCMODE_REG, v);
+}
+
+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;
+	const u8 *payload = pkt->payload + xfer->tx_done;
+	u16 length = pkt->payload_length - xfer->tx_done;
+	bool first = !xfer->tx_done;
+	u32 reg;
+
+	dev_dbg(dev, "< xfer %pK: tx len %u, done %u, rx len %u, done %u\n",
+		xfer, length, xfer->tx_done, xfer->rx_len, xfer->rx_done);
+
+	if (length > DSI_TX_FIFO_SIZE)
+		length = DSI_TX_FIFO_SIZE;
+
+	xfer->tx_done += length;
+
+	/* Send payload */
+	while (length >= 4) {
+		reg = get_unaligned_le32(payload);
+		samsung_dsim_write(dsi, DSIM_PAYLOAD_REG, reg);
+		payload += 4;
+		length -= 4;
+	}
+
+	reg = 0;
+	switch (length) {
+	case 3:
+		reg |= payload[2] << 16;
+		fallthrough;
+	case 2:
+		reg |= payload[1] << 8;
+		fallthrough;
+	case 1:
+		reg |= payload[0];
+		samsung_dsim_write(dsi, DSIM_PAYLOAD_REG, reg);
+		break;
+	}
+
+	/* Send packet header */
+	if (!first)
+		return;
+
+	reg = get_unaligned_le32(pkt->header);
+	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)) {
+		samsung_dsim_set_cmd_lpm(dsi, xfer->flags & MIPI_DSI_MSG_USE_LPM);
+		dsi->state ^= DSIM_STATE_CMD_LPM;
+	}
+
+	samsung_dsim_write(dsi, DSIM_PKTHDR_REG, reg);
+
+	if (xfer->flags & MIPI_DSI_MSG_REQ_ACK)
+		samsung_dsim_force_bta(dsi);
+}
+
+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;
+	struct device *dev = dsi->dev;
+	u16 length;
+	u32 reg;
+
+	if (first) {
+		reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG);
+
+		switch (reg & 0x3f) {
+		case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
+		case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
+			if (xfer->rx_len >= 2) {
+				payload[1] = reg >> 16;
+				++xfer->rx_done;
+			}
+			fallthrough;
+		case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
+		case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
+			payload[0] = reg >> 8;
+			++xfer->rx_done;
+			xfer->rx_len = xfer->rx_done;
+			xfer->result = 0;
+			goto clear_fifo;
+		case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
+			dev_err(dev, "DSI Error Report: 0x%04x\n", (reg >> 8) & 0xffff);
+			xfer->result = 0;
+			goto clear_fifo;
+		}
+
+		length = (reg >> 8) & 0xffff;
+		if (length > xfer->rx_len) {
+			dev_err(dev,
+				"response too long (%u > %u bytes), stripping\n",
+				xfer->rx_len, length);
+			length = xfer->rx_len;
+		} else if (length < xfer->rx_len)
+			xfer->rx_len = length;
+	}
+
+	length = xfer->rx_len - xfer->rx_done;
+	xfer->rx_done += length;
+
+	/* Receive payload */
+	while (length >= 4) {
+		reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG);
+		payload[0] = (reg >>  0) & 0xff;
+		payload[1] = (reg >>  8) & 0xff;
+		payload[2] = (reg >> 16) & 0xff;
+		payload[3] = (reg >> 24) & 0xff;
+		payload += 4;
+		length -= 4;
+	}
+
+	if (length) {
+		reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG);
+		switch (length) {
+		case 3:
+			payload[2] = (reg >> 16) & 0xff;
+			fallthrough;
+		case 2:
+			payload[1] = (reg >> 8) & 0xff;
+			fallthrough;
+		case 1:
+			payload[0] = reg & 0xff;
+		}
+	}
+
+	if (xfer->rx_done == xfer->rx_len)
+		xfer->result = 0;
+
+clear_fifo:
+	length = DSI_RX_FIFO_SIZE / 4;
+	do {
+		reg = samsung_dsim_read(dsi, DSIM_RXFIFO_REG);
+		if (reg == DSI_RX_FIFO_EMPTY)
+			break;
+	} while (--length);
+}
+
+static void samsung_dsim_transfer_start(struct samsung_dsim *dsi)
+{
+	unsigned long flags;
+	struct samsung_dsim_transfer *xfer;
+	bool start = false;
+
+again:
+	spin_lock_irqsave(&dsi->transfer_lock, flags);
+
+	if (list_empty(&dsi->transfer_list)) {
+		spin_unlock_irqrestore(&dsi->transfer_lock, flags);
+		return;
+	}
+
+	xfer = list_first_entry(&dsi->transfer_list,
+				struct samsung_dsim_transfer, list);
+
+	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
+
+	if (xfer->packet.payload_length &&
+	    xfer->tx_done == xfer->packet.payload_length)
+		/* waiting for RX */
+		return;
+
+	samsung_dsim_send_to_fifo(dsi, xfer);
+
+	if (xfer->packet.payload_length || xfer->rx_len)
+		return;
+
+	xfer->result = 0;
+	complete(&xfer->completed);
+
+	spin_lock_irqsave(&dsi->transfer_lock, flags);
+
+	list_del_init(&xfer->list);
+	start = !list_empty(&dsi->transfer_list);
+
+	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
+
+	if (start)
+		goto again;
+}
+
+static bool samsung_dsim_transfer_finish(struct samsung_dsim *dsi)
+{
+	struct samsung_dsim_transfer *xfer;
+	unsigned long flags;
+	bool start = true;
+
+	spin_lock_irqsave(&dsi->transfer_lock, flags);
+
+	if (list_empty(&dsi->transfer_list)) {
+		spin_unlock_irqrestore(&dsi->transfer_lock, flags);
+		return false;
+	}
+
+	xfer = list_first_entry(&dsi->transfer_list,
+				struct samsung_dsim_transfer, list);
+
+	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
+
+	dev_dbg(dsi->dev,
+		"> xfer %pK, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n",
+		xfer, xfer->packet.payload_length, xfer->tx_done, xfer->rx_len,
+		xfer->rx_done);
+
+	if (xfer->tx_done != xfer->packet.payload_length)
+		return true;
+
+	if (xfer->rx_done != xfer->rx_len)
+		samsung_dsim_read_from_fifo(dsi, xfer);
+
+	if (xfer->rx_done != xfer->rx_len)
+		return true;
+
+	spin_lock_irqsave(&dsi->transfer_lock, flags);
+
+	list_del_init(&xfer->list);
+	start = !list_empty(&dsi->transfer_list);
+
+	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
+
+	if (!xfer->rx_len)
+		xfer->result = 0;
+	complete(&xfer->completed);
+
+	return start;
+}
+
+static void samsung_dsim_remove_transfer(struct samsung_dsim *dsi,
+					 struct samsung_dsim_transfer *xfer)
+{
+	unsigned long flags;
+	bool start;
+
+	spin_lock_irqsave(&dsi->transfer_lock, flags);
+
+	if (!list_empty(&dsi->transfer_list) &&
+	    xfer == list_first_entry(&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)
+			samsung_dsim_transfer_start(dsi);
+		return;
+	}
+
+	list_del_init(&xfer->list);
+
+	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
+}
+
+static int samsung_dsim_transfer(struct samsung_dsim *dsi,
+				 struct samsung_dsim_transfer *xfer)
+{
+	unsigned long flags;
+	bool stopped;
+
+	xfer->tx_done = 0;
+	xfer->rx_done = 0;
+	xfer->result = -ETIMEDOUT;
+	init_completion(&xfer->completed);
+
+	spin_lock_irqsave(&dsi->transfer_lock, flags);
+
+	stopped = list_empty(&dsi->transfer_list);
+	list_add_tail(&xfer->list, &dsi->transfer_list);
+
+	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
+
+	if (stopped)
+		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;
+
+		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;
+	}
+
+	/* Also covers hardware timeout condition */
+	return xfer->result;
+}
+
+static irqreturn_t samsung_dsim_irq(int irq, void *dev_id)
+{
+	struct samsung_dsim *dsi = dev_id;
+	u32 status;
+
+	status = samsung_dsim_read(dsi, DSIM_INTSRC_REG);
+	if (!status) {
+		static unsigned long j;
+
+		if (printk_timed_ratelimit(&j, 500))
+			dev_warn(dsi->dev, "spurious interrupt\n");
+		return IRQ_HANDLED;
+	}
+	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);
+		samsung_dsim_write(dsi, DSIM_INTMSK_REG, mask);
+		complete(&dsi->completed);
+		return IRQ_HANDLED;
+	}
+
+	if (!(status & (DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY |
+			DSIM_INT_PLL_STABLE)))
+		return IRQ_HANDLED;
+
+	if (samsung_dsim_transfer_finish(dsi))
+		samsung_dsim_transfer_start(dsi);
+
+	return IRQ_HANDLED;
+}
+
+static void samsung_dsim_enable_irq(struct samsung_dsim *dsi)
+{
+	const struct samsung_dsim_plat_data *pdata = dsi->plat_data;
+
+	enable_irq(dsi->irq);
+
+	if (pdata && pdata->irq_ops && pdata->irq_ops->enable)
+		pdata->irq_ops->enable(dsi);
+}
+
+static void samsung_dsim_disable_irq(struct samsung_dsim *dsi)
+{
+	const struct samsung_dsim_plat_data *pdata = dsi->plat_data;
+
+	if (pdata && pdata->irq_ops && pdata->irq_ops->disable)
+		pdata->irq_ops->disable(dsi);
+
+	disable_irq(dsi->irq);
+}
+
+static int samsung_dsim_init(struct samsung_dsim *dsi)
+{
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
+
+	samsung_dsim_reset(dsi);
+	samsung_dsim_enable_irq(dsi);
+
+	if (driver_data->reg_values[RESET_TYPE] == DSIM_FUNCRST)
+		samsung_dsim_enable_lane(dsi, BIT(dsi->lanes) - 1);
+
+	samsung_dsim_enable_clock(dsi);
+	if (driver_data->wait_for_reset)
+		samsung_dsim_wait_for_reset(dsi);
+	samsung_dsim_set_phy_ctrl(dsi);
+	samsung_dsim_init_link(dsi);
+
+	return 0;
+}
+
+static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge,
+					   struct drm_bridge_state *old_bridge_state)
+{
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
+	int ret;
+
+	if (dsi->state & DSIM_STATE_ENABLED)
+		return;
+
+	ret = pm_runtime_resume_and_get(dsi->dev);
+	if (ret < 0) {
+		dev_err(dsi->dev, "failed to enable DSI device.\n");
+		return;
+	}
+
+	dsi->state |= DSIM_STATE_ENABLED;
+}
+
+static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
+				       struct drm_bridge_state *old_bridge_state)
+{
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
+
+	samsung_dsim_set_display_mode(dsi);
+	samsung_dsim_set_display_enable(dsi, true);
+
+	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
+}
+
+static void samsung_dsim_atomic_disable(struct drm_bridge *bridge,
+					struct drm_bridge_state *old_bridge_state)
+{
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
+
+	if (!(dsi->state & DSIM_STATE_ENABLED))
+		return;
+
+	dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
+}
+
+static void samsung_dsim_atomic_post_disable(struct drm_bridge *bridge,
+					     struct drm_bridge_state *old_bridge_state)
+{
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
+
+	samsung_dsim_set_display_enable(dsi, false);
+
+	dsi->state &= ~DSIM_STATE_ENABLED;
+	pm_runtime_put_sync(dsi->dev);
+}
+
+static void samsung_dsim_mode_set(struct drm_bridge *bridge,
+				  const struct drm_display_mode *mode,
+				  const struct drm_display_mode *adjusted_mode)
+{
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
+
+	drm_mode_copy(&dsi->mode, adjusted_mode);
+}
+
+static int samsung_dsim_attach(struct drm_bridge *bridge,
+			       enum drm_bridge_attach_flags flags)
+{
+	struct samsung_dsim *dsi = bridge_to_dsi(bridge);
+
+	return drm_bridge_attach(bridge->encoder, dsi->out_bridge, NULL, flags);
+}
+
+static const struct drm_bridge_funcs samsung_dsim_bridge_funcs = {
+	.atomic_duplicate_state		= drm_atomic_helper_bridge_duplicate_state,
+	.atomic_destroy_state		= drm_atomic_helper_bridge_destroy_state,
+	.atomic_reset			= drm_atomic_helper_bridge_reset,
+	.atomic_pre_enable		= samsung_dsim_atomic_pre_enable,
+	.atomic_enable			= samsung_dsim_atomic_enable,
+	.atomic_disable			= samsung_dsim_atomic_disable,
+	.atomic_post_disable		= samsung_dsim_atomic_post_disable,
+	.mode_set			= samsung_dsim_mode_set,
+	.attach				= samsung_dsim_attach,
+};
+
+MODULE_DEVICE_TABLE(of, samsung_dsim_of_match);
+
+static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
+				    struct mipi_dsi_device *device)
+{
+	struct samsung_dsim *dsi = host_to_dsi(host);
+	const struct samsung_dsim_plat_data *pdata = dsi->plat_data;
+	struct device *dev = dsi->dev;
+	int ret;
+
+	dsi->out_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
+	if (IS_ERR(dsi->out_bridge)) {
+		ret = PTR_ERR(dsi->out_bridge);
+		DRM_DEV_ERROR(dev, "failed to find the bridge: %d\n", ret);
+		return ret;
+	}
+
+	DRM_DEV_INFO(dev, "Attached %s device\n", device->name);
+
+	drm_bridge_add(&dsi->bridge);
+
+	if (pdata && pdata->host_ops && pdata->host_ops->attach) {
+		ret = pdata->host_ops->attach(dsi, device);
+		if (ret < 0)
+			return ret;
+	}
+
+	dsi->lanes = device->lanes;
+	dsi->format = device->format;
+	dsi->mode_flags = device->mode_flags;
+
+	return 0;
+}
+
+static int samsung_dsim_host_detach(struct mipi_dsi_host *host,
+				    struct mipi_dsi_device *device)
+{
+	struct samsung_dsim *dsi = host_to_dsi(host);
+	const struct samsung_dsim_plat_data *pdata = dsi->plat_data;
+	int ret;
+
+	if (dsi->out_bridge->funcs->detach)
+		dsi->out_bridge->funcs->detach(dsi->out_bridge);
+
+	if (pdata && pdata->host_ops && pdata->host_ops->detach) {
+		ret = pdata->host_ops->detach(dsi, device);
+		if (ret < 0)
+			return ret;
+	}
+
+	drm_bridge_remove(&dsi->bridge);
+
+	return 0;
+}
+
+static ssize_t samsung_dsim_host_transfer(struct mipi_dsi_host *host,
+					  const struct mipi_dsi_msg *msg)
+{
+	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 = 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;
+
+	xfer.rx_len = msg->rx_len;
+	xfer.rx_payload = msg->rx_buf;
+	xfer.flags = msg->flags;
+
+	ret = samsung_dsim_transfer(dsi, &xfer);
+	return (ret < 0) ? ret : xfer.rx_done;
+}
+
+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 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);
+
+	if (ret < 0)
+		pr_err("%pOF: failed to get '%s' property\n", np, propname);
+
+	return ret;
+}
+
+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 = samsung_dsim_of_read_u32(node, "samsung,pll-clock-frequency",
+				       &dsi->pll_clk_rate);
+	if (ret < 0)
+		return ret;
+
+	ret = samsung_dsim_of_read_u32(node, "samsung,burst-clock-frequency",
+				       &dsi->burst_clk_rate);
+	if (ret < 0)
+		return ret;
+
+	ret = samsung_dsim_of_read_u32(node, "samsung,esc-clock-frequency",
+				       &dsi->esc_clk_rate);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+__weak const struct samsung_dsim_plat_data *
+samsung_dsim_plat_probe(struct samsung_dsim *priv)
+{
+	return NULL;
+}
+
+__weak void samsung_dsim_plat_remove(struct samsung_dsim *priv)
+{
+}
+
+static int samsung_dsim_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct samsung_dsim *dsi;
+	int ret, i;
+
+	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
+	if (!dsi)
+		return -ENOMEM;
+
+	init_completion(&dsi->completed);
+	spin_lock_init(&dsi->transfer_lock);
+	INIT_LIST_HEAD(&dsi->transfer_list);
+
+	dsi->dsi_host.ops = &samsung_dsim_ops;
+	dsi->dsi_host.dev = dev;
+
+	dsi->dev = dev;
+	dsi->driver_data = of_device_get_match_data(dev);
+
+	dsi->supplies[0].supply = "vddcore";
+	dsi->supplies[1].supply = "vddio";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies),
+				      dsi->supplies);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to get regulators\n");
+
+	dsi->clks = devm_kcalloc(dev, dsi->driver_data->num_clks,
+				 sizeof(*dsi->clks), GFP_KERNEL);
+	if (!dsi->clks)
+		return -ENOMEM;
+
+	for (i = 0; i < dsi->driver_data->num_clks; i++) {
+		dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
+		if (IS_ERR(dsi->clks[i])) {
+			if (strcmp(clk_names[i], "sclk_mipi") == 0) {
+				dsi->clks[i] = devm_clk_get(dev, OLD_SCLK_MIPI_CLK_NAME);
+				if (!IS_ERR(dsi->clks[i]))
+					continue;
+			}
+
+			dev_info(dev, "failed to get the clock: %s\n", clk_names[i]);
+			return PTR_ERR(dsi->clks[i]);
+		}
+	}
+
+	dsi->reg_base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(dsi->reg_base))
+		return PTR_ERR(dsi->reg_base);
+
+	dsi->phy = devm_phy_get(dev, "dsim");
+	if (IS_ERR(dsi->phy)) {
+		dev_info(dev, "failed to get dsim phy\n");
+		return PTR_ERR(dsi->phy);
+	}
+
+	dsi->irq = platform_get_irq(pdev, 0);
+	if (dsi->irq < 0)
+		return dsi->irq;
+
+	ret = devm_request_threaded_irq(dev, dsi->irq, NULL,
+					samsung_dsim_irq,
+					IRQF_ONESHOT | IRQF_NO_AUTOEN,
+					dev_name(dev), dsi);
+	if (ret) {
+		dev_err(dev, "failed to request dsi irq\n");
+		return ret;
+	}
+
+	ret = samsung_dsim_parse_dt(dsi);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, dsi);
+
+	pm_runtime_enable(dev);
+
+	dsi->bridge.funcs = &samsung_dsim_bridge_funcs;
+	dsi->bridge.of_node = dev->of_node;
+	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
+
+	dsi->plat_data = samsung_dsim_plat_probe(dsi);
+	if (IS_ERR(dsi->plat_data)) {
+		ret = PTR_ERR(dsi->plat_data);
+		goto err_disable_runtime;
+	}
+
+	return 0;
+
+err_disable_runtime:
+	pm_runtime_disable(dev);
+
+	return ret;
+}
+
+static int samsung_dsim_remove(struct platform_device *pdev)
+{
+	struct samsung_dsim *dsi = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+
+	samsung_dsim_plat_remove(dsi);
+
+	return 0;
+}
+
+static int __maybe_unused samsung_dsim_suspend(struct device *dev)
+{
+	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);
+
+	if (dsi->state & DSIM_STATE_INITIALIZED) {
+		dsi->state &= ~DSIM_STATE_INITIALIZED;
+
+		samsung_dsim_disable_clock(dsi);
+
+		samsung_dsim_disable_irq(dsi);
+	}
+
+	dsi->state &= ~DSIM_STATE_CMD_LPM;
+
+	phy_power_off(dsi->phy);
+
+	for (i = driver_data->num_clks - 1; i > -1; i--)
+		clk_disable_unprepare(dsi->clks[i]);
+
+	ret = regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
+	if (ret < 0)
+		dev_err(dsi->dev, "cannot disable regulators %d\n", ret);
+
+	return 0;
+}
+
+static int __maybe_unused samsung_dsim_resume(struct device *dev)
+{
+	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);
+	if (ret < 0) {
+		dev_err(dsi->dev, "cannot enable regulators %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < driver_data->num_clks; i++) {
+		ret = clk_prepare_enable(dsi->clks[i]);
+		if (ret < 0)
+			goto err_clk;
+	}
+
+	ret = phy_power_on(dsi->phy);
+	if (ret < 0) {
+		dev_err(dsi->dev, "cannot enable phy %d\n", ret);
+		goto err_clk;
+	}
+
+	return 0;
+
+err_clk:
+	while (--i > -1)
+		clk_disable_unprepare(dsi->clks[i]);
+	regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
+
+	return ret;
+}
+
+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 = samsung_dsim_probe,
+	.remove = samsung_dsim_remove,
+	.driver = {
+		   .name = "samsung-dsim",
+		   .owner = THIS_MODULE,
+		   .pm = &samsung_dsim_pm_ops,
+		   .of_match_table = samsung_dsim_of_match,
+	},
+};
+
+MODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>");
+MODULE_DESCRIPTION("Samsung MIPI DSIM controller bridge");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index f27cfd2a9726..784d379e3dd2 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -58,6 +58,7 @@ config DRM_EXYNOS_DSI
 	depends on DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || DRM_EXYNOS7_DECON
 	select DRM_MIPI_DSI
 	select DRM_PANEL
+	select DRM_SAMSUNG_DSIM
 	default n
 	help
 	  This enables support for Exynos MIPI-DSI device.
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 5fe262f31065..97167c5ffc78 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1,1338 +1,72 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Samsung SoC MIPI DSI Master driver.
+ * Samsung MIPI DSIM glue for Exynos SoCs.
  *
  * Copyright (c) 2014 Samsung Electronics Co., Ltd
  *
  * Contacts: Tomasz Figa <t.figa@samsung.com>
-*/
+ */
 
-#include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/component.h>
-#include <linux/gpio/consumer.h>
-#include <linux/irq.h>
-#include <linux/of_device.h>
-#include <linux/of_graph.h>
-#include <linux/phy/phy.h>
-#include <linux/regulator/consumer.h>
 
-#include <asm/unaligned.h>
-
-#include <video/mipi_display.h>
-#include <video/videomode.h>
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_bridge.h>
-#include <drm/drm_mipi_dsi.h>
-#include <drm/drm_print.h>
+#include <drm/bridge/samsung-dsim.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_drv.h"
 
-/* returns true iff both arguments logically differs */
-#define NEQV(a, b) (!(a) ^ !(b))
-
-/* DSIM_STATUS */
-#define DSIM_STOP_STATE_DAT(x)		(((x) & 0xf) << 0)
-#define DSIM_STOP_STATE_CLK		(1 << 8)
-#define DSIM_TX_READY_HS_CLK		(1 << 10)
-#define DSIM_PLL_STABLE			(1 << 31)
-
-/* DSIM_SWRST */
-#define DSIM_FUNCRST			(1 << 16)
-#define DSIM_SWRST			(1 << 0)
-
-/* DSIM_TIMEOUT */
-#define DSIM_LPDR_TIMEOUT(x)		((x) << 0)
-#define DSIM_BTA_TIMEOUT(x)		((x) << 16)
-
-/* DSIM_CLKCTRL */
-#define DSIM_ESC_PRESCALER(x)		(((x) & 0xffff) << 0)
-#define DSIM_ESC_PRESCALER_MASK		(0xffff << 0)
-#define DSIM_LANE_ESC_CLK_EN_CLK	(1 << 19)
-#define DSIM_LANE_ESC_CLK_EN_DATA(x)	(((x) & 0xf) << 20)
-#define DSIM_LANE_ESC_CLK_EN_DATA_MASK	(0xf << 20)
-#define DSIM_BYTE_CLKEN			(1 << 24)
-#define DSIM_BYTE_CLK_SRC(x)		(((x) & 0x3) << 25)
-#define DSIM_BYTE_CLK_SRC_MASK		(0x3 << 25)
-#define DSIM_PLL_BYPASS			(1 << 27)
-#define DSIM_ESC_CLKEN			(1 << 28)
-#define DSIM_TX_REQUEST_HSCLK		(1 << 31)
-
-/* DSIM_CONFIG */
-#define DSIM_LANE_EN_CLK		(1 << 0)
-#define DSIM_LANE_EN(x)			(((x) & 0xf) << 1)
-#define DSIM_NUM_OF_DATA_LANE(x)	(((x) & 0x3) << 5)
-#define DSIM_SUB_PIX_FORMAT(x)		(((x) & 0x7) << 8)
-#define DSIM_MAIN_PIX_FORMAT_MASK	(0x7 << 12)
-#define DSIM_MAIN_PIX_FORMAT_RGB888	(0x7 << 12)
-#define DSIM_MAIN_PIX_FORMAT_RGB666	(0x6 << 12)
-#define DSIM_MAIN_PIX_FORMAT_RGB666_P	(0x5 << 12)
-#define DSIM_MAIN_PIX_FORMAT_RGB565	(0x4 << 12)
-#define DSIM_SUB_VC			(((x) & 0x3) << 16)
-#define DSIM_MAIN_VC			(((x) & 0x3) << 18)
-#define DSIM_HSA_MODE			(1 << 20)
-#define DSIM_HBP_MODE			(1 << 21)
-#define DSIM_HFP_MODE			(1 << 22)
-#define DSIM_HSE_MODE			(1 << 23)
-#define DSIM_AUTO_MODE			(1 << 24)
-#define DSIM_VIDEO_MODE			(1 << 25)
-#define DSIM_BURST_MODE			(1 << 26)
-#define DSIM_SYNC_INFORM		(1 << 27)
-#define DSIM_EOT_DISABLE		(1 << 28)
-#define DSIM_MFLUSH_VS			(1 << 29)
-/* This flag is valid only for exynos3250/3472/5260/5430 */
-#define DSIM_CLKLANE_STOP		(1 << 30)
-
-/* DSIM_ESCMODE */
-#define DSIM_TX_TRIGGER_RST		(1 << 4)
-#define DSIM_TX_LPDT_LP			(1 << 6)
-#define DSIM_CMD_LPDT_LP		(1 << 7)
-#define DSIM_FORCE_BTA			(1 << 16)
-#define DSIM_FORCE_STOP_STATE		(1 << 20)
-#define DSIM_STOP_STATE_CNT(x)		(((x) & 0x7ff) << 21)
-#define DSIM_STOP_STATE_CNT_MASK	(0x7ff << 21)
-
-/* DSIM_MDRESOL */
-#define DSIM_MAIN_STAND_BY		(1 << 31)
-#define DSIM_MAIN_VRESOL(x, num_bits)	(((x) & ((1 << (num_bits)) - 1)) << 16)
-#define DSIM_MAIN_HRESOL(x, num_bits)	(((x) & ((1 << (num_bits)) - 1)) << 0)
-
-/* DSIM_MVPORCH */
-#define DSIM_CMD_ALLOW(x)		((x) << 28)
-#define DSIM_STABLE_VFP(x)		((x) << 16)
-#define DSIM_MAIN_VBP(x)		((x) << 0)
-#define DSIM_CMD_ALLOW_MASK		(0xf << 28)
-#define DSIM_STABLE_VFP_MASK		(0x7ff << 16)
-#define DSIM_MAIN_VBP_MASK		(0x7ff << 0)
-
-/* DSIM_MHPORCH */
-#define DSIM_MAIN_HFP(x)		((x) << 16)
-#define DSIM_MAIN_HBP(x)		((x) << 0)
-#define DSIM_MAIN_HFP_MASK		((0xffff) << 16)
-#define DSIM_MAIN_HBP_MASK		((0xffff) << 0)
-
-/* DSIM_MSYNC */
-#define DSIM_MAIN_VSA(x)		((x) << 22)
-#define DSIM_MAIN_HSA(x)		((x) << 0)
-#define DSIM_MAIN_VSA_MASK		((0x3ff) << 22)
-#define DSIM_MAIN_HSA_MASK		((0xffff) << 0)
-
-/* DSIM_SDRESOL */
-#define DSIM_SUB_STANDY(x)		((x) << 31)
-#define DSIM_SUB_VRESOL(x)		((x) << 16)
-#define DSIM_SUB_HRESOL(x)		((x) << 0)
-#define DSIM_SUB_STANDY_MASK		((0x1) << 31)
-#define DSIM_SUB_VRESOL_MASK		((0x7ff) << 16)
-#define DSIM_SUB_HRESOL_MASK		((0x7ff) << 0)
-
-/* DSIM_INTSRC */
-#define DSIM_INT_PLL_STABLE		(1 << 31)
-#define DSIM_INT_SW_RST_RELEASE		(1 << 30)
-#define DSIM_INT_SFR_FIFO_EMPTY		(1 << 29)
-#define DSIM_INT_SFR_HDR_FIFO_EMPTY	(1 << 28)
-#define DSIM_INT_BTA			(1 << 25)
-#define DSIM_INT_FRAME_DONE		(1 << 24)
-#define DSIM_INT_RX_TIMEOUT		(1 << 21)
-#define DSIM_INT_BTA_TIMEOUT		(1 << 20)
-#define DSIM_INT_RX_DONE		(1 << 18)
-#define DSIM_INT_RX_TE			(1 << 17)
-#define DSIM_INT_RX_ACK			(1 << 16)
-#define DSIM_INT_RX_ECC_ERR		(1 << 15)
-#define DSIM_INT_RX_CRC_ERR		(1 << 14)
-
-/* DSIM_FIFOCTRL */
-#define DSIM_RX_DATA_FULL		(1 << 25)
-#define DSIM_RX_DATA_EMPTY		(1 << 24)
-#define DSIM_SFR_HEADER_FULL		(1 << 23)
-#define DSIM_SFR_HEADER_EMPTY		(1 << 22)
-#define DSIM_SFR_PAYLOAD_FULL		(1 << 21)
-#define DSIM_SFR_PAYLOAD_EMPTY		(1 << 20)
-#define DSIM_I80_HEADER_FULL		(1 << 19)
-#define DSIM_I80_HEADER_EMPTY		(1 << 18)
-#define DSIM_I80_PAYLOAD_FULL		(1 << 17)
-#define DSIM_I80_PAYLOAD_EMPTY		(1 << 16)
-#define DSIM_SD_HEADER_FULL		(1 << 15)
-#define DSIM_SD_HEADER_EMPTY		(1 << 14)
-#define DSIM_SD_PAYLOAD_FULL		(1 << 13)
-#define DSIM_SD_PAYLOAD_EMPTY		(1 << 12)
-#define DSIM_MD_HEADER_FULL		(1 << 11)
-#define DSIM_MD_HEADER_EMPTY		(1 << 10)
-#define DSIM_MD_PAYLOAD_FULL		(1 << 9)
-#define DSIM_MD_PAYLOAD_EMPTY		(1 << 8)
-#define DSIM_RX_FIFO			(1 << 4)
-#define DSIM_SFR_FIFO			(1 << 3)
-#define DSIM_I80_FIFO			(1 << 2)
-#define DSIM_SD_FIFO			(1 << 1)
-#define DSIM_MD_FIFO			(1 << 0)
-
-/* DSIM_PHYACCHR */
-#define DSIM_AFC_EN			(1 << 14)
-#define DSIM_AFC_CTL(x)			(((x) & 0x7) << 5)
-
-/* 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_M(x)			((x) << 4)
-#define DSIM_PLL_S(x)			((x) << 1)
-
-/* DSIM_PHYCTRL */
-#define DSIM_PHYCTRL_ULPS_EXIT(x)	(((x) & 0x1ff) << 0)
-#define DSIM_PHYCTRL_B_DPHYCTL_VREG_LP	(1 << 30)
-#define DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP	(1 << 14)
-
-/* DSIM_PHYTIMING */
-#define DSIM_PHYTIMING_LPX(x)		((x) << 8)
-#define DSIM_PHYTIMING_HS_EXIT(x)	((x) << 0)
-
-/* DSIM_PHYTIMING1 */
-#define DSIM_PHYTIMING1_CLK_PREPARE(x)	((x) << 24)
-#define DSIM_PHYTIMING1_CLK_ZERO(x)	((x) << 16)
-#define DSIM_PHYTIMING1_CLK_POST(x)	((x) << 8)
-#define DSIM_PHYTIMING1_CLK_TRAIL(x)	((x) << 0)
-
-/* DSIM_PHYTIMING2 */
-#define DSIM_PHYTIMING2_HS_PREPARE(x)	((x) << 16)
-#define DSIM_PHYTIMING2_HS_ZERO(x)	((x) << 8)
-#define DSIM_PHYTIMING2_HS_TRAIL(x)	((x) << 0)
-
-#define DSI_MAX_BUS_WIDTH		4
-#define DSI_NUM_VIRTUAL_CHANNELS	4
-#define DSI_TX_FIFO_SIZE		2048
-#define DSI_RX_FIFO_SIZE		256
-#define DSI_XFER_TIMEOUT_MS		100
-#define DSI_RX_FIFO_EMPTY		0x30800002
-
-#define OLD_SCLK_MIPI_CLK_NAME "pll_clk"
-
-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 {
-	EXYNOS_DSI_TX,
-	EXYNOS_DSI_RX,
-};
-
-struct exynos_dsi_transfer {
-	struct list_head list;
-	struct completion completed;
-	int result;
-	struct mipi_dsi_packet packet;
-	u16 flags;
-	u16 tx_done;
-
-	u8 *rx_payload;
-	u16 rx_len;
-	u16 rx_done;
-};
-
-#define DSIM_STATE_ENABLED		BIT(0)
-#define DSIM_STATE_INITIALIZED		BIT(1)
-#define DSIM_STATE_CMD_LPM		BIT(2)
-#define DSIM_STATE_VIDOUT_AVAILABLE	BIT(3)
-
-struct exynos_dsi_driver_data {
-	const unsigned int *reg_ofs;
-	unsigned int plltmr_reg;
-	unsigned int has_freqband:1;
-	unsigned int has_clklane_stop:1;
-	unsigned int num_clks;
-	unsigned int max_freq;
-	unsigned int wait_for_reset;
-	unsigned int num_bits_resol;
-	const unsigned int *reg_values;
-};
-
 struct exynos_dsi {
 	struct drm_encoder encoder;
-	struct mipi_dsi_host dsi_host;
-	struct drm_bridge bridge;
-	struct drm_bridge *out_bridge;
-	struct device *dev;
-	struct drm_display_mode mode;
+	struct samsung_dsim *priv;
 
-	void __iomem *reg_base;
-	struct phy *phy;
-	struct clk **clks;
-	struct regulator_bulk_data supplies[2];
-	int irq;
 	struct gpio_desc *te_gpio;
 
-	u32 pll_clk_rate;
-	u32 burst_clk_rate;
-	u32 esc_clk_rate;
-	u32 lanes;
-	u32 mode_flags;
-	u32 format;
-
-	int state;
-	struct drm_property *brightness;
-	struct completion completed;
-
-	spinlock_t transfer_lock; /* protects transfer_list */
-	struct list_head transfer_list;
-
-	const struct exynos_dsi_driver_data *driver_data;
-};
-
-#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
-
-static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b)
-{
-	return container_of(b, struct exynos_dsi, bridge);
-}
-
-enum reg_idx {
-	DSIM_STATUS_REG,	/* Status register */
-	DSIM_SWRST_REG,		/* Software reset register */
-	DSIM_CLKCTRL_REG,	/* Clock control register */
-	DSIM_TIMEOUT_REG,	/* Time out register */
-	DSIM_CONFIG_REG,	/* Configuration register */
-	DSIM_ESCMODE_REG,	/* Escape mode register */
-	DSIM_MDRESOL_REG,
-	DSIM_MVPORCH_REG,	/* Main display Vporch register */
-	DSIM_MHPORCH_REG,	/* Main display Hporch register */
-	DSIM_MSYNC_REG,		/* Main display sync area register */
-	DSIM_INTSRC_REG,	/* Interrupt source register */
-	DSIM_INTMSK_REG,	/* Interrupt mask register */
-	DSIM_PKTHDR_REG,	/* Packet Header FIFO register */
-	DSIM_PAYLOAD_REG,	/* Payload FIFO register */
-	DSIM_RXFIFO_REG,	/* Read FIFO register */
-	DSIM_FIFOCTRL_REG,	/* FIFO status and control register */
-	DSIM_PLLCTRL_REG,	/* PLL control register */
-	DSIM_PHYCTRL_REG,
-	DSIM_PHYTIMING_REG,
-	DSIM_PHYTIMING1_REG,
-	DSIM_PHYTIMING2_REG,
-	NUM_REGS
-};
-
-static inline void exynos_dsi_write(struct exynos_dsi *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)
-{
-	return readl(dsi->reg_base + dsi->driver_data->reg_ofs[idx]);
-}
-
-static const unsigned int exynos_reg_ofs[] = {
-	[DSIM_STATUS_REG] =  0x00,
-	[DSIM_SWRST_REG] =  0x04,
-	[DSIM_CLKCTRL_REG] =  0x08,
-	[DSIM_TIMEOUT_REG] =  0x0c,
-	[DSIM_CONFIG_REG] =  0x10,
-	[DSIM_ESCMODE_REG] =  0x14,
-	[DSIM_MDRESOL_REG] =  0x18,
-	[DSIM_MVPORCH_REG] =  0x1c,
-	[DSIM_MHPORCH_REG] =  0x20,
-	[DSIM_MSYNC_REG] =  0x24,
-	[DSIM_INTSRC_REG] =  0x2c,
-	[DSIM_INTMSK_REG] =  0x30,
-	[DSIM_PKTHDR_REG] =  0x34,
-	[DSIM_PAYLOAD_REG] =  0x38,
-	[DSIM_RXFIFO_REG] =  0x3c,
-	[DSIM_FIFOCTRL_REG] =  0x44,
-	[DSIM_PLLCTRL_REG] =  0x4c,
-	[DSIM_PHYCTRL_REG] =  0x5c,
-	[DSIM_PHYTIMING_REG] =  0x64,
-	[DSIM_PHYTIMING1_REG] =  0x68,
-	[DSIM_PHYTIMING2_REG] =  0x6c,
-};
-
-static const unsigned int exynos5433_reg_ofs[] = {
-	[DSIM_STATUS_REG] = 0x04,
-	[DSIM_SWRST_REG] = 0x0C,
-	[DSIM_CLKCTRL_REG] = 0x10,
-	[DSIM_TIMEOUT_REG] = 0x14,
-	[DSIM_CONFIG_REG] = 0x18,
-	[DSIM_ESCMODE_REG] = 0x1C,
-	[DSIM_MDRESOL_REG] = 0x20,
-	[DSIM_MVPORCH_REG] = 0x24,
-	[DSIM_MHPORCH_REG] = 0x28,
-	[DSIM_MSYNC_REG] = 0x2C,
-	[DSIM_INTSRC_REG] = 0x34,
-	[DSIM_INTMSK_REG] = 0x38,
-	[DSIM_PKTHDR_REG] = 0x3C,
-	[DSIM_PAYLOAD_REG] = 0x40,
-	[DSIM_RXFIFO_REG] = 0x44,
-	[DSIM_FIFOCTRL_REG] = 0x4C,
-	[DSIM_PLLCTRL_REG] = 0x94,
-	[DSIM_PHYCTRL_REG] = 0xA4,
-	[DSIM_PHYTIMING_REG] = 0xB4,
-	[DSIM_PHYTIMING1_REG] = 0xB8,
-	[DSIM_PHYTIMING2_REG] = 0xBC,
-};
-
-enum reg_value_idx {
-	RESET_TYPE,
-	PLL_TIMER,
-	STOP_STATE_CNT,
-	PHYCTRL_ULPS_EXIT,
-	PHYCTRL_VREG_LP,
-	PHYCTRL_SLEW_UP,
-	PHYTIMING_LPX,
-	PHYTIMING_HS_EXIT,
-	PHYTIMING_CLK_PREPARE,
-	PHYTIMING_CLK_ZERO,
-	PHYTIMING_CLK_POST,
-	PHYTIMING_CLK_TRAIL,
-	PHYTIMING_HS_PREPARE,
-	PHYTIMING_HS_ZERO,
-	PHYTIMING_HS_TRAIL
-};
-
-static const unsigned int reg_values[] = {
-	[RESET_TYPE] = DSIM_SWRST,
-	[PLL_TIMER] = 500,
-	[STOP_STATE_CNT] = 0xf,
-	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0x0af),
-	[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(0x27),
-	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0d),
-	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x08),
-	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x09),
-	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x0d),
-	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b),
+	struct samsung_dsim_plat_data pdata;
 };
 
-static const unsigned int exynos5422_reg_values[] = {
-	[RESET_TYPE] = DSIM_SWRST,
-	[PLL_TIMER] = 500,
-	[STOP_STATE_CNT] = 0xf,
-	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0xaf),
-	[PHYCTRL_VREG_LP] = 0,
-	[PHYCTRL_SLEW_UP] = 0,
-	[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x08),
-	[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0d),
-	[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x09),
-	[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x30),
-	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0e),
-	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x0a),
-	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x0c),
-	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x11),
-	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0d),
-};
-
-static const unsigned int exynos5433_reg_values[] = {
-	[RESET_TYPE] = DSIM_FUNCRST,
-	[PLL_TIMER] = 22200,
-	[STOP_STATE_CNT] = 0xa,
-	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0x190),
-	[PHYCTRL_VREG_LP] = DSIM_PHYCTRL_B_DPHYCTL_VREG_LP,
-	[PHYCTRL_SLEW_UP] = DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP,
-	[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x07),
-	[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0c),
-	[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x09),
-	[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x2d),
-	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0e),
-	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x09),
-	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x0b),
-	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x10),
-	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c),
-};
-
-static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = {
-	.reg_ofs = exynos_reg_ofs,
-	.plltmr_reg = 0x50,
-	.has_freqband = 1,
-	.has_clklane_stop = 1,
-	.num_clks = 2,
-	.max_freq = 1000,
-	.wait_for_reset = 1,
-	.num_bits_resol = 11,
-	.reg_values = reg_values,
-};
-
-static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
-	.reg_ofs = exynos_reg_ofs,
-	.plltmr_reg = 0x50,
-	.has_freqband = 1,
-	.has_clklane_stop = 1,
-	.num_clks = 2,
-	.max_freq = 1000,
-	.wait_for_reset = 1,
-	.num_bits_resol = 11,
-	.reg_values = reg_values,
-};
-
-static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
-	.reg_ofs = exynos_reg_ofs,
-	.plltmr_reg = 0x58,
-	.num_clks = 2,
-	.max_freq = 1000,
-	.wait_for_reset = 1,
-	.num_bits_resol = 11,
-	.reg_values = reg_values,
-};
-
-static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
-	.reg_ofs = exynos5433_reg_ofs,
-	.plltmr_reg = 0xa0,
-	.has_clklane_stop = 1,
-	.num_clks = 5,
-	.max_freq = 1500,
-	.wait_for_reset = 0,
-	.num_bits_resol = 12,
-	.reg_values = exynos5433_reg_values,
-};
-
-static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = {
-	.reg_ofs = exynos5433_reg_ofs,
-	.plltmr_reg = 0xa0,
-	.has_clklane_stop = 1,
-	.num_clks = 2,
-	.max_freq = 1500,
-	.wait_for_reset = 1,
-	.num_bits_resol = 12,
-	.reg_values = exynos5422_reg_values,
-};
-
-static const struct of_device_id exynos_dsi_of_match[] = {
-	{ .compatible = "samsung,exynos3250-mipi-dsi",
-	  .data = &exynos3_dsi_driver_data },
-	{ .compatible = "samsung,exynos4210-mipi-dsi",
-	  .data = &exynos4_dsi_driver_data },
-	{ .compatible = "samsung,exynos5410-mipi-dsi",
-	  .data = &exynos5_dsi_driver_data },
-	{ .compatible = "samsung,exynos5422-mipi-dsi",
-	  .data = &exynos5422_dsi_driver_data },
-	{ .compatible = "samsung,exynos5433-mipi-dsi",
-	  .data = &exynos5433_dsi_driver_data },
-	{ }
-};
-
-static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
-{
-	if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
-		return;
-
-	dev_err(dsi->dev, "timeout waiting for reset\n");
-}
-
-static void exynos_dsi_reset(struct exynos_dsi *dsi)
-{
-	u32 reset_val = dsi->driver_data->reg_values[RESET_TYPE];
-
-	reinit_completion(&dsi->completed);
-	exynos_dsi_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,
-		unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s)
+static void exynos_dsi_enable_irq(void *priv)
 {
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
-	unsigned long best_freq = 0;
-	u32 min_delta = 0xffffffff;
-	u8 p_min, p_max;
-	u8 _p, best_p;
-	u16 _m, best_m;
-	u8 _s, best_s;
-
-	p_min = DIV_ROUND_UP(fin, (12 * MHZ));
-	p_max = fin / (6 * MHZ);
-
-	for (_p = p_min; _p <= p_max; ++_p) {
-		for (_s = 0; _s <= 5; ++_s) {
-			u64 tmp;
-			u32 delta;
-
-			tmp = (u64)fout * (_p << _s);
-			do_div(tmp, fin);
-			_m = tmp;
-			if (_m < 41 || _m > 125)
-				continue;
-
-			tmp = (u64)_m * fin;
-			do_div(tmp, _p);
-			if (tmp < 500 * MHZ ||
-					tmp > driver_data->max_freq * MHZ)
-				continue;
-
-			tmp = (u64)_m * fin;
-			do_div(tmp, _p << _s);
-
-			delta = abs(fout - tmp);
-			if (delta < min_delta) {
-				best_p = _p;
-				best_m = _m;
-				best_s = _s;
-				min_delta = delta;
-				best_freq = tmp;
-			}
-		}
-	}
-
-	if (best_freq) {
-		*p = best_p;
-		*m = best_m;
-		*s = best_s;
-	}
-
-	return best_freq;
-}
-
-static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
-					unsigned long freq)
-{
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
-	unsigned long fin, fout;
-	int timeout;
-	u8 p, s;
-	u16 m;
-	u32 reg;
-
-	fin = dsi->pll_clk_rate;
-	fout = exynos_dsi_pll_find_pms(dsi, fin, freq, &p, &m, &s);
-	if (!fout) {
-		dev_err(dsi->dev,
-			"failed to find PLL PMS for requested frequency\n");
-		return 0;
-	}
-	dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d)\n", fout, p, m, s);
-
-	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);
-
-	if (driver_data->has_freqband) {
-		static const unsigned long freq_bands[] = {
-			100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
-			270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
-			510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
-			770 * MHZ, 870 * MHZ, 950 * MHZ,
-		};
-		int band;
-
-		for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
-			if (fout < freq_bands[band])
-				break;
-
-		dev_dbg(dsi->dev, "band %d\n", band);
-
-		reg |= DSIM_FREQ_BAND(band);
-	}
-
-	exynos_dsi_write(dsi, DSIM_PLLCTRL_REG, reg);
-
-	timeout = 1000;
-	do {
-		if (timeout-- == 0) {
-			dev_err(dsi->dev, "PLL failed to stabilize\n");
-			return 0;
-		}
-		reg = exynos_dsi_read(dsi, DSIM_STATUS_REG);
-	} while ((reg & DSIM_PLL_STABLE) == 0);
-
-	return fout;
-}
-
-static int exynos_dsi_enable_clock(struct exynos_dsi *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);
-	if (!hs_clk) {
-		dev_err(dsi->dev, "failed to configure DSI PLL\n");
-		return -EFAULT;
-	}
-
-	byte_clk = hs_clk / 8;
-	esc_div = DIV_ROUND_UP(byte_clk, dsi->esc_clk_rate);
-	esc_clk = byte_clk / esc_div;
-
-	if (esc_clk > 20 * MHZ) {
-		++esc_div;
-		esc_clk = byte_clk / esc_div;
-	}
-
-	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 &= ~(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);
-	reg |= DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN
-			| DSIM_ESC_PRESCALER(esc_div)
-			| DSIM_LANE_ESC_CLK_EN_CLK
-			| 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);
-
-	return 0;
-}
-
-static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
-{
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
-	const unsigned int *reg_values = driver_data->reg_values;
-	u32 reg;
-
-	if (driver_data->has_freqband)
-		return;
-
-	/* 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);
-
-	/*
-	 * T LPX: Transmitted length of any Low-Power state period
-	 * T HS-EXIT: Time that the transmitter drives LP-11 following a HS
-	 *	burst
-	 */
-	reg = reg_values[PHYTIMING_LPX] | reg_values[PHYTIMING_HS_EXIT];
-	exynos_dsi_write(dsi, DSIM_PHYTIMING_REG, reg);
-
-	/*
-	 * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00
-	 *	Line state immediately before the HS-0 Line state starting the
-	 *	HS transmission
-	 * T CLK-ZERO: Time that the transmitter drives the HS-0 state prior to
-	 *	transmitting the Clock.
-	 * T CLK_POST: Time that the transmitter continues to send HS clock
-	 *	after the last associated Data Lane has transitioned to LP Mode
-	 *	Interval is defined as the period from the end of T HS-TRAIL to
-	 *	the beginning of T CLK-TRAIL
-	 * T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
-	 *	the last payload clock bit of a HS transmission burst
-	 */
-	reg = reg_values[PHYTIMING_CLK_PREPARE] |
-		reg_values[PHYTIMING_CLK_ZERO] |
-		reg_values[PHYTIMING_CLK_POST] |
-		reg_values[PHYTIMING_CLK_TRAIL];
-
-	exynos_dsi_write(dsi, DSIM_PHYTIMING1_REG, reg);
-
-	/*
-	 * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00
-	 *	Line state immediately before the HS-0 Line state starting the
-	 *	HS transmission
-	 * T HS-ZERO: Time that the transmitter drives the HS-0 state prior to
-	 *	transmitting the Sync sequence.
-	 * T HS-TRAIL: Time that the transmitter drives the flipped differential
-	 *	state after last payload data bit of a HS transmission burst
-	 */
-	reg = reg_values[PHYTIMING_HS_PREPARE] | reg_values[PHYTIMING_HS_ZERO] |
-		reg_values[PHYTIMING_HS_TRAIL];
-	exynos_dsi_write(dsi, DSIM_PHYTIMING2_REG, reg);
-}
-
-static void exynos_dsi_disable_clock(struct exynos_dsi *dsi)
-{
-	u32 reg;
-
-	reg = exynos_dsi_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);
-
-	reg = exynos_dsi_read(dsi, DSIM_PLLCTRL_REG);
-	reg &= ~DSIM_PLL_EN;
-	exynos_dsi_write(dsi, DSIM_PLLCTRL_REG, reg);
-}
-
-static void exynos_dsi_enable_lane(struct exynos_dsi *dsi, u32 lane)
-{
-	u32 reg = exynos_dsi_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);
-}
-
-static int exynos_dsi_init_link(struct exynos_dsi *dsi)
-{
-	const struct exynos_dsi_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 &= ~0x1f;
-	exynos_dsi_write(dsi, DSIM_FIFOCTRL_REG, reg);
-
-	usleep_range(9000, 11000);
-
-	reg |= 0x1f;
-	exynos_dsi_write(dsi, DSIM_FIFOCTRL_REG, reg);
-	usleep_range(9000, 11000);
-
-	/* DSI configuration */
-	reg = 0;
-
-	/*
-	 * The first bit of mode_flags specifies display configuration.
-	 * If this bit is set[= MIPI_DSI_MODE_VIDEO], dsi will support video
-	 * mode, otherwise it will support command mode.
-	 */
-	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
-		reg |= DSIM_VIDEO_MODE;
-
-		/*
-		 * The user manual describes that following bits are ignored in
-		 * command mode.
-		 */
-		if (!(dsi->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH))
-			reg |= DSIM_MFLUSH_VS;
-		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
-			reg |= DSIM_SYNC_INFORM;
-		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
-			reg |= DSIM_BURST_MODE;
-		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_AUTO_VERT)
-			reg |= DSIM_AUTO_MODE;
-		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSE)
-			reg |= DSIM_HSE_MODE;
-		if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HFP))
-			reg |= DSIM_HFP_MODE;
-		if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HBP))
-			reg |= DSIM_HBP_MODE;
-		if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HSA))
-			reg |= DSIM_HSA_MODE;
-	}
-
-	if (!(dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
-		reg |= DSIM_EOT_DISABLE;
-
-	switch (dsi->format) {
-	case MIPI_DSI_FMT_RGB888:
-		reg |= DSIM_MAIN_PIX_FORMAT_RGB888;
-		break;
-	case MIPI_DSI_FMT_RGB666:
-		reg |= DSIM_MAIN_PIX_FORMAT_RGB666;
-		break;
-	case MIPI_DSI_FMT_RGB666_PACKED:
-		reg |= DSIM_MAIN_PIX_FORMAT_RGB666_P;
-		break;
-	case MIPI_DSI_FMT_RGB565:
-		reg |= DSIM_MAIN_PIX_FORMAT_RGB565;
-		break;
-	default:
-		dev_err(dsi->dev, "invalid pixel format\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Use non-continuous clock mode if the periparal wants and
-	 * host controller supports
-	 *
-	 * In non-continous clock mode, host controller will turn off
-	 * the HS clock between high-speed transmissions to reduce
-	 * power consumption.
-	 */
-	if (driver_data->has_clklane_stop &&
-			dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
-		reg |= DSIM_CLKLANE_STOP;
-	}
-	exynos_dsi_write(dsi, DSIM_CONFIG_REG, reg);
-
-	lanes_mask = BIT(dsi->lanes) - 1;
-	exynos_dsi_enable_lane(dsi, lanes_mask);
-
-	/* Check clock and data lane state are stop state */
-	timeout = 100;
-	do {
-		if (timeout-- == 0) {
-			dev_err(dsi->dev, "waiting for bus lanes timed out\n");
-			return -EFAULT;
-		}
-
-		reg = exynos_dsi_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 &= ~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);
-
-	reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff);
-	exynos_dsi_write(dsi, DSIM_TIMEOUT_REG, reg);
-
-	return 0;
-}
-
-static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)
-{
-	struct drm_display_mode *m = &dsi->mode;
-	unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;
-	u32 reg;
-
-	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
-		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);
-
-		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);
-
-		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);
-	}
-	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);
-
-	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)
-{
-	u32 reg;
-
-	reg = exynos_dsi_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);
-}
-
-static int exynos_dsi_wait_for_hdr_fifo(struct exynos_dsi *dsi)
-{
-	int timeout = 2000;
-
-	do {
-		u32 reg = exynos_dsi_read(dsi, DSIM_FIFOCTRL_REG);
-
-		if (!(reg & DSIM_SFR_HEADER_FULL))
-			return 0;
-
-		if (!cond_resched())
-			usleep_range(950, 1050);
-	} while (--timeout);
-
-	return -ETIMEDOUT;
-}
-
-static void exynos_dsi_set_cmd_lpm(struct exynos_dsi *dsi, bool lpm)
-{
-	u32 v = exynos_dsi_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);
-}
-
-static void exynos_dsi_force_bta(struct exynos_dsi *dsi)
-{
-	u32 v = exynos_dsi_read(dsi, DSIM_ESCMODE_REG);
-	v |= DSIM_FORCE_BTA;
-	exynos_dsi_write(dsi, DSIM_ESCMODE_REG, v);
-}
-
-static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi,
-					struct exynos_dsi_transfer *xfer)
-{
-	struct device *dev = dsi->dev;
-	struct mipi_dsi_packet *pkt = &xfer->packet;
-	const u8 *payload = pkt->payload + xfer->tx_done;
-	u16 length = pkt->payload_length - xfer->tx_done;
-	bool first = !xfer->tx_done;
-	u32 reg;
-
-	dev_dbg(dev, "< xfer %pK: tx len %u, done %u, rx len %u, done %u\n",
-		xfer, length, xfer->tx_done, xfer->rx_len, xfer->rx_done);
-
-	if (length > DSI_TX_FIFO_SIZE)
-		length = DSI_TX_FIFO_SIZE;
-
-	xfer->tx_done += length;
-
-	/* Send payload */
-	while (length >= 4) {
-		reg = get_unaligned_le32(payload);
-		exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg);
-		payload += 4;
-		length -= 4;
-	}
-
-	reg = 0;
-	switch (length) {
-	case 3:
-		reg |= payload[2] << 16;
-		fallthrough;
-	case 2:
-		reg |= payload[1] << 8;
-		fallthrough;
-	case 1:
-		reg |= payload[0];
-		exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg);
-		break;
-	}
-
-	/* Send packet header */
-	if (!first)
-		return;
-
-	reg = get_unaligned_le32(pkt->header);
-	if (exynos_dsi_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);
-		dsi->state ^= DSIM_STATE_CMD_LPM;
-	}
-
-	exynos_dsi_write(dsi, DSIM_PKTHDR_REG, reg);
-
-	if (xfer->flags & MIPI_DSI_MSG_REQ_ACK)
-		exynos_dsi_force_bta(dsi);
-}
-
-static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi,
-					struct exynos_dsi_transfer *xfer)
-{
-	u8 *payload = xfer->rx_payload + xfer->rx_done;
-	bool first = !xfer->rx_done;
-	struct device *dev = dsi->dev;
-	u16 length;
-	u32 reg;
-
-	if (first) {
-		reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG);
-
-		switch (reg & 0x3f) {
-		case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
-		case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
-			if (xfer->rx_len >= 2) {
-				payload[1] = reg >> 16;
-				++xfer->rx_done;
-			}
-			fallthrough;
-		case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
-		case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
-			payload[0] = reg >> 8;
-			++xfer->rx_done;
-			xfer->rx_len = xfer->rx_done;
-			xfer->result = 0;
-			goto clear_fifo;
-		case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
-			dev_err(dev, "DSI Error Report: 0x%04x\n",
-				(reg >> 8) & 0xffff);
-			xfer->result = 0;
-			goto clear_fifo;
-		}
-
-		length = (reg >> 8) & 0xffff;
-		if (length > xfer->rx_len) {
-			dev_err(dev,
-				"response too long (%u > %u bytes), stripping\n",
-				xfer->rx_len, length);
-			length = xfer->rx_len;
-		} else if (length < xfer->rx_len)
-			xfer->rx_len = length;
-	}
-
-	length = xfer->rx_len - xfer->rx_done;
-	xfer->rx_done += length;
-
-	/* Receive payload */
-	while (length >= 4) {
-		reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG);
-		payload[0] = (reg >>  0) & 0xff;
-		payload[1] = (reg >>  8) & 0xff;
-		payload[2] = (reg >> 16) & 0xff;
-		payload[3] = (reg >> 24) & 0xff;
-		payload += 4;
-		length -= 4;
-	}
-
-	if (length) {
-		reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG);
-		switch (length) {
-		case 3:
-			payload[2] = (reg >> 16) & 0xff;
-			fallthrough;
-		case 2:
-			payload[1] = (reg >> 8) & 0xff;
-			fallthrough;
-		case 1:
-			payload[0] = reg & 0xff;
-		}
-	}
-
-	if (xfer->rx_done == xfer->rx_len)
-		xfer->result = 0;
+	struct exynos_dsi *dsi = priv;
 
-clear_fifo:
-	length = DSI_RX_FIFO_SIZE / 4;
-	do {
-		reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG);
-		if (reg == DSI_RX_FIFO_EMPTY)
-			break;
-	} while (--length);
-}
-
-static void exynos_dsi_transfer_start(struct exynos_dsi *dsi)
-{
-	unsigned long flags;
-	struct exynos_dsi_transfer *xfer;
-	bool start = false;
-
-again:
-	spin_lock_irqsave(&dsi->transfer_lock, flags);
-
-	if (list_empty(&dsi->transfer_list)) {
-		spin_unlock_irqrestore(&dsi->transfer_lock, flags);
-		return;
-	}
-
-	xfer = list_first_entry(&dsi->transfer_list,
-					struct exynos_dsi_transfer, list);
-
-	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
-
-	if (xfer->packet.payload_length &&
-	    xfer->tx_done == xfer->packet.payload_length)
-		/* waiting for RX */
-		return;
-
-	exynos_dsi_send_to_fifo(dsi, xfer);
-
-	if (xfer->packet.payload_length || xfer->rx_len)
-		return;
-
-	xfer->result = 0;
-	complete(&xfer->completed);
-
-	spin_lock_irqsave(&dsi->transfer_lock, flags);
-
-	list_del_init(&xfer->list);
-	start = !list_empty(&dsi->transfer_list);
-
-	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
-
-	if (start)
-		goto again;
-}
-
-static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi)
-{
-	struct exynos_dsi_transfer *xfer;
-	unsigned long flags;
-	bool start = true;
-
-	spin_lock_irqsave(&dsi->transfer_lock, flags);
-
-	if (list_empty(&dsi->transfer_list)) {
-		spin_unlock_irqrestore(&dsi->transfer_lock, flags);
-		return false;
-	}
-
-	xfer = list_first_entry(&dsi->transfer_list,
-					struct exynos_dsi_transfer, list);
-
-	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
-
-	dev_dbg(dsi->dev,
-		"> xfer %pK, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n",
-		xfer, xfer->packet.payload_length, xfer->tx_done, xfer->rx_len,
-		xfer->rx_done);
-
-	if (xfer->tx_done != xfer->packet.payload_length)
-		return true;
-
-	if (xfer->rx_done != xfer->rx_len)
-		exynos_dsi_read_from_fifo(dsi, xfer);
-
-	if (xfer->rx_done != xfer->rx_len)
-		return true;
-
-	spin_lock_irqsave(&dsi->transfer_lock, flags);
-
-	list_del_init(&xfer->list);
-	start = !list_empty(&dsi->transfer_list);
-
-	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
-
-	if (!xfer->rx_len)
-		xfer->result = 0;
-	complete(&xfer->completed);
-
-	return start;
-}
-
-static void exynos_dsi_remove_transfer(struct exynos_dsi *dsi,
-					struct exynos_dsi_transfer *xfer)
-{
-	unsigned long flags;
-	bool start;
-
-	spin_lock_irqsave(&dsi->transfer_lock, flags);
-
-	if (!list_empty(&dsi->transfer_list) &&
-	    xfer == list_first_entry(&dsi->transfer_list,
-				     struct exynos_dsi_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);
-		return;
-	}
-
-	list_del_init(&xfer->list);
-
-	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
+	if (dsi->te_gpio)
+		enable_irq(gpiod_to_irq(dsi->te_gpio));
 }
 
-static int exynos_dsi_transfer(struct exynos_dsi *dsi,
-					struct exynos_dsi_transfer *xfer)
+static void exynos_dsi_disable_irq(void *priv)
 {
-	unsigned long flags;
-	bool stopped;
+	struct exynos_dsi *dsi = priv;
 
-	xfer->tx_done = 0;
-	xfer->rx_done = 0;
-	xfer->result = -ETIMEDOUT;
-	init_completion(&xfer->completed);
-
-	spin_lock_irqsave(&dsi->transfer_lock, flags);
-
-	stopped = list_empty(&dsi->transfer_list);
-	list_add_tail(&xfer->list, &dsi->transfer_list);
-
-	spin_unlock_irqrestore(&dsi->transfer_lock, flags);
-
-	if (stopped)
-		exynos_dsi_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);
-		dev_err(dsi->dev, "xfer timed out: %*ph %*ph\n", 4, pkt->header,
-			(int)pkt->payload_length, pkt->payload);
-		return -ETIMEDOUT;
-	}
-
-	/* Also covers hardware timeout condition */
-	return xfer->result;
+	if (dsi->te_gpio)
+		disable_irq(gpiod_to_irq(dsi->te_gpio));
 }
 
-static irqreturn_t exynos_dsi_irq(int irq, void *dev_id)
-{
-	struct exynos_dsi *dsi = dev_id;
-	u32 status;
-
-	status = exynos_dsi_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);
-
-	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);
-		complete(&dsi->completed);
-		return IRQ_HANDLED;
-	}
-
-	if (!(status & (DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY |
-			DSIM_INT_PLL_STABLE)))
-		return IRQ_HANDLED;
-
-	if (exynos_dsi_transfer_finish(dsi))
-		exynos_dsi_transfer_start(dsi);
-
-	return IRQ_HANDLED;
-}
+static const struct samsung_dsim_irq_ops samsung_dsim_exynos_host_irq = {
+	.enable = exynos_dsi_enable_irq,
+	.disable = exynos_dsi_disable_irq,
+};
 
 static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id)
 {
 	struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id;
+	struct samsung_dsim *priv = dsi->priv;
 	struct drm_encoder *encoder = &dsi->encoder;
 
-	if (dsi->state & DSIM_STATE_VIDOUT_AVAILABLE)
+	if (priv->state & DSIM_STATE_VIDOUT_AVAILABLE)
 		exynos_drm_crtc_te_handler(encoder->crtc);
 
 	return IRQ_HANDLED;
 }
 
-static void exynos_dsi_enable_irq(struct exynos_dsi *dsi)
-{
-	enable_irq(dsi->irq);
-
-	if (dsi->te_gpio)
-		enable_irq(gpiod_to_irq(dsi->te_gpio));
-}
-
-static void exynos_dsi_disable_irq(struct exynos_dsi *dsi)
-{
-	if (dsi->te_gpio)
-		disable_irq(gpiod_to_irq(dsi->te_gpio));
-
-	disable_irq(dsi->irq);
-}
-
-static int exynos_dsi_init(struct exynos_dsi *dsi)
-{
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
-
-	exynos_dsi_reset(dsi);
-	exynos_dsi_enable_irq(dsi);
-
-	if (driver_data->reg_values[RESET_TYPE] == DSIM_FUNCRST)
-		exynos_dsi_enable_lane(dsi, BIT(dsi->lanes) - 1);
-
-	exynos_dsi_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);
-
-	return 0;
-}
-
-static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi,
-				      struct device *panel)
+static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi, struct device *panel)
 {
-	int ret;
+	struct samsung_dsim *priv = dsi->priv;
 	int te_gpio_irq;
+	int ret;
 
-	dsi->te_gpio = devm_gpiod_get_optional(dsi->dev, "te", GPIOD_IN);
+	dsi->te_gpio = devm_gpiod_get_optional(priv->dev, "te", GPIOD_IN);
 	if (IS_ERR(dsi->te_gpio)) {
-		dev_err(dsi->dev, "gpio request failed with %ld\n",
+		dev_err(priv->dev, "gpio request failed with %ld\n",
 				PTR_ERR(dsi->te_gpio));
 		return PTR_ERR(dsi->te_gpio);
 	}
@@ -1342,7 +76,7 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi,
 	ret = request_threaded_irq(te_gpio_irq, exynos_dsi_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);
+		dev_err(priv->dev, "request interrupt failed with %d\n", ret);
 		gpiod_put(dsi->te_gpio);
 		return ret;
 	}
@@ -1358,111 +92,15 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
 	}
 }
 
-static void exynos_dsi_atomic_pre_enable(struct drm_bridge *bridge,
-					 struct drm_bridge_state *old_bridge_state)
-{
-	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
-	int ret;
-
-	if (dsi->state & DSIM_STATE_ENABLED)
-		return;
-
-	ret = pm_runtime_resume_and_get(dsi->dev);
-	if (ret < 0) {
-		dev_err(dsi->dev, "failed to enable DSI device.\n");
-		return;
-	}
-
-	dsi->state |= DSIM_STATE_ENABLED;
-}
-
-static void exynos_dsi_atomic_enable(struct drm_bridge *bridge,
-				     struct drm_bridge_state *old_bridge_state)
-{
-	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
-
-	exynos_dsi_set_display_mode(dsi);
-	exynos_dsi_set_display_enable(dsi, true);
-
-	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
-
-	return;
-}
-
-static void exynos_dsi_atomic_disable(struct drm_bridge *bridge,
-				      struct drm_bridge_state *old_bridge_state)
-{
-	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
-
-	if (!(dsi->state & DSIM_STATE_ENABLED))
-		return;
-
-	dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
-}
-
-static void exynos_dsi_atomic_post_disable(struct drm_bridge *bridge,
-					   struct drm_bridge_state *old_bridge_state)
-{
-	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
-
-	exynos_dsi_set_display_enable(dsi, false);
-
-	dsi->state &= ~DSIM_STATE_ENABLED;
-	pm_runtime_put_sync(dsi->dev);
-}
-
-static void exynos_dsi_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_attach(struct drm_bridge *bridge,
-			     enum drm_bridge_attach_flags flags)
+static int exynos_dsi_host_attach(void *priv, struct mipi_dsi_device *device)
 {
-	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
-
-	return drm_bridge_attach(bridge->encoder, dsi->out_bridge, NULL, flags);
-}
-
-static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
-	.atomic_duplicate_state		= drm_atomic_helper_bridge_duplicate_state,
-	.atomic_destroy_state		= drm_atomic_helper_bridge_destroy_state,
-	.atomic_reset			= drm_atomic_helper_bridge_reset,
-	.atomic_pre_enable		= exynos_dsi_atomic_pre_enable,
-	.atomic_enable			= exynos_dsi_atomic_enable,
-	.atomic_disable			= exynos_dsi_atomic_disable,
-	.atomic_post_disable		= exynos_dsi_atomic_post_disable,
-	.mode_set			= exynos_dsi_mode_set,
-	.attach				= exynos_dsi_attach,
-};
-
-MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
-
-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 device *dev = dsi->dev;
+	struct exynos_dsi *dsi = priv;
+	struct samsung_dsim *_priv = dsi->priv;
 	struct drm_encoder *encoder = &dsi->encoder;
 	struct drm_device *drm = encoder->dev;
 	int ret;
 
-	dsi->out_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
-	if (IS_ERR(dsi->out_bridge)) {
-		ret = PTR_ERR(dsi->out_bridge);
-		DRM_DEV_ERROR(dev, "failed to find the bridge: %d\n", ret);
-		return ret;
-	}
-
-	DRM_DEV_INFO(dev, "Attached %s device\n", device->name);
-
-	drm_bridge_add(&dsi->bridge);
-
-	drm_bridge_attach(encoder, &dsi->bridge, NULL, 0);
+	drm_bridge_attach(encoder, &_priv->bridge, NULL, 0);
 
 	/*
 	 * This is a temporary solution and should be made by more generic way.
@@ -1478,11 +116,11 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 
 	mutex_lock(&drm->mode_config.mutex);
 
-	dsi->lanes = device->lanes;
-	dsi->format = device->format;
-	dsi->mode_flags = device->mode_flags;
+	_priv->lanes = device->lanes;
+	_priv->format = device->format;
+	_priv->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);
+			!(_priv->mode_flags & MIPI_DSI_MODE_VIDEO);
 
 	mutex_unlock(&drm->mode_config.mutex);
 
@@ -1492,99 +130,28 @@ 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 exynos_dsi_host_detach(void *priv, struct mipi_dsi_device *device)
 {
-	struct exynos_dsi *dsi = host_to_dsi(host);
+	struct exynos_dsi *dsi = priv;
 	struct drm_device *drm = dsi->encoder.dev;
 
-	if (dsi->out_bridge->funcs->detach)
-		dsi->out_bridge->funcs->detach(dsi->out_bridge);
-
 	if (drm->mode_config.poll_enabled)
 		drm_kms_helper_hotplug_event(drm);
 
 	exynos_dsi_unregister_te_irq(dsi);
 
-	drm_bridge_remove(&dsi->bridge);
-
 	return 0;
 }
 
-static ssize_t exynos_dsi_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;
-	int ret;
-
-	if (!(dsi->state & DSIM_STATE_ENABLED))
-		return -EINVAL;
-
-	if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
-		ret = exynos_dsi_init(dsi);
-		if (ret)
-			return ret;
-		dsi->state |= DSIM_STATE_INITIALIZED;
-	}
-
-	ret = mipi_dsi_create_packet(&xfer.packet, msg);
-	if (ret < 0)
-		return ret;
-
-	xfer.rx_len = msg->rx_len;
-	xfer.rx_payload = msg->rx_buf;
-	xfer.flags = msg->flags;
-
-	ret = exynos_dsi_transfer(dsi, &xfer);
-	return (ret < 0) ? ret : xfer.rx_done;
-}
-
-static const struct mipi_dsi_host_ops exynos_dsi_ops = {
+static const struct samsung_dsim_host_ops samsung_dsim_exynos_host_ops = {
 	.attach = exynos_dsi_host_attach,
 	.detach = exynos_dsi_host_detach,
-	.transfer = exynos_dsi_host_transfer,
 };
 
-static int exynos_dsi_of_read_u32(const struct device_node *np,
-				  const char *propname, u32 *out_value)
-{
-	int ret = of_property_read_u32(np, propname, out_value);
-
-	if (ret < 0)
-		pr_err("%pOF: failed to get '%s' property\n", np, propname);
-
-	return ret;
-}
-
-static int exynos_dsi_parse_dt(struct exynos_dsi *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",
-				     &dsi->pll_clk_rate);
-	if (ret < 0)
-		return ret;
-
-	ret = exynos_dsi_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",
-				     &dsi->esc_clk_rate);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int exynos_dsi_bind(struct device *dev, struct device *master,
-				void *data)
+static int exynos_dsi_bind(struct device *dev, struct device *master, void *data)
 {
 	struct exynos_dsi *dsi = dev_get_drvdata(dev);
+	struct samsung_dsim *priv = dsi->priv;
 	struct drm_encoder *encoder = &dsi->encoder;
 	struct drm_device *drm_dev = data;
 	int ret;
@@ -1595,17 +162,17 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 	if (ret < 0)
 		return ret;
 
-	return mipi_dsi_host_register(&dsi->dsi_host);
+	return mipi_dsi_host_register(&priv->dsi_host);
 }
 
-static void exynos_dsi_unbind(struct device *dev, struct device *master,
-				void *data)
+static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data)
 {
 	struct exynos_dsi *dsi = dev_get_drvdata(dev);
+	struct samsung_dsim *priv = dsi->priv;
 
-	exynos_dsi_atomic_disable(&dsi->bridge, NULL);
+	priv->bridge.funcs->atomic_disable(&priv->bridge, NULL);
 
-	mipi_dsi_host_unregister(&dsi->dsi_host);
+	mipi_dsi_host_unregister(&priv->dsi_host);
 }
 
 static const struct component_ops exynos_dsi_component_ops = {
@@ -1613,192 +180,31 @@ static const struct component_ops exynos_dsi_component_ops = {
 	.unbind	= exynos_dsi_unbind,
 };
 
-static int exynos_dsi_probe(struct platform_device *pdev)
+const struct samsung_dsim_plat_data *samsung_dsim_plat_probe(struct samsung_dsim *priv)
 {
-	struct device *dev = &pdev->dev;
 	struct exynos_dsi *dsi;
-	int ret, i;
+	int ret;
 
-	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
+	dsi = devm_kzalloc(priv->dev, sizeof(*dsi), GFP_KERNEL);
 	if (!dsi)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	init_completion(&dsi->completed);
-	spin_lock_init(&dsi->transfer_lock);
-	INIT_LIST_HEAD(&dsi->transfer_list);
+	dsi->pdata.host_ops = &samsung_dsim_exynos_host_ops;
+	dsi->pdata.irq_ops = &samsung_dsim_exynos_host_irq;
+	dsi->priv = priv;
 
-	dsi->dsi_host.ops = &exynos_dsi_ops;
-	dsi->dsi_host.dev = dev;
-
-	dsi->dev = dev;
-	dsi->driver_data = of_device_get_match_data(dev);
-
-	dsi->supplies[0].supply = "vddcore";
-	dsi->supplies[1].supply = "vddio";
-	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies),
-				      dsi->supplies);
+	ret = component_add(priv->dev, &exynos_dsi_component_ops);
 	if (ret)
-		return dev_err_probe(dev, ret, "failed to get regulators\n");
-
-	dsi->clks = devm_kcalloc(dev,
-			dsi->driver_data->num_clks, sizeof(*dsi->clks),
-			GFP_KERNEL);
-	if (!dsi->clks)
-		return -ENOMEM;
-
-	for (i = 0; i < dsi->driver_data->num_clks; i++) {
-		dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
-		if (IS_ERR(dsi->clks[i])) {
-			if (strcmp(clk_names[i], "sclk_mipi") == 0) {
-				dsi->clks[i] = devm_clk_get(dev,
-							OLD_SCLK_MIPI_CLK_NAME);
-				if (!IS_ERR(dsi->clks[i]))
-					continue;
-			}
-
-			dev_info(dev, "failed to get the clock: %s\n",
-					clk_names[i]);
-			return PTR_ERR(dsi->clks[i]);
-		}
-	}
-
-	dsi->reg_base = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(dsi->reg_base))
-		return PTR_ERR(dsi->reg_base);
+		return ERR_PTR(ret);
 
-	dsi->phy = devm_phy_get(dev, "dsim");
-	if (IS_ERR(dsi->phy)) {
-		dev_info(dev, "failed to get dsim phy\n");
-		return PTR_ERR(dsi->phy);
-	}
-
-	dsi->irq = platform_get_irq(pdev, 0);
-	if (dsi->irq < 0)
-		return dsi->irq;
-
-	ret = devm_request_threaded_irq(dev, dsi->irq, NULL,
-					exynos_dsi_irq,
-					IRQF_ONESHOT | IRQF_NO_AUTOEN,
-					dev_name(dev), dsi);
-	if (ret) {
-		dev_err(dev, "failed to request dsi irq\n");
-		return ret;
-	}
-
-	ret = exynos_dsi_parse_dt(dsi);
-	if (ret)
-		return ret;
-
-	platform_set_drvdata(pdev, dsi);
-
-	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;
-
-	ret = component_add(dev, &exynos_dsi_component_ops);
-	if (ret)
-		goto err_disable_runtime;
-
-	return 0;
-
-err_disable_runtime:
-	pm_runtime_disable(dev);
-
-	return ret;
-}
-
-static int exynos_dsi_remove(struct platform_device *pdev)
-{
-	pm_runtime_disable(&pdev->dev);
-
-	component_del(&pdev->dev, &exynos_dsi_component_ops);
-
-	return 0;
-}
-
-static int __maybe_unused exynos_dsi_suspend(struct device *dev)
-{
-	struct exynos_dsi *dsi = dev_get_drvdata(dev);
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
-	int ret, i;
-
-	usleep_range(10000, 20000);
-
-	if (dsi->state & DSIM_STATE_INITIALIZED) {
-		dsi->state &= ~DSIM_STATE_INITIALIZED;
-
-		exynos_dsi_disable_clock(dsi);
-
-		exynos_dsi_disable_irq(dsi);
-	}
-
-	dsi->state &= ~DSIM_STATE_CMD_LPM;
-
-	phy_power_off(dsi->phy);
-
-	for (i = driver_data->num_clks - 1; i > -1; i--)
-		clk_disable_unprepare(dsi->clks[i]);
-
-	ret = regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
-	if (ret < 0)
-		dev_err(dsi->dev, "cannot disable regulators %d\n", ret);
-
-	return 0;
+	return &dsi->pdata;
 }
 
-static int __maybe_unused exynos_dsi_resume(struct device *dev)
+void samsung_dsim_plat_remove(struct samsung_dsim *priv)
 {
-	struct exynos_dsi *dsi = dev_get_drvdata(dev);
-	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
-	int ret, i;
-
-	ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
-	if (ret < 0) {
-		dev_err(dsi->dev, "cannot enable regulators %d\n", ret);
-		return ret;
-	}
-
-	for (i = 0; i < driver_data->num_clks; i++) {
-		ret = clk_prepare_enable(dsi->clks[i]);
-		if (ret < 0)
-			goto err_clk;
-	}
-
-	ret = phy_power_on(dsi->phy);
-	if (ret < 0) {
-		dev_err(dsi->dev, "cannot enable phy %d\n", ret);
-		goto err_clk;
-	}
-
-	return 0;
-
-err_clk:
-	while (--i > -1)
-		clk_disable_unprepare(dsi->clks[i]);
-	regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
-
-	return ret;
+	component_del(priv->dev, &exynos_dsi_component_ops);
 }
 
-static const struct dev_pm_ops exynos_dsi_pm_ops = {
-	SET_RUNTIME_PM_OPS(exynos_dsi_suspend, exynos_dsi_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,
-	.driver = {
-		   .name = "exynos-dsi",
-		   .owner = THIS_MODULE,
-		   .pm = &exynos_dsi_pm_ops,
-		   .of_match_table = exynos_dsi_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");
diff --git a/include/drm/bridge/samsung-dsim.h b/include/drm/bridge/samsung-dsim.h
new file mode 100644
index 000000000000..59a43f9c4477
--- /dev/null
+++ b/include/drm/bridge/samsung-dsim.h
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022 Amarula Solutions(India)
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#ifndef __SAMSUNG_DSIM__
+#define __SAMSUNG_DSIM__
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_mipi_dsi.h>
+
+#define DSIM_STATE_ENABLED		BIT(0)
+#define DSIM_STATE_INITIALIZED		BIT(1)
+#define DSIM_STATE_CMD_LPM		BIT(2)
+#define DSIM_STATE_VIDOUT_AVAILABLE	BIT(3)
+
+struct samsung_dsim_transfer {
+	struct list_head list;
+	struct completion completed;
+	int result;
+	struct mipi_dsi_packet packet;
+	u16 flags;
+	u16 tx_done;
+
+	u8 *rx_payload;
+	u16 rx_len;
+	u16 rx_done;
+};
+
+struct samsung_dsim_driver_data {
+	const unsigned int *reg_ofs;
+	unsigned int plltmr_reg;
+	unsigned int has_freqband:1;
+	unsigned int has_clklane_stop:1;
+	unsigned int num_clks;
+	unsigned int max_freq;
+	unsigned int wait_for_reset;
+	unsigned int num_bits_resol;
+	const unsigned int *reg_values;
+};
+
+struct samsung_dsim_host_ops {
+	int (*attach)(void *priv, struct mipi_dsi_device *device);
+	int (*detach)(void *priv, struct mipi_dsi_device *device);
+};
+
+struct samsung_dsim_irq_ops {
+	void (*enable)(void *priv);
+	void (*disable)(void *priv);
+};
+
+struct samsung_dsim_plat_data {
+	const struct samsung_dsim_host_ops *host_ops;
+	const struct samsung_dsim_irq_ops *irq_ops;
+
+	void *priv;
+};
+
+struct samsung_dsim {
+	struct mipi_dsi_host dsi_host;
+	struct drm_bridge bridge;
+	struct drm_bridge *out_bridge;
+	struct device *dev;
+	struct drm_display_mode mode;
+
+	void __iomem *reg_base;
+	struct phy *phy;
+	struct clk **clks;
+	struct regulator_bulk_data supplies[2];
+	int irq;
+
+	u32 pll_clk_rate;
+	u32 burst_clk_rate;
+	u32 esc_clk_rate;
+	u32 lanes;
+	u32 mode_flags;
+	u32 format;
+
+	int state;
+	struct drm_property *brightness;
+	struct completion completed;
+
+	spinlock_t transfer_lock; /* protects transfer_list */
+	struct list_head transfer_list;
+
+	const struct samsung_dsim_driver_data *driver_data;
+	const struct samsung_dsim_plat_data *plat_data;
+};
+
+const struct samsung_dsim_plat_data *samsung_dsim_plat_probe(struct samsung_dsim *priv);
+void samsung_dsim_plat_remove(struct samsung_dsim *priv);
+
+#endif /* __SAMSUNG_DSIM__ */
-- 
2.25.1


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

* [PATCH 02/11] drm: bridge: samsung-dsim: Handle platform init via driver_data
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
  2022-04-08 16:20   ` [PATCH 01/11] drm: bridge: Add Samsung DSIM bridge driver Jagan Teki
@ 2022-04-08 16:20   ` Jagan Teki
  2022-04-12  9:55     ` Marek Szyprowski
  2022-04-08 16:21   ` [PATCH 03/11] drm: bridge: samsung-dsim: Mark PHY as optional Jagan Teki
                     ` (11 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:20 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

In order to make a common Samsung DSIM bridge driver some platform specific
glue code needs to maintain separately as it is hard to maintain platform
specific glue and conventional component_ops on the drm bridge drivers side.

This patch is trying to support that glue code initialization and invocation
in the form of platform_init flag in driver_data.

So, the platforms which enable platform_init flags will handle all platform
specific initialization via samsung_dsim_plat_probe.

The Platform probe is responsible to
- initialize samsung_dsim_plat_data and install hooks
- initialize component_ops
- preserve samsung_dsim structure pointer

v1:
* use platform_init instead of exynos_specific
* handle component_ops in glue code

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

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index ee5d7e5518a6..0e6a5d1c7e4e 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -370,6 +370,7 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
 	.wait_for_reset = 1,
 	.num_bits_resol = 11,
 	.reg_values = reg_values,
+	.platform_init = true,
 };
 
 static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
@@ -382,6 +383,7 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
 	.wait_for_reset = 1,
 	.num_bits_resol = 11,
 	.reg_values = reg_values,
+	.platform_init = true,
 };
 
 static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
@@ -392,6 +394,7 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
 	.wait_for_reset = 1,
 	.num_bits_resol = 11,
 	.reg_values = reg_values,
+	.platform_init = true,
 };
 
 static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
@@ -403,6 +406,7 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
 	.wait_for_reset = 0,
 	.num_bits_resol = 12,
 	.reg_values = exynos5433_reg_values,
+	.platform_init = true,
 };
 
 static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
@@ -414,6 +418,7 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
 	.wait_for_reset = 1,
 	.num_bits_resol = 12,
 	.reg_values = exynos5422_reg_values,
+	.platform_init = true,
 };
 
 static const struct of_device_id samsung_dsim_of_match[] = {
@@ -1565,12 +1570,16 @@ static int samsung_dsim_probe(struct platform_device *pdev)
 	dsi->bridge.of_node = dev->of_node;
 	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 
-	dsi->plat_data = samsung_dsim_plat_probe(dsi);
-	if (IS_ERR(dsi->plat_data)) {
+	if (dsi->driver_data->platform_init) {
+		dsi->plat_data = samsung_dsim_plat_probe(dsi);
 		ret = PTR_ERR(dsi->plat_data);
-		goto err_disable_runtime;
+	} else {
+		ret = mipi_dsi_host_register(&dsi->dsi_host);
 	}
 
+	if (ret)
+		goto err_disable_runtime;
+
 	return 0;
 
 err_disable_runtime:
@@ -1585,7 +1594,10 @@ static int samsung_dsim_remove(struct platform_device *pdev)
 
 	pm_runtime_disable(&pdev->dev);
 
-	samsung_dsim_plat_remove(dsi);
+	if (dsi->driver_data->platform_init)
+		samsung_dsim_plat_remove(dsi);
+	else
+		mipi_dsi_host_unregister(&dsi->dsi_host);
 
 	return 0;
 }
diff --git a/include/drm/bridge/samsung-dsim.h b/include/drm/bridge/samsung-dsim.h
index 59a43f9c4477..eca7eacb5910 100644
--- a/include/drm/bridge/samsung-dsim.h
+++ b/include/drm/bridge/samsung-dsim.h
@@ -39,6 +39,7 @@ struct samsung_dsim_driver_data {
 	unsigned int wait_for_reset;
 	unsigned int num_bits_resol;
 	const unsigned int *reg_values;
+	bool platform_init;
 };
 
 struct samsung_dsim_host_ops {
-- 
2.25.1


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

* [PATCH 03/11] drm: bridge: samsung-dsim: Mark PHY as optional
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
  2022-04-08 16:20   ` [PATCH 01/11] drm: bridge: Add Samsung DSIM bridge driver Jagan Teki
  2022-04-08 16:20   ` [PATCH 02/11] drm: bridge: samsung-dsim: Handle platform init via driver_data Jagan Teki
@ 2022-04-08 16:21   ` Jagan Teki
  2022-04-08 16:21   ` [PATCH 04/11] drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable() Jagan Teki
                     ` (10 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:21 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

In i.MX8M Mini/Nano SoC the DSI Phy requires a MIPI DPHY bit
to reset in order to activate the PHY and that can be done via
upstream i.MX8M blk-ctrl driver.

So, mark the phy get as optional.

v1:
* new patch

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

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 0e6a5d1c7e4e..ff05c8e01cff 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1539,7 +1539,7 @@ static int samsung_dsim_probe(struct platform_device *pdev)
 	if (IS_ERR(dsi->reg_base))
 		return PTR_ERR(dsi->reg_base);
 
-	dsi->phy = devm_phy_get(dev, "dsim");
+	dsi->phy = devm_phy_optional_get(dev, "dsim");
 	if (IS_ERR(dsi->phy)) {
 		dev_info(dev, "failed to get dsim phy\n");
 		return PTR_ERR(dsi->phy);
-- 
2.25.1


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

* [PATCH 04/11] drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable()
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (2 preceding siblings ...)
  2022-04-08 16:21   ` [PATCH 03/11] drm: bridge: samsung-dsim: Mark PHY as optional Jagan Teki
@ 2022-04-08 16:21   ` Jagan Teki
  2022-04-11 12:23     ` Adam Ford
  2022-04-08 16:21   ` [PATCH 05/11] drm: bridge: samsung-dsim: Fix PLL_P (PMS_P) offset Jagan Teki
                     ` (9 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:21 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

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

Handling DSI host initialization in transfer calls misses the
controller setup for I2C configured DSI bridges.

This patch adds the DSI initialization from transfer to bridge
pre_enable as the bridge pre_enable API is invoked by core as
it is common across all classes of DSI device drivers.

v1:
* keep DSI init in host transfer

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

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index ff05c8e01cff..3e12b469dfa8 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1290,6 +1290,13 @@ static void samsung_dsim_atomic_pre_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;
+	}
 }
 
 static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
-- 
2.25.1


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

* [PATCH 05/11] drm: bridge: samsung-dsim: Fix PLL_P (PMS_P) offset
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (3 preceding siblings ...)
  2022-04-08 16:21   ` [PATCH 04/11] drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable() Jagan Teki
@ 2022-04-08 16:21   ` Jagan Teki
  2022-04-08 16:21   ` [PATCH 06/11] drm: bridge: samsung-dsim: Add module init, exit Jagan Teki
                     ` (8 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:21 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

The i.MX 8M Mini Applications Processor Reference Manual, Rev. 3, 11/2020
with 13.7.10.1 Master PLL PMS Value setting Register mentioned PMS_P offset
range from BIT[18-13] and the upstream driver is using the same offset.

However, offset 13 is not working on i.MX8M Mini platforms but downstream
NXP driver is using 14 [1] and it is working with i.MX8M Mini SoC.

Not sure about whether it is reference manual documentation or something
else but this patch trusts the downstream code and fixes the PLL_P offset.

[1] https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/gpu/drm/bridge/sec-dsim.c?h=imx_5.4.47_2.2.0#n211

v1:
* updated commit message
* add downstream driver link

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/gpu/drm/bridge/samsung-dsim.c | 10 ++++++++--
 include/drm/bridge/samsung-dsim.h     |  1 +
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 3e12b469dfa8..423d654e8ffd 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -169,7 +169,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)
 
@@ -369,6 +369,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,
 	.platform_init = true,
 };
@@ -382,6 +383,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,
 	.platform_init = true,
 };
@@ -393,6 +395,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,
 	.platform_init = true,
 };
@@ -405,6 +408,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,
 	.platform_init = true,
 };
@@ -417,6 +421,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,
 	.platform_init = true,
 };
@@ -564,7 +569,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[] = {
diff --git a/include/drm/bridge/samsung-dsim.h b/include/drm/bridge/samsung-dsim.h
index eca7eacb5910..4eb48ec6543f 100644
--- a/include/drm/bridge/samsung-dsim.h
+++ b/include/drm/bridge/samsung-dsim.h
@@ -38,6 +38,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 platform_init;
 };
-- 
2.25.1


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

* [PATCH 06/11] drm: bridge: samsung-dsim: Add module init, exit
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (4 preceding siblings ...)
  2022-04-08 16:21   ` [PATCH 05/11] drm: bridge: samsung-dsim: Fix PLL_P (PMS_P) offset Jagan Teki
@ 2022-04-08 16:21   ` Jagan Teki
  2022-04-08 16:21   ` [PATCH 07/11] drm: bridge: samsung-dsim: Add atomic_check Jagan Teki
                     ` (7 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:21 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, 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.

v1:
* none

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 423d654e8ffd..1fe4b8e737a4 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1696,6 +1696,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("Jagan Teki <jagan@amarulasolutions.com>");
 MODULE_DESCRIPTION("Samsung MIPI DSIM controller bridge");
 MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* [PATCH 07/11] drm: bridge: samsung-dsim: Add atomic_check
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (5 preceding siblings ...)
  2022-04-08 16:21   ` [PATCH 06/11] drm: bridge: samsung-dsim: Add module init, exit Jagan Teki
@ 2022-04-08 16:21   ` Jagan Teki
  2022-04-08 16:21   ` [PATCH 08/11] drm: bridge: samsung-dsim: Add atomic_get_input_bus_fmts Jagan Teki
                     ` (6 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:21 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

Fixing up the mode flags is required in order to correlate the
correct sync flags of the surrounding components in the chain
to make sure the whole pipeline can work properly.

So, handle the mode flags via bridge, atomic_check.

v1:
* fix mode flags in atomic_check instead of mode_fixup

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

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 1fe4b8e737a4..38db1f93ed51 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1338,6 +1338,19 @@ static void samsung_dsim_atomic_post_disable(struct drm_bridge *bridge,
 	pm_runtime_put_sync(dsi->dev);
 }
 
+static int samsung_dsim_atomic_check(struct drm_bridge *bridge,
+				     struct drm_bridge_state *bridge_state,
+				     struct drm_crtc_state *crtc_state,
+				     struct drm_connector_state *conn_state)
+{
+	struct drm_display_mode *adjusted_mode = &crtc_state->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 0;
+}
+
 static void samsung_dsim_mode_set(struct drm_bridge *bridge,
 				  const struct drm_display_mode *mode,
 				  const struct drm_display_mode *adjusted_mode)
@@ -1359,6 +1372,7 @@ static const struct drm_bridge_funcs samsung_dsim_bridge_funcs = {
 	.atomic_duplicate_state		= drm_atomic_helper_bridge_duplicate_state,
 	.atomic_destroy_state		= drm_atomic_helper_bridge_destroy_state,
 	.atomic_reset			= drm_atomic_helper_bridge_reset,
+	.atomic_check			= samsung_dsim_atomic_check,
 	.atomic_pre_enable		= samsung_dsim_atomic_pre_enable,
 	.atomic_enable			= samsung_dsim_atomic_enable,
 	.atomic_disable			= samsung_dsim_atomic_disable,
-- 
2.25.1


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

* [PATCH 08/11] drm: bridge: samsung-dsim: Add atomic_get_input_bus_fmts
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (6 preceding siblings ...)
  2022-04-08 16:21   ` [PATCH 07/11] drm: bridge: samsung-dsim: Add atomic_check Jagan Teki
@ 2022-04-08 16:21   ` Jagan Teki
  2022-04-08 16:21   ` [PATCH 09/11] drm: bridge: samsung-dsim: Add input_bus_flags Jagan Teki
                     ` (5 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:21 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

Finding the right input bus format throughout the pipeline is hard
so add atomic_get_input_bus_fmts callback and initialize with the
default RGB888_1X24 bus format on DSI-end.

This format can be used in pipeline for negotiating bus format between
the DSI-end of this bridge and the other component closer to pipeline
components.

v1:
* new patch

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

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 38db1f93ed51..02802526f82f 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1338,6 +1338,32 @@ static void samsung_dsim_atomic_post_disable(struct drm_bridge *bridge,
 	pm_runtime_put_sync(dsi->dev);
 }
 
+#define MAX_INPUT_SEL_FORMATS	1
+
+static u32 *
+samsung_dsim_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+				       struct drm_bridge_state *bridge_state,
+				       struct drm_crtc_state *crtc_state,
+				       struct drm_connector_state *conn_state,
+				       u32 output_fmt,
+				       unsigned int *num_input_fmts)
+{
+	u32 *input_fmts;
+
+	*num_input_fmts = 0;
+
+	input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),
+			     GFP_KERNEL);
+	if (!input_fmts)
+		return NULL;
+
+	/* This is the DSI-end bus format */
+	input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
+	*num_input_fmts = 1;
+
+	return input_fmts;
+}
+
 static int samsung_dsim_atomic_check(struct drm_bridge *bridge,
 				     struct drm_bridge_state *bridge_state,
 				     struct drm_crtc_state *crtc_state,
@@ -1372,6 +1398,7 @@ static const struct drm_bridge_funcs samsung_dsim_bridge_funcs = {
 	.atomic_duplicate_state		= drm_atomic_helper_bridge_duplicate_state,
 	.atomic_destroy_state		= drm_atomic_helper_bridge_destroy_state,
 	.atomic_reset			= drm_atomic_helper_bridge_reset,
+	.atomic_get_input_bus_fmts	= samsung_dsim_atomic_get_input_bus_fmts,
 	.atomic_check			= samsung_dsim_atomic_check,
 	.atomic_pre_enable		= samsung_dsim_atomic_pre_enable,
 	.atomic_enable			= samsung_dsim_atomic_enable,
-- 
2.25.1


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

* [PATCH 09/11] drm: bridge: samsung-dsim: Add input_bus_flags
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (7 preceding siblings ...)
  2022-04-08 16:21   ` [PATCH 08/11] drm: bridge: samsung-dsim: Add atomic_get_input_bus_fmts Jagan Teki
@ 2022-04-08 16:21   ` Jagan Teki
  2022-04-08 16:21   ` [PATCH 10/11] dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support Jagan Teki
                     ` (4 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:21 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, 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.

v1:
* none

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 02802526f82f..71bbaf19f530 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1543,6 +1543,10 @@ __weak void samsung_dsim_plat_remove(struct samsung_dsim *priv)
 {
 }
 
+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;
@@ -1622,6 +1626,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;
 
 	if (dsi->driver_data->platform_init) {
-- 
2.25.1


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

* [PATCH 10/11] dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (8 preceding siblings ...)
  2022-04-08 16:21   ` [PATCH 09/11] drm: bridge: samsung-dsim: Add input_bus_flags Jagan Teki
@ 2022-04-08 16:21   ` Jagan Teki
  2022-04-10 18:12     ` Laurent Pinchart
  2022-04-08 16:21   ` [PATCH 11/11] drm: bridge: samsung-dsim: Add " Jagan Teki
                     ` (3 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:21 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

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

Add dt-bingings for it.

v1:
* new patch

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
index be377786e8cd..5133d4d39190 100644
--- a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
@@ -7,6 +7,7 @@ Required properties:
 		"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
 		"samsung,exynos5422-mipi-dsi" /* for Exynos5422/5800 SoCs */
 		"samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
+		"fsl,imx8mm-mipi-dsim" /* for i.MX8M Mini/Nano 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
-- 
2.25.1


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

* [PATCH 11/11] drm: bridge: samsung-dsim: Add i.MX8MM support
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (9 preceding siblings ...)
  2022-04-08 16:21   ` [PATCH 10/11] dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support Jagan Teki
@ 2022-04-08 16:21   ` Jagan Teki
  2022-04-10 18:06     ` Laurent Pinchart
  2022-04-09  0:25   ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Tim Harvey
                     ` (2 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2022-04-08 16:21 UTC (permalink / raw)
  To: Andrzej Hajda, Inki Dae, Marek Szyprowski, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel, Jagan Teki

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

Add compatible and associated driver_data for it.

v1:
* none

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

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 71bbaf19f530..d91510a51981 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -360,6 +360,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,
@@ -426,6 +444,18 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
 	.platform_init = 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,
+	.pll_p_offset = 14,
+	.reg_values = imx8mm_dsim_reg_values,
+};
+
 static const struct of_device_id samsung_dsim_of_match[] = {
 	{
 		.compatible = "samsung,exynos3250-mipi-dsi",
@@ -447,6 +477,10 @@ static const struct of_device_id samsung_dsim_of_match[] = {
 		.compatible = "samsung,exynos5433-mipi-dsi",
 		.data = &exynos5433_dsi_driver_data
 	},
+	{
+		.compatible = "fsl,imx8mm-mipi-dsim",
+		.data = &imx8mm_dsi_driver_data
+	},
 	{ /* sentinel. */ }
 };
 
-- 
2.25.1


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

* Re: [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (10 preceding siblings ...)
  2022-04-08 16:21   ` [PATCH 11/11] drm: bridge: samsung-dsim: Add " Jagan Teki
@ 2022-04-09  0:25   ` Tim Harvey
  2022-04-11 13:11   ` (EXT) " Alexander Stein
  2022-04-11 13:56   ` Marek Szyprowski
  13 siblings, 0 replies; 27+ messages in thread
From: Tim Harvey @ 2022-04-09  0:25 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Device Tree Mailing List, linux-samsung-soc, Laurent Pinchart,
	Joonyoung Shim, Neil Armstrong, linux-amarula, DRI mailing list,
	Seung-Woo Kim, NXP Linux Team, Frieder Schrempf, Kyungmin Park,
	Rob Herring, Robert Foss, Andrzej Hajda, Fancy Fang,
	Michael Nazzareno Trimarchi, Adam Ford, Linux ARM Mailing List,
	Marek Szyprowski

On Fri, Apr 8, 2022 at 9:22 AM Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> This series supports common bridge support for Samsung MIPI DSIM
> which is used in Exynos and i.MX8MM SoC's.
>
> Previous RFC can be available here [1].
>
> The final bridge supports both the Exynos and i.MX8MM DSI devices.
>
> On, summary this patch-set break the entire DSIM driver into
> - platform specific glue code for platform ops, component_ops.
> - common bridge driver which handle platform glue init and invoke.
>
> Patch 0000:     Samsung DSIM bridge
>
> Patch 0001:     platform init flag via driver_data
>
> Patch 0002/9:   bridge fixes, atomic API's
>
> Patch 0010:     document fsl,imx8mm-mipi-dsim
>
> Patch 0011:     add i.MX8MM DSIM support
>
> Tested in Engicam i.Core MX8M Mini SoM.
>
> Anyone interested, please have a look on this repo [2]
>
> [2] https://github.com/openedev/kernel/tree/imx8mm-dsi-v1
> [1] https://lore.kernel.org/linux-arm-kernel/YP2j9k5SrZ2%2Fo2%2F5@ravnborg.org/T/
>
> Any inputs?
> Jagan.
>
> Jagan Teki (11):
>   drm: bridge: Add Samsung DSIM bridge driver
>   drm: bridge: samsung-dsim: Handle platform init via driver_data
>   drm: bridge: samsung-dsim: Mark PHY as optional
>   drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable()
>   drm: bridge: samsung-dsim: Fix PLL_P (PMS_P) offset
>   drm: bridge: samsung-dsim: Add module init, exit
>   drm: bridge: samsung-dsim: Add atomic_check
>   drm: bridge: samsung-dsim: Add atomic_get_input_bus_fmts
>   drm: bridge: samsung-dsim: Add input_bus_flags
>   dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support
>   drm: bridge: samsung-dsim: Add i.MX8MM support
>
>  .../bindings/display/exynos/exynos_dsim.txt   |    1 +
>  MAINTAINERS                                   |   12 +
>  drivers/gpu/drm/bridge/Kconfig                |   12 +
>  drivers/gpu/drm/bridge/Makefile               |    1 +
>  drivers/gpu/drm/bridge/samsung-dsim.c         | 1803 +++++++++++++++++
>  drivers/gpu/drm/exynos/Kconfig                |    1 +
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c       | 1704 +---------------
>  include/drm/bridge/samsung-dsim.h             |   97 +
>  8 files changed, 1982 insertions(+), 1649 deletions(-)
>  create mode 100644 drivers/gpu/drm/bridge/samsung-dsim.c
>  create mode 100644 include/drm/bridge/samsung-dsim.h
>
> --
> 2.25.1
>

Jagan,

Thanks so much for continuing to work this through!

I've successfully tested this series on imx8mm-venice-gw73xx-0x using
the following:
- DFROBOT 7" raspberrypi touchscreen display (DFR0506) [1]
- the following defconfig:
CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY
CONFIG_DRM_PANEL_SIMPLE
CONFIG_DRM_PANEL_BRIDGE
CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN
CONFIG_DRM_TOSHIBA_TC358762
CONFIG_DRM_SAMSUNG_DSIM
CONFIG_DRM_MXSFB
- the following dt overlay:
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
 * Copyright 2022 Gateworks Corporation
 */

#include <dt-bindings/gpio/gpio.h>

#include "imx8mm-pinfunc.h"

/dts-v1/;
/plugin/;

&{/} {
        compatible = "gw,imx8mm-gw73xx-0x", "fsl,imx8mm";

        panel {
                compatible = "powertip,ph800480t013-idf02";
                power-supply = <&attiny>;
                backlight = <&attiny>;

                port {
                        panel_out_bridge: endpoint {
                                remote-endpoint = <&bridge_out_panel>;
                        };
                };
        };
};

&i2c3 {
        #address-cells = <1>;
        #size-cells = <0>;

        attiny: regulator@45 {
                compatible = "raspberrypi,7inch-touchscreen-panel-regulator";
                reg = <0x45>;
        };
};

&lcdif {
        status = "okay";
};

&dsi {
        #address-cells = <1>;
        #size-cells = <0>;
        status = "okay";

        bridge@0 {
                compatible = "toshiba,tc358762";
                reg = <0>;
                vddc-supply = <&attiny>;
                #address-cells = <1>;
                #size-cells = <0>;
                status = "okay";

                ports {
                        #address-cells = <1>;
                        #size-cells = <0>;

                        port@0 {
                                reg = <0>;
                                bridge_in_dsi: endpoint {
                                        remote-endpoint = <&dsi_out_bridge>;
                                        data-lanes = <0 1>;
                                };
                        };

                        port@1 {
                                reg = <1>;
                                bridge_out_panel: endpoint {
                                        remote-endpoint = <&panel_out_bridge>;
                                };
                        };
                };
        };

        ports {
                #address-cells = <1>;
                #size-cells = <0>;

                port@1 {
                        reg = <1>;

                        dsi_out_bridge: endpoint {
                                remote-endpoint = <&bridge_in_dsi>;
                        };
                };
        };
};

Tested-by: Tim Harvey <tharvey@gateworks.com> #imx8mm-venice-gw73xx with DFR0506

I'll be happy to test any follow-on series as needed.

Best Regards,

Tim
[1] https://www.dfrobot.com/product-1655.html

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

* Re: [PATCH 11/11] drm: bridge: samsung-dsim: Add i.MX8MM support
  2022-04-08 16:21   ` [PATCH 11/11] drm: bridge: samsung-dsim: Add " Jagan Teki
@ 2022-04-10 18:06     ` Laurent Pinchart
  0 siblings, 0 replies; 27+ messages in thread
From: Laurent Pinchart @ 2022-04-10 18:06 UTC (permalink / raw)
  To: Jagan Teki
  Cc: dri-devel, devicetree, linux-samsung-soc, Joonyoung Shim,
	Neil Armstrong, linux-amarula, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Robert Foss,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	Adam Ford, linux-arm-kernel, Marek Szyprowski

Hi Jagan,

Thank you for the patch.

On Fri, Apr 08, 2022 at 09:51:08PM +0530, Jagan Teki wrote:
> Samsung MIPI DSIM master can also be found in i.MX8MM SoC.
> 
> Add compatible and associated driver_data for it.
> 
> v1:
> * none
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  drivers/gpu/drm/bridge/samsung-dsim.c | 34 +++++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
> index 71bbaf19f530..d91510a51981 100644
> --- a/drivers/gpu/drm/bridge/samsung-dsim.c
> +++ b/drivers/gpu/drm/bridge/samsung-dsim.c
> @@ -360,6 +360,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),
> +};

Most of these values don't seem to be specific to a particular SoC
integration, but should be tuned for the board and the connected DSI
sink. That's out of scope for this patch of course.

> +
>  static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
>  	.reg_ofs = exynos_reg_ofs,
>  	.plltmr_reg = 0x50,
> @@ -426,6 +444,18 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
>  	.platform_init = 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,
> +	.pll_p_offset = 14,
> +	.reg_values = imx8mm_dsim_reg_values,
> +};

I haven't verified the values, the rest looks good to me.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +
>  static const struct of_device_id samsung_dsim_of_match[] = {
>  	{
>  		.compatible = "samsung,exynos3250-mipi-dsi",
> @@ -447,6 +477,10 @@ static const struct of_device_id samsung_dsim_of_match[] = {
>  		.compatible = "samsung,exynos5433-mipi-dsi",
>  		.data = &exynos5433_dsi_driver_data
>  	},
> +	{
> +		.compatible = "fsl,imx8mm-mipi-dsim",
> +		.data = &imx8mm_dsi_driver_data
> +	},
>  	{ /* sentinel. */ }
>  };
>  

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 10/11] dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support
  2022-04-08 16:21   ` [PATCH 10/11] dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support Jagan Teki
@ 2022-04-10 18:12     ` Laurent Pinchart
  2022-04-29  9:40       ` Jagan Teki
  0 siblings, 1 reply; 27+ messages in thread
From: Laurent Pinchart @ 2022-04-10 18:12 UTC (permalink / raw)
  To: Jagan Teki
  Cc: dri-devel, devicetree, linux-samsung-soc, Joonyoung Shim,
	Neil Armstrong, linux-amarula, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Robert Foss,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	Adam Ford, linux-arm-kernel, Marek Szyprowski

Hi Jagan,

Thank you for the patch.

On Fri, Apr 08, 2022 at 09:51:07PM +0530, Jagan Teki wrote:
> Samsung MIPI DSIM bridge can also be found in i.MX8MM/i.MX8MN SoC.
> 
> Add dt-bingings for it.
> 
> v1:
> * new patch
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> index be377786e8cd..5133d4d39190 100644
> --- a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> +++ b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> @@ -7,6 +7,7 @@ Required properties:

May I try and ask you to convert the DT bindings to YAML as part of this
series ? :-)

>  		"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
>  		"samsung,exynos5422-mipi-dsi" /* for Exynos5422/5800 SoCs */
>  		"samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
> +		"fsl,imx8mm-mipi-dsim" /* for i.MX8M Mini/Nano SoCs */

Should we have two different compatible strings for i.MX8MM and i.MX8MN
?

>    - 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

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 04/11] drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable()
  2022-04-08 16:21   ` [PATCH 04/11] drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable() Jagan Teki
@ 2022-04-11 12:23     ` Adam Ford
  0 siblings, 0 replies; 27+ messages in thread
From: Adam Ford @ 2022-04-11 12:23 UTC (permalink / raw)
  To: Jagan Teki
  Cc: dri-devel, devicetree, linux-samsung-soc, Laurent Pinchart,
	Joonyoung Shim, Neil Armstrong, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Robert Foss,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	linux-amarula, arm-soc, Marek Szyprowski

On Fri, Apr 8, 2022 at 11:22 AM Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> Host transfer() in DSI master will invoke only when the DSI commands
> are sent from DSI devices like DSI Panel or DSI bridges and this
> host transfer wouldn't invoke for I2C-based-DSI bridge drivers.
>
> Handling DSI host initialization in transfer calls misses the
> controller setup for I2C configured DSI bridges.
>
> This patch adds the DSI initialization from transfer to bridge
> pre_enable as the bridge pre_enable API is invoked by core as
> it is common across all classes of DSI device drivers.
>
> v1:
> * keep DSI init in host transfer
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  drivers/gpu/drm/bridge/samsung-dsim.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
> index ff05c8e01cff..3e12b469dfa8 100644
> --- a/drivers/gpu/drm/bridge/samsung-dsim.c
> +++ b/drivers/gpu/drm/bridge/samsung-dsim.c
> @@ -1290,6 +1290,13 @@ static void samsung_dsim_atomic_pre_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;

Out of curiosity, is there a reason that  dsi->state cannot add
DSIM_STATE_INITIALIZED inside the samsung_dsim_init function call?  It
seems to me that if samsung_dsim_init returns successfully, it should
set that flag.  I don't know if it's called from other places or not.

adam
> +       }
>  }
>
>  static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
> --
> 2.25.1
>

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

* Re: (EXT) [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (11 preceding siblings ...)
  2022-04-09  0:25   ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Tim Harvey
@ 2022-04-11 13:11   ` Alexander Stein
  2022-04-11 13:56   ` Marek Szyprowski
  13 siblings, 0 replies; 27+ messages in thread
From: Alexander Stein @ 2022-04-11 13:11 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Neil Armstrong, dri-devel, Laurent Pinchart, Andrzej Hajda,
	Fancy Fang, Marek Szyprowski, linux-samsung-soc, Joonyoung Shim,
	Frieder Schrempf, NXP Linux Team, Michael Nazzareno Trimarchi,
	Jagan Teki, devicetree, Rob Herring, Adam Ford, linux-arm-kernel,
	Seung-Woo Kim, Robert Foss, Kyungmin Park, linux-amarula

Hi Jagan,

thanks for picking this up again and sending a new version.

Am Freitag, 8. April 2022, 18:20:57 CEST schrieb Jagan Teki:
> This series supports common bridge support for Samsung MIPI DSIM
> which is used in Exynos and i.MX8MM SoC's.
> 
> Previous RFC can be available here [1].
> 
> The final bridge supports both the Exynos and i.MX8MM DSI devices.
> 
> On, summary this patch-set break the entire DSIM driver into
> - platform specific glue code for platform ops, component_ops.
> - common bridge driver which handle platform glue init and invoke.
> 
> Patch 0000: 	Samsung DSIM bridge
> 
> Patch 0001: 	platform init flag via driver_data
> 
> Patch 0002/9:   bridge fixes, atomic API's
> 
> Patch 0010:	document fsl,imx8mm-mipi-dsim
> 
> Patch 0011:	add i.MX8MM DSIM support
> 
> Tested in Engicam i.Core MX8M Mini SoM.
> 
> Anyone interested, please have a look on this repo [2]
> 
> [2] https://github.com/openedev/kernel/tree/imx8mm-dsi-v1
> [1]
> https://lore.kernel.org/linux-arm-kernel/YP2j9k5SrZ2%2Fo2%2F5@ravnborg.org/
> T/
> 
> Any inputs?

With the following patch I can use LVDS, connected via an LVDS bridge on my 
TQMa8MxML + MBa8Mx. Unless I enable 4 MIPI-DSI lanes.
Using "data-lanes = <1 2 3 4>;" instead show a flickering image, but the 
"content" seems ok. On the downstream kernel MIPI-DSI is working, apparently 
using 4-lanes. On the first glance a bigger difference to the downstream 
kernel from NXP is that AFAICS they change the clocks depending on the 
currently selected mode [1]. I tried playing with the clocks but I don't fully 
grasp which clock has which effect, so I eventually had no results.
Any ideas what might be wrong here?

On a side note, might be completely unrelated to this series, I get the 
following warning as well:
> sn65dsi83 2-002d: Unsupported LVDS bus format 0x100a, please check output 
bridge driver. Falling back to SPWG24.

0x100a is MEDIA_BUS_FMT_RGB888_1X24 from 
samsung_dsim_atomic_get_input_bus_fmts(). For some reason this is propagates 
to the output_bus_cfg used in sn65dsi83_atomic_enable(). I would have expected 
this is MEDIA_BUS_FMT_RGB888_1X7X4_SPWG from "tianma,tm070jvhg33" display.

Best regards,
Alexander

[1] https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/gpu/drm/
bridge/sec-dsim.c?h=lf-5.10.72-2.2.0#n1255

Here is my patch for the DT
--->8---
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/
freescale/Makefile
index 52ce0f798657..7dd280b45681 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -58,6 +58,11 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-icore-mx8mm-edimm2.2.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-kontron-n801x-s.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-nitrogen-r2.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-tqma8mqml-mba8mx.dtb
+
+tqma8mqml-mba8mx-imx327-dtbs += imx8mm-tqma8mqml-mba8mx.dtb imx8mm-tqma8mqml-
mba8mx-imx327.dtbo
+tqma8mqml-mba8mx-lvds-dtbs += imx8mm-tqma8mqml-mba8mx.dtb imx8mm-tqma8mqml-
mba8mx-lvds.dtbo
+dtb-$(CONFIG_ARCH_MXC) += tqma8mqml-mba8mx-imx327.dtb tqma8mqml-mba8mx-
lvds.dtb
+
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-var-som-symphony.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw71xx-0x.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw72xx-0x.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx-lvds.dts b/
arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx-lvds.dts
new file mode 100644
index 000000000000..8c743d291459
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx-lvds.dts
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
+/*
+ * Copyright 2021-2022 TQ-Systems GmbH
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	compatible = "tq,imx8mm-tqma8mqml-mba8mx", "tq,imx8mm-tqma8mqml", 
"fsl,imx8mm";
+};
+
+&backlight_lvds0 {
+	status = "okay";
+};
+
+&dsi {
+	status = "okay";
+
+	ports {
+		port@1 {
+			mipi_dsi_out: endpoint {
+				remote-endpoint = 
<&lvds_bridge_in>;
+			};
+		};
+	};
+};
+
+&dsi_lvds_bridge {
+	status = "okay";
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			lvds_bridge_in: endpoint {
+				data-lanes = <1 2 3>;
+				remote-endpoint = <&mipi_dsi_out>;
+			};
+		};
+	};
+};
+
+&expander0 {
+	dsi-mux-oe-hog {
+		gpio-hog;
+		gpios = <10 0>;
+		output-low;
+		line-name = "DSI_MUX_OE#";
+	};
+};
+
+&lcdif {
+	status = "okay";
+};
+
+&panel0 {
+	compatible = "tianma,tm070jvhg33";
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/mba8mx.dtsi b/arch/arm64/boot/dts/
freescale/mba8mx.dtsi
index c2f0f1a1566c..4b2cca3268eb 100644
--- a/arch/arm64/boot/dts/freescale/mba8mx.dtsi
+++ b/arch/arm64/boot/dts/freescale/mba8mx.dtsi
@@ -8,6 +8,16 @@
 /* TQ-Systems GmbH MBa8Mx baseboard */
 
 / {
+	backlight_lvds0: backlight0 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm3 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_12v>;
+		enable-gpios = <&expander2 2 GPIO_ACTIVE_HIGH>;
+		status = "disabled";
+	};
+
 	beeper {
 		compatible = "pwm-beeper";
 		pwms = <&pwm4 0 250000 0>;
@@ -66,12 +76,31 @@ led2: led2 {
 		};
 	};
 
+	panel0: panel_lvds0 {
+		backlight = <&backlight_lvds0>;
+		status = "disabled";
+
+		port {
+			panel_in_lvds0: endpoint {
+				remote-endpoint = 
<&lvds_bridge_out>;
+			};
+		};
+	};
+
 	pcie0_refclk: pcie0-refclk {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <100000000>;
 	};
 
+	reg_12v: regulator-12v {
+		compatible = "regulator-fixed";
+		regulator-name = "MBA8MX_12V";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+	};
+
 	reg_hub_vbus: regulator-hub-vbus {
 		compatible = "regulator-fixed";
 		regulator-name = "MBA8MX_HUB_VBUS";
@@ -227,6 +256,27 @@ &i2c3 {
 	scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
 	sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
 	status = "okay";
+
+	dsi_lvds_bridge: dsi-lvds-bridge@2d {
+		compatible = "ti,sn65dsi83";
+		reg = <0x2d>;
+		enable-gpios = <&expander0 6 GPIO_ACTIVE_HIGH>;
+		vcc-supply = <&reg_sn65dsi83_1v8>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@2 {
+				reg = <2>;
+
+				lvds_bridge_out: endpoint {
+					remote-endpoint = 
<&panel_in_lvds0>;
+				};
+			};
+		};
+	};
 };
 
 &pwm3 {
--->8---






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

* Re: [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge
  2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
                     ` (12 preceding siblings ...)
  2022-04-11 13:11   ` (EXT) " Alexander Stein
@ 2022-04-11 13:56   ` Marek Szyprowski
  2022-04-11 14:39     ` Adam Ford
  13 siblings, 1 reply; 27+ messages in thread
From: Marek Szyprowski @ 2022-04-11 13:56 UTC (permalink / raw)
  To: Jagan Teki, Andrzej Hajda, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel

On 08.04.2022 18:20, Jagan Teki wrote:
> This series supports common bridge support for Samsung MIPI DSIM
> which is used in Exynos and i.MX8MM SoC's.
>
> Previous RFC can be available here [1].
>
> The final bridge supports both the Exynos and i.MX8MM DSI devices.
>
> On, summary this patch-set break the entire DSIM driver into
> - platform specific glue code for platform ops, component_ops.
> - common bridge driver which handle platform glue init and invoke.
>
> Patch 0000: 	Samsung DSIM bridge
>
> Patch 0001: 	platform init flag via driver_data
>
> Patch 0002/9:   bridge fixes, atomic API's
>
> Patch 0010:	document fsl,imx8mm-mipi-dsim
>
> Patch 0011:	add i.MX8MM DSIM support
>
> Tested in Engicam i.Core MX8M Mini SoM.
>
> Anyone interested, please have a look on this repo [2]
>
> [2] https://protect2.fireeye.com/v1/url?k=930e329a-f28527b5-930fb9d5-74fe485cbfe7-b0c53e2d688ddbc5&q=1&e=e6aa727d-5ae2-4ca5-bff3-7f62d8fae87e&u=https%3A%2F%2Fgithub.com%2Fopenedev%2Fkernel%2Ftree%2Fimx8mm-dsi-v1
> [1] https://lore.kernel.org/linux-arm-kernel/YP2j9k5SrZ2%2Fo2%2F5@ravnborg.org/T/
>
> Any inputs?

I wanted to test this on the Exynos, but I wasn't able to find what base 
should I apply this patchset. I've tried linux-next as well as 
95a2441e4347 ("drm: exynos: dsi: Switch to atomic funcs").

Please note that pointing a proper base for the patchset is really 
essential if you really want others to test it.


> Jagan.
>
> Jagan Teki (11):
>    drm: bridge: Add Samsung DSIM bridge driver
>    drm: bridge: samsung-dsim: Handle platform init via driver_data
>    drm: bridge: samsung-dsim: Mark PHY as optional
>    drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable()
>    drm: bridge: samsung-dsim: Fix PLL_P (PMS_P) offset
>    drm: bridge: samsung-dsim: Add module init, exit
>    drm: bridge: samsung-dsim: Add atomic_check
>    drm: bridge: samsung-dsim: Add atomic_get_input_bus_fmts
>    drm: bridge: samsung-dsim: Add input_bus_flags
>    dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support
>    drm: bridge: samsung-dsim: Add i.MX8MM support
>
>   .../bindings/display/exynos/exynos_dsim.txt   |    1 +
>   MAINTAINERS                                   |   12 +
>   drivers/gpu/drm/bridge/Kconfig                |   12 +
>   drivers/gpu/drm/bridge/Makefile               |    1 +
>   drivers/gpu/drm/bridge/samsung-dsim.c         | 1803 +++++++++++++++++
>   drivers/gpu/drm/exynos/Kconfig                |    1 +
>   drivers/gpu/drm/exynos/exynos_drm_dsi.c       | 1704 +---------------
>   include/drm/bridge/samsung-dsim.h             |   97 +
>   8 files changed, 1982 insertions(+), 1649 deletions(-)
>   create mode 100644 drivers/gpu/drm/bridge/samsung-dsim.c
>   create mode 100644 include/drm/bridge/samsung-dsim.h
>
Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


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

* Re: [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge
  2022-04-11 13:56   ` Marek Szyprowski
@ 2022-04-11 14:39     ` Adam Ford
  2022-04-11 15:29       ` Adam Ford
  2022-04-11 16:25       ` Marek Szyprowski
  0 siblings, 2 replies; 27+ messages in thread
From: Adam Ford @ 2022-04-11 14:39 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: dri-devel, devicetree, linux-samsung-soc, Joonyoung Shim,
	Neil Armstrong, Robert Foss, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Jagan Teki,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	linux-amarula, arm-soc, Laurent Pinchart

On Mon, Apr 11, 2022 at 8:56 AM Marek Szyprowski
<m.szyprowski@samsung.com> wrote:
>
> On 08.04.2022 18:20, Jagan Teki wrote:
> > This series supports common bridge support for Samsung MIPI DSIM
> > which is used in Exynos and i.MX8MM SoC's.
> >
> > Previous RFC can be available here [1].
> >
> > The final bridge supports both the Exynos and i.MX8MM DSI devices.
> >
> > On, summary this patch-set break the entire DSIM driver into
> > - platform specific glue code for platform ops, component_ops.
> > - common bridge driver which handle platform glue init and invoke.
> >
> > Patch 0000:   Samsung DSIM bridge
> >
> > Patch 0001:   platform init flag via driver_data
> >
> > Patch 0002/9:   bridge fixes, atomic API's
> >
> > Patch 0010:   document fsl,imx8mm-mipi-dsim
> >
> > Patch 0011:   add i.MX8MM DSIM support
> >
> > Tested in Engicam i.Core MX8M Mini SoM.
> >
> > Anyone interested, please have a look on this repo [2]
> >
> > [2] https://protect2.fireeye.com/v1/url?k=930e329a-f28527b5-930fb9d5-74fe485cbfe7-b0c53e2d688ddbc5&q=1&e=e6aa727d-5ae2-4ca5-bff3-7f62d8fae87e&u=https%3A%2F%2Fgithub.com%2Fopenedev%2Fkernel%2Ftree%2Fimx8mm-dsi-v1
> > [1] https://lore.kernel.org/linux-arm-kernel/YP2j9k5SrZ2%2Fo2%2F5@ravnborg.org/T/
> >
> > Any inputs?
>
> I wanted to test this on the Exynos, but I wasn't able to find what base
> should I apply this patchset. I've tried linux-next as well as
> 95a2441e4347 ("drm: exynos: dsi: Switch to atomic funcs").
>
> Please note that pointing a proper base for the patchset is really
> essential if you really want others to test it.

Can you clone his repo and test that?  He posted it above.  I was
going to clone it at some point this week to give it a try.

adam
>
>
> > Jagan.
> >
> > Jagan Teki (11):
> >    drm: bridge: Add Samsung DSIM bridge driver
> >    drm: bridge: samsung-dsim: Handle platform init via driver_data
> >    drm: bridge: samsung-dsim: Mark PHY as optional
> >    drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable()
> >    drm: bridge: samsung-dsim: Fix PLL_P (PMS_P) offset
> >    drm: bridge: samsung-dsim: Add module init, exit
> >    drm: bridge: samsung-dsim: Add atomic_check
> >    drm: bridge: samsung-dsim: Add atomic_get_input_bus_fmts
> >    drm: bridge: samsung-dsim: Add input_bus_flags
> >    dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support
> >    drm: bridge: samsung-dsim: Add i.MX8MM support
> >
> >   .../bindings/display/exynos/exynos_dsim.txt   |    1 +
> >   MAINTAINERS                                   |   12 +
> >   drivers/gpu/drm/bridge/Kconfig                |   12 +
> >   drivers/gpu/drm/bridge/Makefile               |    1 +
> >   drivers/gpu/drm/bridge/samsung-dsim.c         | 1803 +++++++++++++++++
> >   drivers/gpu/drm/exynos/Kconfig                |    1 +
> >   drivers/gpu/drm/exynos/exynos_drm_dsi.c       | 1704 +---------------
> >   include/drm/bridge/samsung-dsim.h             |   97 +
> >   8 files changed, 1982 insertions(+), 1649 deletions(-)
> >   create mode 100644 drivers/gpu/drm/bridge/samsung-dsim.c
> >   create mode 100644 include/drm/bridge/samsung-dsim.h
> >
> Best regards
> --
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
>

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

* Re: [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge
  2022-04-11 14:39     ` Adam Ford
@ 2022-04-11 15:29       ` Adam Ford
  2022-04-11 16:25       ` Marek Szyprowski
  1 sibling, 0 replies; 27+ messages in thread
From: Adam Ford @ 2022-04-11 15:29 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: dri-devel, devicetree, linux-samsung-soc, Joonyoung Shim,
	Neil Armstrong, Robert Foss, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Jagan Teki,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	linux-amarula, arm-soc, Laurent Pinchart

On Mon, Apr 11, 2022 at 9:39 AM Adam Ford <aford173@gmail.com> wrote:
>
> On Mon, Apr 11, 2022 at 8:56 AM Marek Szyprowski
> <m.szyprowski@samsung.com> wrote:
> >
> > On 08.04.2022 18:20, Jagan Teki wrote:
> > > This series supports common bridge support for Samsung MIPI DSIM
> > > which is used in Exynos and i.MX8MM SoC's.
> > >
> > > Previous RFC can be available here [1].
> > >
> > > The final bridge supports both the Exynos and i.MX8MM DSI devices.
> > >
> > > On, summary this patch-set break the entire DSIM driver into
> > > - platform specific glue code for platform ops, component_ops.
> > > - common bridge driver which handle platform glue init and invoke.
> > >
> > > Patch 0000:   Samsung DSIM bridge
> > >
> > > Patch 0001:   platform init flag via driver_data
> > >
> > > Patch 0002/9:   bridge fixes, atomic API's
> > >
> > > Patch 0010:   document fsl,imx8mm-mipi-dsim
> > >
> > > Patch 0011:   add i.MX8MM DSIM support
> > >
> > > Tested in Engicam i.Core MX8M Mini SoM.
> > >
> > > Anyone interested, please have a look on this repo [2]
> > >
> > > [2] https://protect2.fireeye.com/v1/url?k=930e329a-f28527b5-930fb9d5-74fe485cbfe7-b0c53e2d688ddbc5&q=1&e=e6aa727d-5ae2-4ca5-bff3-7f62d8fae87e&u=https%3A%2F%2Fgithub.com%2Fopenedev%2Fkernel%2Ftree%2Fimx8mm-dsi-v1
> > > [1] https://lore.kernel.org/linux-arm-kernel/YP2j9k5SrZ2%2Fo2%2F5@ravnborg.org/T/
> > >
> > > Any inputs?
> >
> > I wanted to test this on the Exynos, but I wasn't able to find what base
> > should I apply this patchset. I've tried linux-next as well as
> > 95a2441e4347 ("drm: exynos: dsi: Switch to atomic funcs").
> >
> > Please note that pointing a proper base for the patchset is really
> > essential if you really want others to test it.
>
> Can you clone his repo and test that?  He posted it above.  I was
> going to clone it at some point this week to give it a try.

Jagan,

Is there anyway you could rebase this onto 5.18-rc1? Marek was having
issues applying patches to a known branch, and it looks like I cannot
enable stuff on Nano without applying a bunch of patches, because this
base lacks the power-domain features on Nano that are present in the
5.18-rc1.

thanks,

adam

>
> adam
> >
> >
> > > Jagan.
> > >
> > > Jagan Teki (11):
> > >    drm: bridge: Add Samsung DSIM bridge driver
> > >    drm: bridge: samsung-dsim: Handle platform init via driver_data
> > >    drm: bridge: samsung-dsim: Mark PHY as optional
> > >    drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable()
> > >    drm: bridge: samsung-dsim: Fix PLL_P (PMS_P) offset
> > >    drm: bridge: samsung-dsim: Add module init, exit
> > >    drm: bridge: samsung-dsim: Add atomic_check
> > >    drm: bridge: samsung-dsim: Add atomic_get_input_bus_fmts
> > >    drm: bridge: samsung-dsim: Add input_bus_flags
> > >    dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support
> > >    drm: bridge: samsung-dsim: Add i.MX8MM support
> > >
> > >   .../bindings/display/exynos/exynos_dsim.txt   |    1 +
> > >   MAINTAINERS                                   |   12 +
> > >   drivers/gpu/drm/bridge/Kconfig                |   12 +
> > >   drivers/gpu/drm/bridge/Makefile               |    1 +
> > >   drivers/gpu/drm/bridge/samsung-dsim.c         | 1803 +++++++++++++++++
> > >   drivers/gpu/drm/exynos/Kconfig                |    1 +
> > >   drivers/gpu/drm/exynos/exynos_drm_dsi.c       | 1704 +---------------
> > >   include/drm/bridge/samsung-dsim.h             |   97 +
> > >   8 files changed, 1982 insertions(+), 1649 deletions(-)
> > >   create mode 100644 drivers/gpu/drm/bridge/samsung-dsim.c
> > >   create mode 100644 include/drm/bridge/samsung-dsim.h
> > >
> > Best regards
> > --
> > Marek Szyprowski, PhD
> > Samsung R&D Institute Poland
> >

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

* Re: [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge
  2022-04-11 14:39     ` Adam Ford
  2022-04-11 15:29       ` Adam Ford
@ 2022-04-11 16:25       ` Marek Szyprowski
  2022-04-11 20:26         ` Adam Ford
  1 sibling, 1 reply; 27+ messages in thread
From: Marek Szyprowski @ 2022-04-11 16:25 UTC (permalink / raw)
  To: Adam Ford
  Cc: dri-devel, devicetree, linux-samsung-soc, Joonyoung Shim,
	Neil Armstrong, Robert Foss, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Jagan Teki,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	linux-amarula, arm-soc, Laurent Pinchart

On 11.04.2022 16:39, Adam Ford wrote:
> On Mon, Apr 11, 2022 at 8:56 AM Marek Szyprowski
> <m.szyprowski@samsung.com> wrote:
>> On 08.04.2022 18:20, Jagan Teki wrote:
>>> This series supports common bridge support for Samsung MIPI DSIM
>>> which is used in Exynos and i.MX8MM SoC's.
>>>
>>> Previous RFC can be available here [1].
>>>
>>> The final bridge supports both the Exynos and i.MX8MM DSI devices.
>>>
>>> On, summary this patch-set break the entire DSIM driver into
>>> - platform specific glue code for platform ops, component_ops.
>>> - common bridge driver which handle platform glue init and invoke.
>>>
>>> Patch 0000:   Samsung DSIM bridge
>>>
>>> Patch 0001:   platform init flag via driver_data
>>>
>>> Patch 0002/9:   bridge fixes, atomic API's
>>>
>>> Patch 0010:   document fsl,imx8mm-mipi-dsim
>>>
>>> Patch 0011:   add i.MX8MM DSIM support
>>>
>>> Tested in Engicam i.Core MX8M Mini SoM.
>>>
>>> Anyone interested, please have a look on this repo [2]
>>>
>>> [2] https://protect2.fireeye.com/v1/url?k=930e329a-f28527b5-930fb9d5-74fe485cbfe7-b0c53e2d688ddbc5&q=1&e=e6aa727d-5ae2-4ca5-bff3-7f62d8fae87e&u=https%3A%2F%2Fgithub.com%2Fopenedev%2Fkernel%2Ftree%2Fimx8mm-dsi-v1
>>> [1] https://lore.kernel.org/linux-arm-kernel/YP2j9k5SrZ2%2Fo2%2F5@ravnborg.org/T/
>>>
>>> Any inputs?
>> I wanted to test this on the Exynos, but I wasn't able to find what base
>> should I apply this patchset. I've tried linux-next as well as
>> 95a2441e4347 ("drm: exynos: dsi: Switch to atomic funcs").
>>
>> Please note that pointing a proper base for the patchset is really
>> essential if you really want others to test it.
> Can you clone his repo and test that?  He posted it above.  I was
> going to clone it at some point this week to give it a try.

Okay, my fault. I've missed that.

There is a trivial compilation issue, 
drivers/gpu/drm/exynos/exynos_drm_dsi.c lacks "#include 
<linux/gpio/consumer.h>" after conversion. Besides that, it simply nukes 
on the simplest Exynos setup (exynos4210-trats) during the initialization:

[drm] Exynos DRM: using 11c00000.fimd device for DMA mapping operations
exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops)
8<--- cut here ---
Unable to handle kernel NULL pointer dereference at virtual address 00000048
[00000048] *pgd=00000000
Internal error: Oops: 5 [#1] PREEMPT SMP ARM
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 
5.17.0-rc2-00577-g22e968113668-dirty #11635
Hardware name: Samsung Exynos (Flattened Device Tree)
PC is at exynos_dsi_bind+0x14/0x3c
LR is at component_bind_all+0x130/0x290
pc : [<c06924e0>]    lr : [<c06b0f6c>]    psr: 60000113
sp : c1cafcb8  ip : 00000002  fp : c0f4a53c
r10: c135e6a8  r9 : c1efd800  r8 : 00000000
r7 : c26d2100  r6 : c2c69fc0  r5 : 00000018  r4 : 00000000
r3 : c06924cc  r2 : 00000002  r1 : 00000000  r0 : c1efd800
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
Control: 10c5387d  Table: 4000404a  DAC: 00000051
Register r0 information: slab kmalloc-2k start c1efd800 pointer offset 0 
size 2048
Register r1 information: NULL pointer
Register r2 information: non-paged memory
Register r3 information: non-slab/vmalloc memory
Register r4 information: NULL pointer
Register r5 information: non-paged memory
Register r6 information: slab kmalloc-64 start c2c69fc0 pointer offset 0 
size 64
Register r7 information: slab kmalloc-64 start c26d2100 pointer offset 0 
size 64
Register r8 information: NULL pointer
Register r9 information: slab kmalloc-2k start c1efd800 pointer offset 0 
size 2048
Register r10 information: non-slab/vmalloc memory
Register r11 information: non-slab/vmalloc memory
Register r12 information: non-paged memory
Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
Stack: (0xc1cafcb8 to 0xc1cb0000)
...
  exynos_dsi_bind from component_bind_all+0x130/0x290
  component_bind_all from exynos_drm_bind+0xe8/0x194
  exynos_drm_bind from try_to_bring_up_master+0x208/0x2d0
  try_to_bring_up_master from component_master_add_with_match+0xd0/0x104
  component_master_add_with_match from exynos_drm_platform_probe+0xe8/0x118
  exynos_drm_platform_probe from platform_probe+0x80/0xc0
  platform_probe from really_probe+0xfc/0x440
  really_probe from __driver_probe_device+0xa4/0x204
  __driver_probe_device from driver_probe_device+0x34/0xd4
  driver_probe_device from __driver_attach+0x114/0x184
  __driver_attach from bus_for_each_dev+0x64/0xb0
  bus_for_each_dev from bus_add_driver+0x170/0x20c
  bus_add_driver from driver_register+0x78/0x10c
  driver_register from exynos_drm_init+0xe0/0x14c
  exynos_drm_init from do_one_initcall+0x6c/0x3a4
  do_one_initcall from kernel_init_freeable+0x1c4/0x214
  kernel_init_freeable from kernel_init+0x18/0x12c
  kernel_init from ret_from_fork+0x14/0x2c
Exception stack(0xc1caffb0 to 0xc1cafff8)
ffa0:                                     00000000 00000000 00000000 
00000000
ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
00000000
ffe0: 00000000 00000000 00000000 00000000 00000013 00000000
Code: e5904040 e1a00002 e3a02002 e1a01004 (e5945048)
---[ end trace 0000000000000000 ]---
Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
CPU1: stopping
CPU: 1 PID: 0 Comm: swapper/1 Tainted: G      D 
5.17.0-rc2-00577-g22e968113668-dirty #11635
Hardware name: Samsung Exynos (Flattened Device Tree)
  unwind_backtrace from show_stack+0x10/0x14
  show_stack from dump_stack_lvl+0x58/0x70
  dump_stack_lvl from do_handle_IPI+0x2ec/0x36c
  do_handle_IPI from ipi_handler+0x18/0x20
  ipi_handler from handle_percpu_devid_irq+0xd0/0x394
  handle_percpu_devid_irq from generic_handle_domain_irq+0x44/0x88
  generic_handle_domain_irq from gic_handle_irq+0x88/0xac
  gic_handle_irq from generic_handle_arch_irq+0x58/0x78
  generic_handle_arch_irq from __irq_svc+0x54/0x88
Exception stack(0xc1cd1f48 to 0xc1cd1f90)
1f40:                   00000001 c0eff5a4 00000001 c011ca80 c1208f0c 
c1353420
1f60: 00000000 c1d8d000 00000000 c0f34234 c1d8d000 00000000 c0eeee98 
c1cd1f98
1f80: c0109144 c0109148 20000013 ffffffff
  __irq_svc from arch_cpu_idle+0x40/0x44
  arch_cpu_idle from default_idle_call+0x74/0x2c4
  default_idle_call from do_idle+0x1cc/0x284
  do_idle from cpu_startup_entry+0x18/0x1c
  cpu_startup_entry from 0x401018b4
---[ end Kernel panic - not syncing: Attempted to kill init! 
exitcode=0x0000000b ]---


I will try to take a look into this later in the evening.


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


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

* Re: [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge
  2022-04-11 16:25       ` Marek Szyprowski
@ 2022-04-11 20:26         ` Adam Ford
  0 siblings, 0 replies; 27+ messages in thread
From: Adam Ford @ 2022-04-11 20:26 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: dri-devel, devicetree, linux-samsung-soc, Joonyoung Shim,
	Neil Armstrong, Robert Foss, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Jagan Teki,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	linux-amarula, arm-soc, Laurent Pinchart

On Mon, Apr 11, 2022 at 11:25 AM Marek Szyprowski
<m.szyprowski@samsung.com> wrote:
>
> On 11.04.2022 16:39, Adam Ford wrote:
> > On Mon, Apr 11, 2022 at 8:56 AM Marek Szyprowski
> > <m.szyprowski@samsung.com> wrote:
> >> On 08.04.2022 18:20, Jagan Teki wrote:
> >>> This series supports common bridge support for Samsung MIPI DSIM
> >>> which is used in Exynos and i.MX8MM SoC's.
> >>>
> >>> Previous RFC can be available here [1].
> >>>
> >>> The final bridge supports both the Exynos and i.MX8MM DSI devices.
> >>>
> >>> On, summary this patch-set break the entire DSIM driver into
> >>> - platform specific glue code for platform ops, component_ops.
> >>> - common bridge driver which handle platform glue init and invoke.
> >>>
> >>> Patch 0000:   Samsung DSIM bridge
> >>>
> >>> Patch 0001:   platform init flag via driver_data
> >>>
> >>> Patch 0002/9:   bridge fixes, atomic API's
> >>>
> >>> Patch 0010:   document fsl,imx8mm-mipi-dsim
> >>>
> >>> Patch 0011:   add i.MX8MM DSIM support
> >>>
> >>> Tested in Engicam i.Core MX8M Mini SoM.
> >>>
> >>> Anyone interested, please have a look on this repo [2]

I attempted to build your newer repo, but I get build errors:

~/src/linux-opendev$ make Image modules ARCH=arm64
CROSS_COMPILE=aarch64-linux-gnu- -j8
  CALL    scripts/atomic/check-atomics.sh
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  MODPOST modules-only.symvers
ERROR: modpost: "dsi_driver" [drivers/gpu/drm/exynos/exynosdrm.ko] undefined!
make[1]: *** [scripts/Makefile.modpost:134: modules-only.symvers] Error 1
make[1]: *** Deleting file 'modules-only.symvers'
make: *** [Makefile:1746: modules] Error 2

I'm using gcc version 11.2.0 (Ubuntu 11.2.0-17ubuntu1) part of the
ubuntu 22.04 beta.  I know it's beta, so it might be buggy, but I
expect GCC 11.2 to be stable.

I'm going to keep investigating.  If I find a fix, I'll send you a
private message with the patch attached to avoid spamming everyone.

adam

> >>>
> >>> [2] https://protect2.fireeye.com/v1/url?k=930e329a-f28527b5-930fb9d5-74fe485cbfe7-b0c53e2d688ddbc5&q=1&e=e6aa727d-5ae2-4ca5-bff3-7f62d8fae87e&u=https%3A%2F%2Fgithub.com%2Fopenedev%2Fkernel%2Ftree%2Fimx8mm-dsi-v1
> >>> [1] https://lore.kernel.org/linux-arm-kernel/YP2j9k5SrZ2%2Fo2%2F5@ravnborg.org/T/
> >>>
> >>> Any inputs?
> >> I wanted to test this on the Exynos, but I wasn't able to find what base
> >> should I apply this patchset. I've tried linux-next as well as
> >> 95a2441e4347 ("drm: exynos: dsi: Switch to atomic funcs").
> >>
> >> Please note that pointing a proper base for the patchset is really
> >> essential if you really want others to test it.
> > Can you clone his repo and test that?  He posted it above.  I was
> > going to clone it at some point this week to give it a try.
>
> Okay, my fault. I've missed that.
>
> There is a trivial compilation issue,
> drivers/gpu/drm/exynos/exynos_drm_dsi.c lacks "#include
> <linux/gpio/consumer.h>" after conversion. Besides that, it simply nukes
> on the simplest Exynos setup (exynos4210-trats) during the initialization:
>
> [drm] Exynos DRM: using 11c00000.fimd device for DMA mapping operations
> exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops)
> 8<--- cut here ---
> Unable to handle kernel NULL pointer dereference at virtual address 00000048
> [00000048] *pgd=00000000
> Internal error: Oops: 5 [#1] PREEMPT SMP ARM
> Modules linked in:
> CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> 5.17.0-rc2-00577-g22e968113668-dirty #11635
> Hardware name: Samsung Exynos (Flattened Device Tree)
> PC is at exynos_dsi_bind+0x14/0x3c
> LR is at component_bind_all+0x130/0x290
> pc : [<c06924e0>]    lr : [<c06b0f6c>]    psr: 60000113
> sp : c1cafcb8  ip : 00000002  fp : c0f4a53c
> r10: c135e6a8  r9 : c1efd800  r8 : 00000000
> r7 : c26d2100  r6 : c2c69fc0  r5 : 00000018  r4 : 00000000
> r3 : c06924cc  r2 : 00000002  r1 : 00000000  r0 : c1efd800
> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
> Control: 10c5387d  Table: 4000404a  DAC: 00000051
> Register r0 information: slab kmalloc-2k start c1efd800 pointer offset 0
> size 2048
> Register r1 information: NULL pointer
> Register r2 information: non-paged memory
> Register r3 information: non-slab/vmalloc memory
> Register r4 information: NULL pointer
> Register r5 information: non-paged memory
> Register r6 information: slab kmalloc-64 start c2c69fc0 pointer offset 0
> size 64
> Register r7 information: slab kmalloc-64 start c26d2100 pointer offset 0
> size 64
> Register r8 information: NULL pointer
> Register r9 information: slab kmalloc-2k start c1efd800 pointer offset 0
> size 2048
> Register r10 information: non-slab/vmalloc memory
> Register r11 information: non-slab/vmalloc memory
> Register r12 information: non-paged memory
> Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
> Stack: (0xc1cafcb8 to 0xc1cb0000)
> ...
>   exynos_dsi_bind from component_bind_all+0x130/0x290
>   component_bind_all from exynos_drm_bind+0xe8/0x194
>   exynos_drm_bind from try_to_bring_up_master+0x208/0x2d0
>   try_to_bring_up_master from component_master_add_with_match+0xd0/0x104
>   component_master_add_with_match from exynos_drm_platform_probe+0xe8/0x118
>   exynos_drm_platform_probe from platform_probe+0x80/0xc0
>   platform_probe from really_probe+0xfc/0x440
>   really_probe from __driver_probe_device+0xa4/0x204
>   __driver_probe_device from driver_probe_device+0x34/0xd4
>   driver_probe_device from __driver_attach+0x114/0x184
>   __driver_attach from bus_for_each_dev+0x64/0xb0
>   bus_for_each_dev from bus_add_driver+0x170/0x20c
>   bus_add_driver from driver_register+0x78/0x10c
>   driver_register from exynos_drm_init+0xe0/0x14c
>   exynos_drm_init from do_one_initcall+0x6c/0x3a4
>   do_one_initcall from kernel_init_freeable+0x1c4/0x214
>   kernel_init_freeable from kernel_init+0x18/0x12c
>   kernel_init from ret_from_fork+0x14/0x2c
> Exception stack(0xc1caffb0 to 0xc1cafff8)
> ffa0:                                     00000000 00000000 00000000
> 00000000
> ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> 00000000
> ffe0: 00000000 00000000 00000000 00000000 00000013 00000000
> Code: e5904040 e1a00002 e3a02002 e1a01004 (e5945048)
> ---[ end trace 0000000000000000 ]---
> Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
> CPU1: stopping
> CPU: 1 PID: 0 Comm: swapper/1 Tainted: G      D
> 5.17.0-rc2-00577-g22e968113668-dirty #11635
> Hardware name: Samsung Exynos (Flattened Device Tree)
>   unwind_backtrace from show_stack+0x10/0x14
>   show_stack from dump_stack_lvl+0x58/0x70
>   dump_stack_lvl from do_handle_IPI+0x2ec/0x36c
>   do_handle_IPI from ipi_handler+0x18/0x20
>   ipi_handler from handle_percpu_devid_irq+0xd0/0x394
>   handle_percpu_devid_irq from generic_handle_domain_irq+0x44/0x88
>   generic_handle_domain_irq from gic_handle_irq+0x88/0xac
>   gic_handle_irq from generic_handle_arch_irq+0x58/0x78
>   generic_handle_arch_irq from __irq_svc+0x54/0x88
> Exception stack(0xc1cd1f48 to 0xc1cd1f90)
> 1f40:                   00000001 c0eff5a4 00000001 c011ca80 c1208f0c
> c1353420
> 1f60: 00000000 c1d8d000 00000000 c0f34234 c1d8d000 00000000 c0eeee98
> c1cd1f98
> 1f80: c0109144 c0109148 20000013 ffffffff
>   __irq_svc from arch_cpu_idle+0x40/0x44
>   arch_cpu_idle from default_idle_call+0x74/0x2c4
>   default_idle_call from do_idle+0x1cc/0x284
>   do_idle from cpu_startup_entry+0x18/0x1c
>   cpu_startup_entry from 0x401018b4
> ---[ end Kernel panic - not syncing: Attempted to kill init!
> exitcode=0x0000000b ]---
>
>
> I will try to take a look into this later in the evening.
>
>
> Best regards
> --
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
>

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

* Re: [PATCH 01/11] drm: bridge: Add Samsung DSIM bridge driver
  2022-04-08 16:20   ` [PATCH 01/11] drm: bridge: Add Samsung DSIM bridge driver Jagan Teki
@ 2022-04-12  9:45     ` Marek Szyprowski
  2022-05-04  9:16       ` Jagan Teki
  0 siblings, 1 reply; 27+ messages in thread
From: Marek Szyprowski @ 2022-04-12  9:45 UTC (permalink / raw)
  To: Jagan Teki, Andrzej Hajda, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel

Hi Jagan,

On 08.04.2022 18:20, Jagan Teki wrote:
> Samsung MIPI DSIM controller is common DSI IP that can be used in various
> SoCs like Exynos, i.MX8M Mini/Nano.
>
> In order to access this DSI controller between various platform SoCs, the
> ideal way to incorporate this in the drm stack is via the drm bridge driver.
>
> This patch is trying to differentiate platform-specific and bridge driver
> code and keep maintaining the exynos_drm_dsi.c code as platform-specific
> glue code and samsung-dsim.c as a common bridge driver code.
>
> - Exynos specific glue code is exynos specific te_irq, host_attach, and
>    detach code along with conventional component_ops.
>
> - Samsung DSIM is a bridge driver which is common across all platforms and
>    the respective platform-specific glue will initialize at the end of the
>    probe. The platform-specific operations and other glue calls will invoke
>    on associate code areas.
>
> 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.
>
> v1:
> * Don't maintain component_ops in bridge driver
> * Don't maintain platform glue code in bridge driver
> * Add platform-specific glue code and make a common bridge
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>

Well, it took me a while to make this working on Exynos. I'm not really 
happy of the design, although I didn't spent much time thinking how to 
improve it and clarify some ambiguities. It doesn't even look that one 
has compiled the Exynos code after this conversion.

The following changes are needed to get it to the same working state as 
before this patch (the next patches however break it even further):

commit e358ee6239305744062713c5aa2e8d44f740b81a (HEAD)
Author: Marek Szyprowski <m.szyprowski@samsung.com>
Date:   Tue Apr 12 11:30:26 2022 +0200

     drm: exynos: dsi: fixup driver after conversion

     Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>

diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c 
b/drivers/gpu/drm/bridge/samsung-dsim.c
index ee5d7e5518a6..8e0064282ce6 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -17,7 +17,6 @@

  #include <linux/clk.h>
  #include <linux/delay.h>
-#include <linux/gpio/consumer.h>
  #include <linux/irq.h>
  #include <linux/of_device.h>
  #include <linux/phy/phy.h>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 97167c5ffc78..bbfacb22d99d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -8,6 +8,7 @@
   */

  #include <linux/component.h>
+#include <linux/gpio/consumer.h>

  #include <drm/bridge/samsung-dsim.h>
  #include <drm/drm_probe_helper.h>
@@ -25,17 +26,19 @@ struct exynos_dsi {
         struct samsung_dsim_plat_data pdata;
  };

-static void exynos_dsi_enable_irq(void *priv)
+static void exynos_dsi_enable_irq(struct samsung_dsim *priv)
  {
-       struct exynos_dsi *dsi = priv;
+       const struct samsung_dsim_plat_data *pdata = priv->plat_data;
+       struct exynos_dsi *dsi = container_of(pdata, struct exynos_dsi, 
pdata);

         if (dsi->te_gpio)
                 enable_irq(gpiod_to_irq(dsi->te_gpio));
  }

-static void exynos_dsi_disable_irq(void *priv)
+static void exynos_dsi_disable_irq(struct samsung_dsim *priv)
  {
-       struct exynos_dsi *dsi = priv;
+       const struct samsung_dsim_plat_data *pdata = priv->plat_data;
+       struct exynos_dsi *dsi = container_of(pdata, struct exynos_dsi, 
pdata);

         if (dsi->te_gpio)
                 disable_irq(gpiod_to_irq(dsi->te_gpio));
@@ -92,15 +95,15 @@ static void exynos_dsi_unregister_te_irq(struct 
exynos_dsi *dsi)
         }
  }

-static int exynos_dsi_host_attach(void *priv, struct mipi_dsi_device 
*device)
+static int exynos_dsi_host_attach(struct samsung_dsim *priv, struct 
mipi_dsi_device *device)
  {
-       struct exynos_dsi *dsi = priv;
-       struct samsung_dsim *_priv = dsi->priv;
+       const struct samsung_dsim_plat_data *pdata = priv->plat_data;
+       struct exynos_dsi *dsi = container_of(pdata, struct exynos_dsi, 
pdata);
         struct drm_encoder *encoder = &dsi->encoder;
         struct drm_device *drm = encoder->dev;
         int ret;

-       drm_bridge_attach(encoder, &_priv->bridge, NULL, 0);
+       drm_bridge_attach(encoder, &priv->bridge, NULL, 0);

         /*
          * This is a temporary solution and should be made by more 
generic way.
@@ -116,11 +119,11 @@ static int exynos_dsi_host_attach(void *priv, 
struct mipi_dsi_device *device)

         mutex_lock(&drm->mode_config.mutex);

-       _priv->lanes = device->lanes;
-       _priv->format = device->format;
-       _priv->mode_flags = device->mode_flags;
+       priv->lanes = device->lanes;
+       priv->format = device->format;
+       priv->mode_flags = device->mode_flags;
         exynos_drm_crtc_get_by_type(drm, 
EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
-                       !(_priv->mode_flags & MIPI_DSI_MODE_VIDEO);
+                       !(priv->mode_flags & MIPI_DSI_MODE_VIDEO);

         mutex_unlock(&drm->mode_config.mutex);

@@ -130,9 +133,10 @@ static int exynos_dsi_host_attach(void *priv, 
struct mipi_dsi_device *device)
         return 0;
  }

-static int exynos_dsi_host_detach(void *priv, struct mipi_dsi_device 
*device)
+static int exynos_dsi_host_detach(struct samsung_dsim *priv, struct 
mipi_dsi_device *device)
  {
-       struct exynos_dsi *dsi = priv;
+       const struct samsung_dsim_plat_data *pdata = priv->plat_data;
+       struct exynos_dsi *dsi = container_of(pdata, struct exynos_dsi, 
pdata);
         struct drm_device *drm = dsi->encoder.dev;

         if (drm->mode_config.poll_enabled)
@@ -150,8 +154,9 @@ static const struct samsung_dsim_host_ops 
samsung_dsim_exynos_host_ops = {

  static int exynos_dsi_bind(struct device *dev, struct device *master, 
void *data)
  {
-       struct exynos_dsi *dsi = dev_get_drvdata(dev);
-       struct samsung_dsim *priv = dsi->priv;
+       struct samsung_dsim *priv = dev_get_drvdata(dev);
+       const struct samsung_dsim_plat_data *pdata = priv->plat_data;
+       struct exynos_dsi *dsi = container_of(pdata, struct exynos_dsi, 
pdata);
         struct drm_encoder *encoder = &dsi->encoder;
         struct drm_device *drm_dev = data;
         int ret;
@@ -167,8 +172,7 @@ static int exynos_dsi_bind(struct device *dev, 
struct device *master, void *data

  static void exynos_dsi_unbind(struct device *dev, struct device 
*master, void *data)
  {
-       struct exynos_dsi *dsi = dev_get_drvdata(dev);
-       struct samsung_dsim *priv = dsi->priv;
+       struct samsung_dsim *priv = dev_get_drvdata(dev);

priv->bridge.funcs->atomic_disable(&priv->bridge, NULL);

diff --git a/include/drm/bridge/samsung-dsim.h 
b/include/drm/bridge/samsung-dsim.h
index 59a43f9c4477..9f579a798635 100644
--- a/include/drm/bridge/samsung-dsim.h
+++ b/include/drm/bridge/samsung-dsim.h
@@ -41,14 +41,18 @@ struct samsung_dsim_driver_data {
         const unsigned int *reg_values;
  };

+struct samsung_dsim;
+
  struct samsung_dsim_host_ops {
-       int (*attach)(void *priv, struct mipi_dsi_device *device);
-       int (*detach)(void *priv, struct mipi_dsi_device *device);
+       int (*attach)(struct samsung_dsim *priv,
+                     struct mipi_dsi_device *device);
+       int (*detach)(struct samsung_dsim *priv,
+                     struct mipi_dsi_device *device);
  };

  struct samsung_dsim_irq_ops {
-       void (*enable)(void *priv);
-       void (*disable)(void *priv);
+       void (*enable)(struct samsung_dsim *priv);
+       void (*disable)(struct samsung_dsim *priv);
  };

  struct samsung_dsim_plat_data {


> ---
>   MAINTAINERS                             |   12 +
>   drivers/gpu/drm/bridge/Kconfig          |   12 +
>   drivers/gpu/drm/bridge/Makefile         |    1 +
>   drivers/gpu/drm/bridge/samsung-dsim.c   | 1676 ++++++++++++++++++++++
>   drivers/gpu/drm/exynos/Kconfig          |    1 +
>   drivers/gpu/drm/exynos/exynos_drm_dsi.c | 1704 +----------------------
>   include/drm/bridge/samsung-dsim.h       |   95 ++
>   7 files changed, 1852 insertions(+), 1649 deletions(-)
>   create mode 100644 drivers/gpu/drm/bridge/samsung-dsim.c
>   create mode 100644 include/drm/bridge/samsung-dsim.h
>
> ...

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


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

* Re: [PATCH 02/11] drm: bridge: samsung-dsim: Handle platform init via driver_data
  2022-04-08 16:20   ` [PATCH 02/11] drm: bridge: samsung-dsim: Handle platform init via driver_data Jagan Teki
@ 2022-04-12  9:55     ` Marek Szyprowski
  0 siblings, 0 replies; 27+ messages in thread
From: Marek Szyprowski @ 2022-04-12  9:55 UTC (permalink / raw)
  To: Jagan Teki, Andrzej Hajda, Inki Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, Frieder Schrempf, Fancy Fang,
	Tim Harvey, Michael Nazzareno Trimarchi, Adam Ford,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Rob Herring
  Cc: devicetree, linux-samsung-soc, dri-devel, NXP Linux Team,
	linux-amarula, linux-arm-kernel


On 08.04.2022 18:20, Jagan Teki wrote:
> In order to make a common Samsung DSIM bridge driver some platform specific
> glue code needs to maintain separately as it is hard to maintain platform
> specific glue and conventional component_ops on the drm bridge drivers side.
>
> This patch is trying to support that glue code initialization and invocation
> in the form of platform_init flag in driver_data.
>
> So, the platforms which enable platform_init flags will handle all platform
> specific initialization via samsung_dsim_plat_probe.
>
> The Platform probe is responsible to
> - initialize samsung_dsim_plat_data and install hooks
> - initialize component_ops
> - preserve samsung_dsim structure pointer
>
> v1:
> * use platform_init instead of exynos_specific
> * handle component_ops in glue code
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>   drivers/gpu/drm/bridge/samsung-dsim.c | 20 ++++++++++++++++----
>   include/drm/bridge/samsung-dsim.h     |  1 +
>   2 files changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
> index ee5d7e5518a6..0e6a5d1c7e4e 100644
> --- a/drivers/gpu/drm/bridge/samsung-dsim.c
> +++ b/drivers/gpu/drm/bridge/samsung-dsim.c
> @@ -370,6 +370,7 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
>   	.wait_for_reset = 1,
>   	.num_bits_resol = 11,
>   	.reg_values = reg_values,
> +	.platform_init = true,
>   };
>   
>   static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
> @@ -382,6 +383,7 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
>   	.wait_for_reset = 1,
>   	.num_bits_resol = 11,
>   	.reg_values = reg_values,
> +	.platform_init = true,
>   };
>   
>   static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
> @@ -392,6 +394,7 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
>   	.wait_for_reset = 1,
>   	.num_bits_resol = 11,
>   	.reg_values = reg_values,
> +	.platform_init = true,
>   };
>   
>   static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
> @@ -403,6 +406,7 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
>   	.wait_for_reset = 0,
>   	.num_bits_resol = 12,
>   	.reg_values = exynos5433_reg_values,
> +	.platform_init = true,
>   };
>   
>   static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
> @@ -414,6 +418,7 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
>   	.wait_for_reset = 1,
>   	.num_bits_resol = 12,
>   	.reg_values = exynos5422_reg_values,
> +	.platform_init = true,
>   };
>   
>   static const struct of_device_id samsung_dsim_of_match[] = {
> @@ -1565,12 +1570,16 @@ static int samsung_dsim_probe(struct platform_device *pdev)
>   	dsi->bridge.of_node = dev->of_node;
>   	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>   
> -	dsi->plat_data = samsung_dsim_plat_probe(dsi);
> -	if (IS_ERR(dsi->plat_data)) {
> +	if (dsi->driver_data->platform_init) {
> +		dsi->plat_data = samsung_dsim_plat_probe(dsi);
>   		ret = PTR_ERR(dsi->plat_data);

ret = IS_ERR(dsi->plat_data) ? PTR_ERR(dsi->plat_data) : 0;

otherwise it always fails.

> -		goto err_disable_runtime;
> +	} else {
> +		ret = mipi_dsi_host_register(&dsi->dsi_host);
>   	}
>   
> +	if (ret)
> +		goto err_disable_runtime;
> +
>   	return 0;
>   
>   err_disable_runtime:
> @@ -1585,7 +1594,10 @@ static int samsung_dsim_remove(struct platform_device *pdev)
>   
>   	pm_runtime_disable(&pdev->dev);
>   
> -	samsung_dsim_plat_remove(dsi);
> +	if (dsi->driver_data->platform_init)
> +		samsung_dsim_plat_remove(dsi);
> +	else
> +		mipi_dsi_host_unregister(&dsi->dsi_host);
>   
>   	return 0;
>   }
> diff --git a/include/drm/bridge/samsung-dsim.h b/include/drm/bridge/samsung-dsim.h
> index 59a43f9c4477..eca7eacb5910 100644
> --- a/include/drm/bridge/samsung-dsim.h
> +++ b/include/drm/bridge/samsung-dsim.h
> @@ -39,6 +39,7 @@ struct samsung_dsim_driver_data {
>   	unsigned int wait_for_reset;
>   	unsigned int num_bits_resol;
>   	const unsigned int *reg_values;
> +	bool platform_init;
>   };
>   
>   struct samsung_dsim_host_ops {

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


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

* Re: [PATCH 10/11] dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support
  2022-04-10 18:12     ` Laurent Pinchart
@ 2022-04-29  9:40       ` Jagan Teki
  0 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2022-04-29  9:40 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, devicetree, linux-samsung-soc, Joonyoung Shim,
	Neil Armstrong, linux-amarula, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Robert Foss,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	Adam Ford, linux-arm-kernel, Marek Szyprowski

Hi Laurent,

On Sun, Apr 10, 2022 at 11:42 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Jagan,
>
> Thank you for the patch.
>
> On Fri, Apr 08, 2022 at 09:51:07PM +0530, Jagan Teki wrote:
> > Samsung MIPI DSIM bridge can also be found in i.MX8MM/i.MX8MN SoC.
> >
> > Add dt-bingings for it.
> >
> > v1:
> > * new patch
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> > index be377786e8cd..5133d4d39190 100644
> > --- a/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> > +++ b/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
> > @@ -7,6 +7,7 @@ Required properties:
>
> May I try and ask you to convert the DT bindings to YAML as part of this
> series ? :-)

I thought the same and I did it for RFC
https://patchwork.kernel.org/project/dri-devel/patch/20210704090230.26489-9-jagan@amarulasolutions.com/

But, I'm thinking of sending a separate patch series for updating yaml
as the existing binding is old that it has some properties need to
fix.

Let me know if you are okay or not for it?

>
> >               "samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
> >               "samsung,exynos5422-mipi-dsi" /* for Exynos5422/5800 SoCs */
> >               "samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
> > +             "fsl,imx8mm-mipi-dsim" /* for i.MX8M Mini/Nano SoCs */
>
> Should we have two different compatible strings for i.MX8MM and i.MX8MN
> ?

Yes, MN is fallback to MM. I will update in next series or add it as
part of yaml conversion series.

Thanks,
Jagan.

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

* Re: [PATCH 01/11] drm: bridge: Add Samsung DSIM bridge driver
  2022-04-12  9:45     ` Marek Szyprowski
@ 2022-05-04  9:16       ` Jagan Teki
  2022-05-04  9:44         ` Marek Szyprowski
  0 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2022-05-04  9:16 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: dri-devel, devicetree, linux-samsung-soc, Joonyoung Shim,
	Neil Armstrong, linux-amarula, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Robert Foss,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	Adam Ford, linux-arm-kernel, Laurent Pinchart

Hi Marek,

On Tue, Apr 12, 2022 at 3:15 PM Marek Szyprowski
<m.szyprowski@samsung.com> wrote:
>
> Hi Jagan,
>
> On 08.04.2022 18:20, Jagan Teki wrote:
> > Samsung MIPI DSIM controller is common DSI IP that can be used in various
> > SoCs like Exynos, i.MX8M Mini/Nano.
> >
> > In order to access this DSI controller between various platform SoCs, the
> > ideal way to incorporate this in the drm stack is via the drm bridge driver.
> >
> > This patch is trying to differentiate platform-specific and bridge driver
> > code and keep maintaining the exynos_drm_dsi.c code as platform-specific
> > glue code and samsung-dsim.c as a common bridge driver code.
> >
> > - Exynos specific glue code is exynos specific te_irq, host_attach, and
> >    detach code along with conventional component_ops.
> >
> > - Samsung DSIM is a bridge driver which is common across all platforms and
> >    the respective platform-specific glue will initialize at the end of the
> >    probe. The platform-specific operations and other glue calls will invoke
> >    on associate code areas.
> >
> > 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.
> >
> > v1:
> > * Don't maintain component_ops in bridge driver
> > * Don't maintain platform glue code in bridge driver
> > * Add platform-specific glue code and make a common bridge
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>
> Well, it took me a while to make this working on Exynos. I'm not really
> happy of the design, although I didn't spent much time thinking how to
> improve it and clarify some ambiguities. It doesn't even look that one
> has compiled the Exynos code after this conversion.

Well, I was successfully built the each commit on exynos and non-exynos

>
> The following changes are needed to get it to the same working state as
> before this patch (the next patches however break it even further):
>
> commit e358ee6239305744062713c5aa2e8d44f740b81a (HEAD)
> Author: Marek Szyprowski <m.szyprowski@samsung.com>
> Date:   Tue Apr 12 11:30:26 2022 +0200
>
>      drm: exynos: dsi: fixup driver after conversion

What exactly it is fixing the existing conversion, could you point that out?

Jagan.

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

* Re: [PATCH 01/11] drm: bridge: Add Samsung DSIM bridge driver
  2022-05-04  9:16       ` Jagan Teki
@ 2022-05-04  9:44         ` Marek Szyprowski
  0 siblings, 0 replies; 27+ messages in thread
From: Marek Szyprowski @ 2022-05-04  9:44 UTC (permalink / raw)
  To: Jagan Teki
  Cc: dri-devel, devicetree, linux-samsung-soc, Joonyoung Shim,
	Neil Armstrong, linux-amarula, Seung-Woo Kim, NXP Linux Team,
	Frieder Schrempf, Kyungmin Park, Rob Herring, Robert Foss,
	Andrzej Hajda, Fancy Fang, Michael Nazzareno Trimarchi,
	Adam Ford, linux-arm-kernel, Laurent Pinchart

Hi Jagan,

On 04.05.2022 11:16, Jagan Teki wrote:
> Hi Marek,
>
> On Tue, Apr 12, 2022 at 3:15 PM Marek Szyprowski
> <m.szyprowski@samsung.com> wrote:
>> Hi Jagan,
>>
>> On 08.04.2022 18:20, Jagan Teki wrote:
>>> Samsung MIPI DSIM controller is common DSI IP that can be used in various
>>> SoCs like Exynos, i.MX8M Mini/Nano.
>>>
>>> In order to access this DSI controller between various platform SoCs, the
>>> ideal way to incorporate this in the drm stack is via the drm bridge driver.
>>>
>>> This patch is trying to differentiate platform-specific and bridge driver
>>> code and keep maintaining the exynos_drm_dsi.c code as platform-specific
>>> glue code and samsung-dsim.c as a common bridge driver code.
>>>
>>> - Exynos specific glue code is exynos specific te_irq, host_attach, and
>>>     detach code along with conventional component_ops.
>>>
>>> - Samsung DSIM is a bridge driver which is common across all platforms and
>>>     the respective platform-specific glue will initialize at the end of the
>>>     probe. The platform-specific operations and other glue calls will invoke
>>>     on associate code areas.
>>>
>>> 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.
>>>
>>> v1:
>>> * Don't maintain component_ops in bridge driver
>>> * Don't maintain platform glue code in bridge driver
>>> * Add platform-specific glue code and make a common bridge
>>>
>>> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>> Well, it took me a while to make this working on Exynos. I'm not really
>> happy of the design, although I didn't spent much time thinking how to
>> improve it and clarify some ambiguities. It doesn't even look that one
>> has compiled the Exynos code after this conversion.
> Well, I was successfully built the each commit on exynos and non-exynos
>
>> The following changes are needed to get it to the same working state as
>> before this patch (the next patches however break it even further):
>>
>> commit e358ee6239305744062713c5aa2e8d44f740b81a (HEAD)
>> Author: Marek Szyprowski <m.szyprowski@samsung.com>
>> Date:   Tue Apr 12 11:30:26 2022 +0200
>>
>>       drm: exynos: dsi: fixup driver after conversion
> What exactly it is fixing the existing conversion, could you point that out?

See the diff. Broken build (missing gpio_consumer.h in exynos-dsi), 
mixed structures put into drvdata (samsung_dsim vs. exynos_dsi) hidden 
by the casting to void * in the samsung_dsim_host_ops.

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


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

end of thread, other threads:[~2022-05-04  9:44 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20220408162213eucas1p158d7c7ee27006a61d4af95d3c72c58e3@eucas1p1.samsung.com>
2022-04-08 16:20 ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Jagan Teki
2022-04-08 16:20   ` [PATCH 01/11] drm: bridge: Add Samsung DSIM bridge driver Jagan Teki
2022-04-12  9:45     ` Marek Szyprowski
2022-05-04  9:16       ` Jagan Teki
2022-05-04  9:44         ` Marek Szyprowski
2022-04-08 16:20   ` [PATCH 02/11] drm: bridge: samsung-dsim: Handle platform init via driver_data Jagan Teki
2022-04-12  9:55     ` Marek Szyprowski
2022-04-08 16:21   ` [PATCH 03/11] drm: bridge: samsung-dsim: Mark PHY as optional Jagan Teki
2022-04-08 16:21   ` [PATCH 04/11] drm: bridge: samsung-dsim: Add DSI init in bridge pre_enable() Jagan Teki
2022-04-11 12:23     ` Adam Ford
2022-04-08 16:21   ` [PATCH 05/11] drm: bridge: samsung-dsim: Fix PLL_P (PMS_P) offset Jagan Teki
2022-04-08 16:21   ` [PATCH 06/11] drm: bridge: samsung-dsim: Add module init, exit Jagan Teki
2022-04-08 16:21   ` [PATCH 07/11] drm: bridge: samsung-dsim: Add atomic_check Jagan Teki
2022-04-08 16:21   ` [PATCH 08/11] drm: bridge: samsung-dsim: Add atomic_get_input_bus_fmts Jagan Teki
2022-04-08 16:21   ` [PATCH 09/11] drm: bridge: samsung-dsim: Add input_bus_flags Jagan Teki
2022-04-08 16:21   ` [PATCH 10/11] dt-bindings: display: exynos: dsim: Add NXP i.MX8MM support Jagan Teki
2022-04-10 18:12     ` Laurent Pinchart
2022-04-29  9:40       ` Jagan Teki
2022-04-08 16:21   ` [PATCH 11/11] drm: bridge: samsung-dsim: Add " Jagan Teki
2022-04-10 18:06     ` Laurent Pinchart
2022-04-09  0:25   ` [PATCH 00/11] drm: bridge: Add Samsung MIPI DSIM bridge Tim Harvey
2022-04-11 13:11   ` (EXT) " Alexander Stein
2022-04-11 13:56   ` Marek Szyprowski
2022-04-11 14:39     ` Adam Ford
2022-04-11 15:29       ` Adam Ford
2022-04-11 16:25       ` Marek Szyprowski
2022-04-11 20:26         ` Adam Ford

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).