diff --git a/drivers/gpu/imx/dpu/dpu-common.c b/drivers/gpu/imx/dpu/dpu-common.c
index ff8dd52e062410490cf1167af22654ca3142fcea..b14ce5414d8a4d03421b02c93607728f103bdf23 100644
--- a/drivers/gpu/imx/dpu/dpu-common.c
+++ b/drivers/gpu/imx/dpu/dpu-common.c
@@ -648,6 +648,39 @@ int dpu_format_plane_height(int height, u32 format, int plane)
 	return height / dpu_format_vert_chroma_subsampling(format);
 }
 
+#define _DPU_UNITS_INIT(unit)						\
+{									\
+	const struct dpu_unit *us = devtype->unit##s;			\
+	int i;								\
+									\
+	/* software check */						\
+	if (WARN_ON(us->num > ARRAY_SIZE(unit##_ids)))			\
+		return -EINVAL;						\
+									\
+	for (i = 0; i < us->num; i++)					\
+		_dpu_##unit##_init(dpu, us->ids[i]);			\
+}
+
+static int
+_dpu_submodules_init(struct dpu_soc *dpu, struct platform_device *pdev)
+{
+	const struct dpu_devtype *devtype = dpu->devtype;
+
+	_DPU_UNITS_INIT(cf);
+	_DPU_UNITS_INIT(dec);
+	_DPU_UNITS_INIT(ed);
+	_DPU_UNITS_INIT(fd);
+	_DPU_UNITS_INIT(fe);
+	_DPU_UNITS_INIT(fg);
+	_DPU_UNITS_INIT(fl);
+	_DPU_UNITS_INIT(hs);
+	_DPU_UNITS_INIT(lb);
+	_DPU_UNITS_INIT(tcon);
+	_DPU_UNITS_INIT(vs);
+
+	return 0;
+}
+
 #define DPU_UNIT_INIT(dpu, base, unit, name, id, pec_ofs, ofs)		\
 {									\
 	int ret;							\
@@ -1509,8 +1542,37 @@ static int dpu_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int dpu_suspend(struct device *dev)
+{
+	/*
+	 * The dpu core driver currently depends on the client drivers
+	 * to do suspend operations to leave dpu a cleaned up state
+	 * machine status before the system enters sleep mode.
+	 */
+	return 0;
+}
+
+static int dpu_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct dpu_soc *dpu = platform_get_drvdata(pdev);
+
+	dpu_intsteer_enable_lines(dpu);
+
+	dpu_pixel_link_init(dpu->id);
+
+	_dpu_submodules_init(dpu, pdev);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(dpu_pm_ops, dpu_suspend, dpu_resume);
+
 static struct platform_driver dpu_driver = {
 	.driver = {
+		.pm = &dpu_pm_ops,
 		.name = "dpu-core",
 		.of_match_table = dpu_dt_ids,
 	},
diff --git a/drivers/gpu/imx/dpu/dpu-constframe.c b/drivers/gpu/imx/dpu/dpu-constframe.c
index 77718cdd1d6d7ea5b85e0e42b8ac2d4ce6731166..1290545809e8bfc2335b937b4a3b909413cd075a 100644
--- a/drivers/gpu/imx/dpu/dpu-constframe.c
+++ b/drivers/gpu/imx/dpu/dpu-constframe.c
@@ -166,6 +166,20 @@ void dpu_cf_put(struct dpu_constframe *cf)
 }
 EXPORT_SYMBOL_GPL(dpu_cf_put);
 
+void _dpu_cf_init(struct dpu_soc *dpu, unsigned int id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cf_ids); i++)
+		if (cf_ids[i] == id)
+			break;
+
+	if (WARN_ON(i == ARRAY_SIZE(cf_ids)))
+		return;
+
+	constframe_shden(dpu->cf_priv[i], true);
+}
+
 int dpu_cf_init(struct dpu_soc *dpu, unsigned int id,
 		unsigned long pec_base, unsigned long base)
 {
@@ -196,7 +210,7 @@ int dpu_cf_init(struct dpu_soc *dpu, unsigned int id,
 
 	mutex_init(&cf->mutex);
 
-	constframe_shden(cf, true);
+	_dpu_cf_init(dpu, id);
 
 	return 0;
 }
diff --git a/drivers/gpu/imx/dpu/dpu-disengcfg.c b/drivers/gpu/imx/dpu/dpu-disengcfg.c
index 05688929b2c55e615f3bccc2512c885a1370b606..007da25d4f98f8452319f4799967a45978bbc5d1 100644
--- a/drivers/gpu/imx/dpu/dpu-disengcfg.c
+++ b/drivers/gpu/imx/dpu/dpu-disengcfg.c
@@ -115,6 +115,10 @@ void dpu_dec_put(struct dpu_disengcfg *dec)
 }
 EXPORT_SYMBOL_GPL(dpu_dec_put);
 
+void _dpu_dec_init(struct dpu_soc *dpu, unsigned int id)
+{
+}
+
 int dpu_dec_init(struct dpu_soc *dpu, unsigned int id,
 			unsigned long unused, unsigned long base)
 {
diff --git a/drivers/gpu/imx/dpu/dpu-extdst.c b/drivers/gpu/imx/dpu/dpu-extdst.c
index fdb85723c668bb3f7ea13dd5b079ee70da4aaf98..ab79fe6a02c8186214c018f0063117df03798e07 100644
--- a/drivers/gpu/imx/dpu/dpu-extdst.c
+++ b/drivers/gpu/imx/dpu/dpu-extdst.c
@@ -440,6 +440,31 @@ void dpu_ed_put(struct dpu_extdst *ed)
 }
 EXPORT_SYMBOL_GPL(dpu_ed_put);
 
+void _dpu_ed_init(struct dpu_soc *dpu, unsigned int id)
+{
+	struct dpu_extdst *ed;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ed_ids); i++)
+		if (ed_ids[i] == id)
+			break;
+
+	if (WARN_ON(i == ARRAY_SIZE(ed_ids)))
+		return;
+
+	ed = dpu->ed_priv[i];
+
+	extdst_pixengcfg_src_sel(ed, ED_SRC_DISABLE);
+	extdst_pixengcfg_shden(ed, true);
+	extdst_pixengcfg_powerdown(ed, false);
+	extdst_pixengcfg_sync_mode(ed, SINGLE);
+	extdst_pixengcfg_reset(ed, false);
+	extdst_pixengcfg_div(ed, DIV_RESET);
+	extdst_shden(ed, true);
+	extdst_perfcountmode(ed, false);
+	extdst_kick_mode(ed, EXTERNAL);
+}
+
 int dpu_ed_init(struct dpu_soc *dpu, unsigned int id,
 		unsigned long pec_base, unsigned long base)
 {
@@ -472,14 +497,7 @@ int dpu_ed_init(struct dpu_soc *dpu, unsigned int id,
 	if (ret < 0)
 		return ret;
 
-	extdst_pixengcfg_shden(ed, true);
-	extdst_pixengcfg_powerdown(ed, false);
-	extdst_pixengcfg_sync_mode(ed, SINGLE);
-	extdst_pixengcfg_reset(ed, false);
-	extdst_pixengcfg_div(ed, DIV_RESET);
-	extdst_shden(ed, true);
-	extdst_perfcountmode(ed, false);
-	extdst_kick_mode(ed, EXTERNAL);
+	_dpu_ed_init(dpu, id);
 
 	return 0;
 }
diff --git a/drivers/gpu/imx/dpu/dpu-fetchdecode.c b/drivers/gpu/imx/dpu/dpu-fetchdecode.c
index c28e110ec7a699c62e9b46bc5763096aec5134aa..fe5dd37dbedf8045b06e964d38f215e5dbeabee6 100644
--- a/drivers/gpu/imx/dpu/dpu-fetchdecode.c
+++ b/drivers/gpu/imx/dpu/dpu-fetchdecode.c
@@ -714,6 +714,30 @@ void dpu_fd_put(struct dpu_fetchdecode *fd)
 }
 EXPORT_SYMBOL_GPL(dpu_fd_put);
 
+void _dpu_fd_init(struct dpu_soc *dpu, unsigned int id)
+{
+	struct dpu_fetchdecode *fd;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fd_ids); i++)
+		if (fd_ids[i] == id)
+			break;
+
+	if (WARN_ON(i == ARRAY_SIZE(fd_ids)))
+		return;
+
+	fd = dpu->fd_priv[i];
+
+	fetchdecode_pixengcfg_dynamic_src_sel(fd, FD_SRC_DISABLE);
+	fetchdecode_baddr_autoupdate(fd, 0x0);
+	fetchdecode_shden(fd, true);
+
+	mutex_lock(&fd->mutex);
+	dpu_fd_write(fd, SETNUMBUFFERS(16) | SETBURSTLENGTH(16),
+			BURSTBUFFERMANAGEMENT);
+	mutex_unlock(&fd->mutex);
+}
+
 int dpu_fd_init(struct dpu_soc *dpu, unsigned int id,
 		unsigned long pec_base, unsigned long base)
 {
@@ -752,13 +776,7 @@ int dpu_fd_init(struct dpu_soc *dpu, unsigned int id,
 	if (ret < 0)
 		return ret;
 
-	fetchdecode_baddr_autoupdate(fd, 0x0);
-	fetchdecode_shden(fd, true);
-
-	mutex_lock(&fd->mutex);
-	dpu_fd_write(fd, SETNUMBUFFERS(16) | SETBURSTLENGTH(16),
-			BURSTBUFFERMANAGEMENT);
-	mutex_unlock(&fd->mutex);
+	_dpu_fd_init(dpu, id);
 
 	return 0;
 }
diff --git a/drivers/gpu/imx/dpu/dpu-fetcheco.c b/drivers/gpu/imx/dpu/dpu-fetcheco.c
index c3ac6fd7cdf28612dbafac3e4050d026eb027812..28d6e80afe8918f98ded25d3a4d4530a76f5d4ab 100644
--- a/drivers/gpu/imx/dpu/dpu-fetcheco.c
+++ b/drivers/gpu/imx/dpu/dpu-fetcheco.c
@@ -478,6 +478,28 @@ void dpu_fe_put(struct dpu_fetcheco *fe)
 }
 EXPORT_SYMBOL_GPL(dpu_fe_put);
 
+void _dpu_fe_init(struct dpu_soc *dpu, unsigned int id)
+{
+	struct dpu_fetcheco *fe;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fe_ids); i++)
+		if (fe_ids[i] == id)
+			break;
+
+	if (WARN_ON(i == ARRAY_SIZE(fe_ids)))
+		return;
+
+	fe = dpu->fe_priv[i];
+
+	fetcheco_shden(fe, true);
+
+	mutex_lock(&fe->mutex);
+	dpu_fe_write(fe, SETNUMBUFFERS(16) | SETBURSTLENGTH(16),
+			BURSTBUFFERMANAGEMENT);
+	mutex_unlock(&fe->mutex);
+}
+
 int dpu_fe_init(struct dpu_soc *dpu, unsigned int id,
 		unsigned long pec_base, unsigned long base)
 {
@@ -506,12 +528,7 @@ int dpu_fe_init(struct dpu_soc *dpu, unsigned int id,
 	fe->id = id;
 	mutex_init(&fe->mutex);
 
-	fetcheco_shden(fe, true);
-
-	mutex_lock(&fe->mutex);
-	dpu_fe_write(fe, SETNUMBUFFERS(16) | SETBURSTLENGTH(16),
-			BURSTBUFFERMANAGEMENT);
-	mutex_unlock(&fe->mutex);
+	_dpu_fe_init(dpu, id);
 
 	return 0;
 }
diff --git a/drivers/gpu/imx/dpu/dpu-fetchlayer.c b/drivers/gpu/imx/dpu/dpu-fetchlayer.c
index fdc8c143788884d8149b104fc8bca5fd0ea8e103..4fe74ee3cd58e41189214a73004f3d326ac7aba1 100644
--- a/drivers/gpu/imx/dpu/dpu-fetchlayer.c
+++ b/drivers/gpu/imx/dpu/dpu-fetchlayer.c
@@ -257,6 +257,10 @@ void dpu_fl_put(struct dpu_fetchlayer *fl)
 }
 EXPORT_SYMBOL_GPL(dpu_fl_put);
 
+void _dpu_fl_init(struct dpu_soc *dpu, unsigned int id)
+{
+}
+
 int dpu_fl_init(struct dpu_soc *dpu, unsigned int id,
 		unsigned long pec_base, unsigned long base)
 {
diff --git a/drivers/gpu/imx/dpu/dpu-framegen.c b/drivers/gpu/imx/dpu/dpu-framegen.c
index b068e7ca313cc8e5e85540492a78685ec190849b..d7dba5a3c8d032ac37d1d5c79da8e187065fd421 100644
--- a/drivers/gpu/imx/dpu/dpu-framegen.c
+++ b/drivers/gpu/imx/dpu/dpu-framegen.c
@@ -261,6 +261,9 @@ void framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m)
 	dpu_fg_write(fg, 0, FGCCR);
 	mutex_unlock(&fg->mutex);
 
+	clk_get_rate(fg->clk_pll);
+	clk_get_rate(fg->clk_disp);
+
 	disp_clock_rate = m->clock * 1000;
 
 	if (devtype->version == DPU_V1) {
@@ -412,11 +415,33 @@ void dpu_fg_put(struct dpu_framegen *fg)
 }
 EXPORT_SYMBOL_GPL(dpu_fg_put);
 
+void _dpu_fg_init(struct dpu_soc *dpu, unsigned int id)
+{
+	struct dpu_framegen *fg;
+	u32 val;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fg_ids); i++)
+		if (fg_ids[i] == id)
+			break;
+
+	if (WARN_ON(i == ARRAY_SIZE(fg_ids)))
+		return;
+
+	fg = dpu->fg_priv[i];
+
+	mutex_lock(&fg->mutex);
+	val = dpu_fg_read(fg, FGSTCTRL);
+	val &= ~FGSYNCMODE_MASK;
+	val |= FGSYNCMODE__OFF;
+	dpu_fg_write(fg, val, FGSTCTRL);
+	mutex_unlock(&fg->mutex);
+}
+
 int dpu_fg_init(struct dpu_soc *dpu, unsigned int id,
 		unsigned long unused, unsigned long base)
 {
 	struct dpu_framegen *fg;
-	u32 val;
 
 	fg = devm_kzalloc(dpu->dev, sizeof(*fg), GFP_KERNEL);
 	if (!fg)
@@ -440,13 +465,7 @@ int dpu_fg_init(struct dpu_soc *dpu, unsigned int id,
 	fg->id = id;
 	mutex_init(&fg->mutex);
 
-	mutex_lock(&fg->mutex);
-	val = dpu_fg_read(fg, FGSTCTRL);
-	val &= ~FGSYNCMODE_MASK;
-	val |= FGSYNCMODE__OFF;
-	dpu_fg_write(fg, val, FGSTCTRL);
-
-	mutex_unlock(&fg->mutex);
+	_dpu_fg_init(dpu, id);
 
 	return 0;
 }
diff --git a/drivers/gpu/imx/dpu/dpu-hscaler.c b/drivers/gpu/imx/dpu/dpu-hscaler.c
index 1ce92d6ee97bbbec195289c7a50697e4fc49b897..d9e34bce46bc10d2c0a1bed0d43e1f906e8517c5 100644
--- a/drivers/gpu/imx/dpu/dpu-hscaler.c
+++ b/drivers/gpu/imx/dpu/dpu-hscaler.c
@@ -338,6 +338,25 @@ void dpu_hs_put(struct dpu_hscaler *hs)
 }
 EXPORT_SYMBOL_GPL(dpu_hs_put);
 
+void _dpu_hs_init(struct dpu_soc *dpu, unsigned int id)
+{
+	struct dpu_hscaler *hs;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hs_ids); i++)
+		if (hs_ids[i] == id)
+			break;
+
+	if (WARN_ON(i == ARRAY_SIZE(hs_ids)))
+		return;
+
+	hs = dpu->hs_priv[i];
+
+	hscaler_shden(hs, true);
+	hscaler_setup2(hs, 0);
+	hscaler_pixengcfg_dynamic_src_sel(hs, HS_SRC_SEL__DISABLE);
+}
+
 int dpu_hs_init(struct dpu_soc *dpu, unsigned int id,
 		unsigned long pec_base, unsigned long base)
 {
@@ -367,8 +386,7 @@ int dpu_hs_init(struct dpu_soc *dpu, unsigned int id,
 
 	mutex_init(&hs->mutex);
 
-	hscaler_shden(hs, true);
-	hscaler_setup2(hs, 0);
+	_dpu_hs_init(dpu, id);
 
 	return 0;
 }
diff --git a/drivers/gpu/imx/dpu/dpu-layerblend.c b/drivers/gpu/imx/dpu/dpu-layerblend.c
index bc78299bb7a4c711b24b7f0e8a15325432b5ffb7..f09b58172f823e0b16f3a917638ad866d905318c 100644
--- a/drivers/gpu/imx/dpu/dpu-layerblend.c
+++ b/drivers/gpu/imx/dpu/dpu-layerblend.c
@@ -346,6 +346,28 @@ void dpu_lb_put(struct dpu_layerblend *lb)
 }
 EXPORT_SYMBOL_GPL(dpu_lb_put);
 
+void _dpu_lb_init(struct dpu_soc *dpu, unsigned int id)
+{
+	struct dpu_layerblend *lb;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lb_ids); i++)
+		if (lb_ids[i] == id)
+			break;
+
+	if (WARN_ON(i == ARRAY_SIZE(lb_ids)))
+		return;
+
+	lb = dpu->lb_priv[i];
+
+	layerblend_pixengcfg_dynamic_prim_sel(lb, LB_PRIM_SEL__DISABLE);
+	layerblend_pixengcfg_dynamic_sec_sel(lb, LB_SEC_SEL__DISABLE);
+	layerblend_pixengcfg_clken(lb, CLKEN__AUTOMATIC);
+	layerblend_shdldsel(lb, BOTH);
+	layerblend_shdtoksel(lb, BOTH);
+	layerblend_shden(lb, true);
+}
+
 int dpu_lb_init(struct dpu_soc *dpu, unsigned int id,
 		unsigned long pec_base, unsigned long base)
 {
@@ -374,11 +396,7 @@ int dpu_lb_init(struct dpu_soc *dpu, unsigned int id,
 	if (ret < 0)
 		return ret;
 
-	layerblend_pixengcfg_dynamic_sec_sel(lb, LB_SEC_SEL__DISABLE);
-	layerblend_pixengcfg_clken(lb, CLKEN__AUTOMATIC);
-	layerblend_shdldsel(lb, BOTH);
-	layerblend_shdtoksel(lb, BOTH);
-	layerblend_shden(lb, true);
+	_dpu_lb_init(dpu, id);
 
 	return 0;
 }
diff --git a/drivers/gpu/imx/dpu/dpu-prv.h b/drivers/gpu/imx/dpu/dpu-prv.h
index 5f22cfbf28cc6ac61c6d5aa77b6c3b980886e3b6..b18e5b628b41d95b34c9a014e65f95724d4db998 100644
--- a/drivers/gpu/imx/dpu/dpu-prv.h
+++ b/drivers/gpu/imx/dpu/dpu-prv.h
@@ -238,6 +238,21 @@ int dpu_format_num_planes(u32 format);
 int dpu_format_plane_width(int width, u32 format, int plane);
 int dpu_format_plane_height(int height, u32 format, int plane);
 
+#define _DECLARE_DPU_UNIT_INIT_FUNC(block)			\
+void _dpu_##block##_init(struct dpu_soc *dpu, unsigned int id)	\
+
+_DECLARE_DPU_UNIT_INIT_FUNC(cf);
+_DECLARE_DPU_UNIT_INIT_FUNC(dec);
+_DECLARE_DPU_UNIT_INIT_FUNC(ed);
+_DECLARE_DPU_UNIT_INIT_FUNC(fd);
+_DECLARE_DPU_UNIT_INIT_FUNC(fe);
+_DECLARE_DPU_UNIT_INIT_FUNC(fg);
+_DECLARE_DPU_UNIT_INIT_FUNC(fl);
+_DECLARE_DPU_UNIT_INIT_FUNC(hs);
+_DECLARE_DPU_UNIT_INIT_FUNC(lb);
+_DECLARE_DPU_UNIT_INIT_FUNC(tcon);
+_DECLARE_DPU_UNIT_INIT_FUNC(vs);
+
 #define DECLARE_DPU_UNIT_INIT_FUNC(block)			\
 int dpu_##block##_init(struct dpu_soc *dpu, unsigned int id,	\
 			 unsigned long pec_base, unsigned long base)
diff --git a/drivers/gpu/imx/dpu/dpu-tcon.c b/drivers/gpu/imx/dpu/dpu-tcon.c
index 8995e75ed76ba7e478cb11fcfb6d8dc8a7b82c50..ff3fda021216ec293d13fe7edf4b5dcf31d86c68 100644
--- a/drivers/gpu/imx/dpu/dpu-tcon.c
+++ b/drivers/gpu/imx/dpu/dpu-tcon.c
@@ -211,6 +211,10 @@ void dpu_tcon_put(struct dpu_tcon *tcon)
 }
 EXPORT_SYMBOL_GPL(dpu_tcon_put);
 
+void _dpu_tcon_init(struct dpu_soc *dpu, unsigned int id)
+{
+}
+
 int dpu_tcon_init(struct dpu_soc *dpu, unsigned int id,
 			unsigned long unused, unsigned long base)
 {
diff --git a/drivers/gpu/imx/dpu/dpu-vscaler.c b/drivers/gpu/imx/dpu/dpu-vscaler.c
index b31ad87a3adc472c2bc19c2be54289137884fd1b..8c8fddfc8cbae532805e5cb74894e7d309d99e6e 100644
--- a/drivers/gpu/imx/dpu/dpu-vscaler.c
+++ b/drivers/gpu/imx/dpu/dpu-vscaler.c
@@ -378,6 +378,28 @@ void dpu_vs_put(struct dpu_vscaler *vs)
 }
 EXPORT_SYMBOL_GPL(dpu_vs_put);
 
+void _dpu_vs_init(struct dpu_soc *dpu, unsigned int id)
+{
+	struct dpu_vscaler *vs;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vs_ids); i++)
+		if (vs_ids[i] == id)
+			break;
+
+	if (WARN_ON(i == ARRAY_SIZE(vs_ids)))
+		return;
+
+	vs = dpu->vs_priv[i];
+
+	vscaler_shden(vs, true);
+	vscaler_setup2(vs, 0);
+	vscaler_setup3(vs, 0);
+	vscaler_setup4(vs, 0);
+	vscaler_setup5(vs, 0);
+	vscaler_pixengcfg_dynamic_src_sel(vs, VS_SRC_SEL__DISABLE);
+}
+
 int dpu_vs_init(struct dpu_soc *dpu, unsigned int id,
 		unsigned long pec_base, unsigned long base)
 {
@@ -407,11 +429,7 @@ int dpu_vs_init(struct dpu_soc *dpu, unsigned int id,
 
 	mutex_init(&vs->mutex);
 
-	vscaler_shden(vs, true);
-	vscaler_setup2(vs, 0);
-	vscaler_setup3(vs, 0);
-	vscaler_setup4(vs, 0);
-	vscaler_setup5(vs, 0);
+	_dpu_vs_init(dpu, id);
 
 	return 0;
 }