diff options
Diffstat (limited to 'drivers/gpu/drm/imx/ipuv3-crtc.c')
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-crtc.c | 90 |
1 files changed, 46 insertions, 44 deletions
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 6be515a9fb69..5456c15d962c 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -55,11 +55,32 @@ static void ipu_crtc_enable(struct drm_crtc *crtc) struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); + ipu_prg_enable(ipu); ipu_dc_enable(ipu); ipu_dc_enable_channel(ipu_crtc->dc); ipu_di_enable(ipu_crtc->di); } +static void ipu_crtc_disable_planes(struct ipu_crtc *ipu_crtc, + struct drm_crtc_state *old_crtc_state) +{ + bool disable_partial = false; + bool disable_full = false; + struct drm_plane *plane; + + drm_atomic_crtc_state_for_each_plane(plane, old_crtc_state) { + if (plane == &ipu_crtc->plane[0]->base) + disable_full = true; + if (&ipu_crtc->plane[1] && plane == &ipu_crtc->plane[1]->base) + disable_partial = true; + } + + if (disable_partial) + ipu_plane_disable(ipu_crtc->plane[1], true); + if (disable_full) + ipu_plane_disable(ipu_crtc->plane[0], false); +} + static void ipu_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { @@ -73,8 +94,9 @@ static void ipu_crtc_atomic_disable(struct drm_crtc *crtc, * attached IDMACs will be left in undefined state, possibly hanging * the IPU or even system. */ - drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false); + ipu_crtc_disable_planes(ipu_crtc, old_crtc_state); ipu_dc_disable(ipu); + ipu_prg_disable(ipu); spin_lock_irq(&crtc->dev->event_lock); if (crtc->state->event) { @@ -129,18 +151,31 @@ static void imx_drm_crtc_destroy_state(struct drm_crtc *crtc, kfree(to_imx_crtc_state(state)); } -static void imx_drm_crtc_destroy(struct drm_crtc *crtc) +static int ipu_enable_vblank(struct drm_crtc *crtc) { - imx_drm_remove_crtc(to_ipu_crtc(crtc)->imx_crtc); + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + + enable_irq(ipu_crtc->irq); + + return 0; +} + +static void ipu_disable_vblank(struct drm_crtc *crtc) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + + disable_irq_nosync(ipu_crtc->irq); } static const struct drm_crtc_funcs ipu_crtc_funcs = { .set_config = drm_atomic_helper_set_config, - .destroy = imx_drm_crtc_destroy, + .destroy = drm_crtc_cleanup, .page_flip = drm_atomic_helper_page_flip, .reset = imx_drm_crtc_reset, .atomic_duplicate_state = imx_drm_crtc_duplicate_state, .atomic_destroy_state = imx_drm_crtc_destroy_state, + .enable_vblank = ipu_enable_vblank, + .disable_vblank = ipu_disable_vblank, }; static irqreturn_t ipu_irq_handler(int irq, void *dev_id) @@ -261,29 +296,6 @@ static const struct drm_crtc_helper_funcs ipu_helper_funcs = { .enable = ipu_crtc_enable, }; -static int ipu_enable_vblank(struct drm_crtc *crtc) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - - enable_irq(ipu_crtc->irq); - - return 0; -} - -static void ipu_disable_vblank(struct drm_crtc *crtc) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - - disable_irq_nosync(ipu_crtc->irq); -} - -static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = { - .enable_vblank = ipu_enable_vblank, - .disable_vblank = ipu_disable_vblank, - .crtc_funcs = &ipu_crtc_funcs, - .crtc_helper_funcs = &ipu_helper_funcs, -}; - static void ipu_put_resources(struct ipu_crtc *ipu_crtc) { if (!IS_ERR_OR_NULL(ipu_crtc->dc)) @@ -321,6 +333,7 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, struct ipu_client_platformdata *pdata, struct drm_device *drm) { struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); + struct drm_crtc *crtc = &ipu_crtc->base; int dp = -EINVAL; int ret; @@ -340,19 +353,16 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, goto err_put_resources; } - ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc, - &ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs, - pdata->of_node); - if (ret) { - dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret); - goto err_put_resources; - } + crtc->port = pdata->of_node; + drm_crtc_helper_add(crtc, &ipu_helper_funcs); + drm_crtc_init_with_planes(drm, crtc, &ipu_crtc->plane[0]->base, NULL, + &ipu_crtc_funcs, NULL); ret = ipu_plane_get_resources(ipu_crtc->plane[0]); if (ret) { dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n", ret); - goto err_remove_crtc; + goto err_put_resources; } /* If this crtc is using the DP, add an overlay plane */ @@ -390,8 +400,6 @@ err_put_plane1_res: ipu_plane_put_resources(ipu_crtc->plane[1]); err_put_plane0_res: ipu_plane_put_resources(ipu_crtc->plane[0]); -err_remove_crtc: - imx_drm_remove_crtc(ipu_crtc->imx_crtc); err_put_resources: ipu_put_resources(ipu_crtc); @@ -457,16 +465,10 @@ static int ipu_drm_remove(struct platform_device *pdev) return 0; } -static struct platform_driver ipu_drm_driver = { +struct platform_driver ipu_drm_driver = { .driver = { .name = "imx-ipuv3-crtc", }, .probe = ipu_drm_probe, .remove = ipu_drm_remove, }; -module_platform_driver(ipu_drm_driver); - -MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-ipuv3-crtc"); |