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