From 510bd0020f52e0f8842ded3cdc7c71852440f5ba Mon Sep 17 00:00:00 2001 From: sky zhou Date: Tue, 14 Aug 2018 20:03:02 +0800 Subject: [PATCH] meson_drm: add irq enable flag in crtc. PD#172623: for vpu clock enabled before drm probed, so we need a flag used in drm to emulate irq enable/disable. Change-Id: Iaddee0a885a396cfd6fa102533a1bde08536229e Signed-off-by: sky zhou --- drivers/amlogic/drm/am_meson_drv.c | 16 ++++++++-- drivers/amlogic/drm/am_meson_vpu.c | 64 ++++++++++++++++++++++++++++---------- 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/drivers/amlogic/drm/am_meson_drv.c b/drivers/amlogic/drm/am_meson_drv.c index ade84fa..190cba3 100644 --- a/drivers/amlogic/drm/am_meson_drv.c +++ b/drivers/amlogic/drm/am_meson_drv.c @@ -100,11 +100,22 @@ EXPORT_SYMBOL(am_meson_unregister_crtc_funcs); static int am_meson_enable_vblank(struct drm_device *dev, unsigned int crtc) { - return 0; + struct meson_drm *priv = dev->dev_private; + + if (crtc > MESON_MAX_CRTC) + return -EBADFD; + + return priv->crtc_funcs[crtc]->enable_vblank(priv->crtc); } static void am_meson_disable_vblank(struct drm_device *dev, unsigned int crtc) { + struct meson_drm *priv = dev->dev_private; + + if (crtc > MESON_MAX_CRTC) + return; + + return priv->crtc_funcs[crtc]->disable_vblank(priv->crtc); } static void am_meson_load(struct drm_device *dev) @@ -256,8 +267,7 @@ static int am_meson_drm_bind(struct device *dev) drm->mode_config.max_height = 8192; drm->mode_config.funcs = &meson_mode_config_funcs; /* - * enable drm irq mode. - * - with irq_enabled = true, we can use the vblank feature. + * irq will init in each crtc, just mark the enable flag here. */ drm->irq_enabled = true; diff --git a/drivers/amlogic/drm/am_meson_vpu.c b/drivers/amlogic/drm/am_meson_vpu.c index 685d4a4..69372bf 100644 --- a/drivers/amlogic/drm/am_meson_vpu.c +++ b/drivers/amlogic/drm/am_meson_vpu.c @@ -73,7 +73,9 @@ struct am_meson_crtc { struct drm_pending_vblank_event *event; - unsigned int irq; + unsigned int vblank_irq; + spinlock_t vblank_irq_lock; + bool vblank_enable; struct dentry *crtc_debugfs_dir; }; @@ -299,6 +301,7 @@ void am_osd_do_display( int format = DRM_FORMAT_ARGB8888; dma_addr_t phyaddr; unsigned long flags; + struct am_meson_crtc *amcrtc = to_am_meson_crtc(drv->crtc); //DRM_INFO("%s osd %d.\n", __func__, osd_plane->osd_idx); @@ -348,7 +351,6 @@ void am_osd_do_display( break; }; - spin_lock_irqsave(&drv->drm->event_lock, flags); #ifdef CONFIG_DRM_MESON_USE_ION meson_fb = container_of(fb, struct am_meson_fb, base); @@ -383,9 +385,10 @@ void am_osd_do_display( fb->flags, fb->pixel_format, state->zpos); DRM_INFO("plane index=%d, type=%d\n", plane->index, plane->type); #endif - osd_drm_plane_page_flip(&plane_map); - spin_unlock_irqrestore(&drv->drm->event_lock, flags); + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + osd_drm_plane_page_flip(&plane_map); + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); } int am_osd_check(struct drm_plane *plane, struct drm_plane_state *state) @@ -540,10 +543,10 @@ static int am_meson_crtc_loader_protect(struct drm_crtc *crtc, bool on) DRM_INFO("%s %d\n", __func__, on); if (on) { - enable_irq(amcrtc->irq); + enable_irq(amcrtc->vblank_irq); drm_crtc_vblank_on(crtc); } else { - disable_irq(amcrtc->irq); + disable_irq(amcrtc->vblank_irq); drm_crtc_vblank_off(crtc); } @@ -552,11 +555,24 @@ static int am_meson_crtc_loader_protect(struct drm_crtc *crtc, bool on) static int am_meson_crtc_enable_vblank(struct drm_crtc *crtc) { + unsigned long flags; + struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc); + + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + amcrtc->vblank_enable = true; + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); + return 0; } static void am_meson_crtc_disable_vblank(struct drm_crtc *crtc) { + unsigned long flags; + struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc); + + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + amcrtc->vblank_enable = false; + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); } static const struct meson_crtc_funcs meson_private_crtc_funcs = { @@ -576,6 +592,7 @@ static bool am_meson_crtc_mode_fixup(struct drm_crtc *crtc, void am_meson_crtc_enable(struct drm_crtc *crtc) { + unsigned long flags; char *name; enum vmode_e mode; struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; @@ -588,6 +605,7 @@ void am_meson_crtc_enable(struct drm_crtc *crtc) return; } DRM_INFO("%s: %s\n", __func__, adjusted_mode->name); + name = am_meson_crtc_get_voutmode(adjusted_mode); mode = validate_vmode(name); if (mode == VMODE_MAX) { @@ -597,24 +615,30 @@ void am_meson_crtc_enable(struct drm_crtc *crtc) set_vout_init(mode); update_vout_viu(); - - enable_irq(amcrtc->irq); + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + amcrtc->vblank_enable = true; + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); + enable_irq(amcrtc->vblank_irq); } void am_meson_crtc_disable(struct drm_crtc *crtc) { struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc); + unsigned long flags; DRM_INFO("%s\n", __func__); if (crtc->state->event && !crtc->state->active) { spin_lock_irq(&crtc->dev->event_lock); drm_crtc_send_vblank_event(crtc, crtc->state->event); spin_unlock_irq(&crtc->dev->event_lock); - crtc->state->event = NULL; } - disable_irq(amcrtc->irq); + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + amcrtc->vblank_enable = false; + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); + + disable_irq(amcrtc->vblank_irq); } void am_meson_crtc_commit(struct drm_crtc *crtc) @@ -678,10 +702,15 @@ int am_meson_crtc_create(struct am_meson_crtc *amcrtc) void am_meson_crtc_irq(struct meson_drm *priv) { + unsigned long flags; struct am_meson_crtc *amcrtc = to_am_meson_crtc(priv->crtc); - osd_drm_vsync_isr_handler(); - am_meson_crtc_handle_vsync(amcrtc); + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + if (amcrtc->vblank_enable) { + osd_drm_vsync_isr_handler(); + am_meson_crtc_handle_vsync(amcrtc); + } + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); } static irqreturn_t am_meson_vpu_irq(int irq, void *arg) @@ -776,14 +805,17 @@ static int am_meson_vpu_bind(struct device *dev, dev_err(dev, "cannot find irq for vpu\n"); return irq; } - amcrtc->irq = (unsigned int)irq; + amcrtc->vblank_irq = (unsigned int)irq; - ret = devm_request_irq(dev, amcrtc->irq, am_meson_vpu_irq, + spin_lock_init(&amcrtc->vblank_irq_lock); + amcrtc->vblank_enable = false; + + ret = devm_request_irq(dev, amcrtc->vblank_irq, am_meson_vpu_irq, IRQF_SHARED, dev_name(dev), drm_dev); if (ret) return ret; - /* IRQ is initially disabled; it gets enabled in crtc_enable */ - disable_irq(amcrtc->irq); + + disable_irq(amcrtc->vblank_irq); INIT_DELAYED_WORK(&osd_dwork, mem_free_work); schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000)); -- 2.7.4