diff options
Diffstat (limited to 'drivers/gpu/drm/rockchip')
-rw-r--r-- | drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/cdn-dp-core.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 74 |
3 files changed, 50 insertions, 64 deletions
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 7d76ff47028d..3e8bf79bea58 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -71,10 +71,6 @@ struct rockchip_dp_device { struct regmap *grf; struct reset_control *rst; - struct work_struct psr_work; - struct mutex psr_lock; - unsigned int psr_state; - const struct rockchip_dp_chip_data *data; struct analogix_dp_device *adp; @@ -84,28 +80,13 @@ struct rockchip_dp_device { static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled) { struct rockchip_dp_device *dp = to_dp(encoder); + int ret; - if (!analogix_dp_psr_supported(dp->adp)) + if (!analogix_dp_psr_enabled(dp->adp)) return; DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); - mutex_lock(&dp->psr_lock); - if (enabled) - dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE; - else - dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; - - schedule_work(&dp->psr_work); - mutex_unlock(&dp->psr_lock); -} - -static void analogix_dp_psr_work(struct work_struct *work) -{ - struct rockchip_dp_device *dp = - container_of(work, typeof(*dp), psr_work); - int ret; - ret = rockchip_drm_wait_vact_end(dp->encoder.crtc, PSR_WAIT_LINE_FLAG_TIMEOUT_MS); if (ret) { @@ -113,12 +94,10 @@ static void analogix_dp_psr_work(struct work_struct *work) return; } - mutex_lock(&dp->psr_lock); - if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE) + if (enabled) analogix_dp_enable_psr(dp->adp); else analogix_dp_disable_psr(dp->adp); - mutex_unlock(&dp->psr_lock); } static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) @@ -135,8 +114,6 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data) struct rockchip_dp_device *dp = to_dp(plat_data); int ret; - cancel_work_sync(&dp->psr_work); - ret = clk_prepare_enable(dp->pclk); if (ret < 0) { DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret); @@ -355,10 +332,6 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, dp->plat_data.power_off = rockchip_dp_powerdown; dp->plat_data.get_modes = rockchip_dp_get_modes; - mutex_init(&dp->psr_lock); - dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; - INIT_WORK(&dp->psr_work, analogix_dp_psr_work); - ret = rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); if (ret < 0) goto err_cleanup_encoder; diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index ec999d9f15f6..c6fbdcd87c16 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -43,8 +43,6 @@ #define GRF_SOC_CON9 0x6224 #define DP_SEL_VOP_LIT BIT(12) #define GRF_SOC_CON26 0x6268 -#define UPHY_SEL_BIT 3 -#define UPHY_SEL_MASK BIT(19) #define DPTX_HPD_SEL (3 << 12) #define DPTX_HPD_DEL (2 << 12) #define DPTX_HPD_SEL_MASK (3 << 28) @@ -394,11 +392,6 @@ static int cdn_dp_enable_phy(struct cdn_dp_device *dp, struct cdn_dp_port *port) union extcon_property_value property; int ret; - ret = cdn_dp_grf_write(dp, GRF_SOC_CON26, - (port->id << UPHY_SEL_BIT) | UPHY_SEL_MASK); - if (ret) - return ret; - if (!port->phy_enabled) { ret = phy_power_on(port->phy); if (ret) { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 158e79e5062e..53d4afe15278 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -117,6 +117,8 @@ struct vop { spinlock_t reg_lock; /* lock vop irq reg */ spinlock_t irq_lock; + /* protects crtc enable/disable */ + struct mutex vop_lock; unsigned int irq; @@ -517,7 +519,10 @@ static int vop_enable(struct drm_crtc *crtc) goto err_disable_aclk; } - memcpy(vop->regs, vop->regsbak, vop->len); + spin_lock(&vop->reg_lock); + for (i = 0; i < vop->len; i += 4) + writel_relaxed(vop->regsbak[i / 4], vop->regs + i); + /* * We need to make sure that all windows are disabled before we * enable the crtc. Otherwise we might try to scan from a destroyed @@ -527,10 +532,9 @@ static int vop_enable(struct drm_crtc *crtc) struct vop_win *vop_win = &vop->win[i]; const struct vop_win_data *win = vop_win->data; - spin_lock(&vop->reg_lock); VOP_WIN_SET(vop, win, enable, 0); - spin_unlock(&vop->reg_lock); } + spin_unlock(&vop->reg_lock); vop_cfg_done(vop); @@ -569,6 +573,7 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, WARN_ON(vop->event); + mutex_lock(&vop->vop_lock); drm_crtc_vblank_off(crtc); /* @@ -604,6 +609,7 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, clk_disable(vop->aclk); clk_disable(vop->hclk); pm_runtime_put(vop->dev); + mutex_unlock(&vop->vop_lock); if (crtc->state->event && !crtc->state->active) { spin_lock_irq(&crtc->dev->event_lock); @@ -868,10 +874,13 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, uint32_t pin_pol, val; int ret; + mutex_lock(&vop->vop_lock); + WARN_ON(vop->event); ret = vop_enable(crtc); if (ret) { + mutex_unlock(&vop->vop_lock); DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret); return; } @@ -935,6 +944,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, clk_set_rate(vop->dclk, adjusted_mode->clock * 1000); VOP_REG_SET(vop, common, standby, 0); + mutex_unlock(&vop->vop_lock); } static bool vop_fs_irq_is_pending(struct vop *vop) @@ -1137,15 +1147,14 @@ static void vop_handle_vblank(struct vop *vop) { struct drm_device *drm = vop->drm_dev; struct drm_crtc *crtc = &vop->crtc; - unsigned long flags; - spin_lock_irqsave(&drm->event_lock, flags); + spin_lock(&drm->event_lock); if (vop->event) { drm_crtc_send_vblank_event(crtc, vop->event); drm_crtc_vblank_put(crtc); vop->event = NULL; } - spin_unlock_irqrestore(&drm->event_lock, flags); + spin_unlock(&drm->event_lock); if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending)) drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq); @@ -1156,21 +1165,20 @@ static irqreturn_t vop_isr(int irq, void *data) struct vop *vop = data; struct drm_crtc *crtc = &vop->crtc; uint32_t active_irqs; - unsigned long flags; int ret = IRQ_NONE; /* * interrupt register has interrupt status, enable and clear bits, we * must hold irq_lock to avoid a race with enable/disable_vblank(). */ - spin_lock_irqsave(&vop->irq_lock, flags); + spin_lock(&vop->irq_lock); active_irqs = VOP_INTR_GET_TYPE(vop, status, INTR_MASK); /* Clear all active interrupt sources */ if (active_irqs) VOP_INTR_SET_TYPE(vop, clear, active_irqs, 1); - spin_unlock_irqrestore(&vop->irq_lock, flags); + spin_unlock(&vop->irq_lock); /* This is expected for vop iommu irqs, since the irq is shared */ if (!active_irqs) @@ -1393,7 +1401,11 @@ static int vop_initial(struct vop *vop) usleep_range(10, 20); reset_control_deassert(ahb_rst); - memcpy(vop->regsbak, vop->regs, vop->len); + VOP_INTR_SET_TYPE(vop, clear, INTR_MASK, 1); + VOP_INTR_SET_TYPE(vop, enable, INTR_MASK, 0); + + for (i = 0; i < vop->len; i += sizeof(u32)) + vop->regsbak[i / 4] = readl_relaxed(vop->regs + i); VOP_REG_SET(vop, misc, global_regdone_en, 1); VOP_REG_SET(vop, common, dsp_blank, 0); @@ -1473,15 +1485,21 @@ int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout) { struct vop *vop = to_vop(crtc); unsigned long jiffies_left; + int ret = 0; if (!crtc || !vop->is_enabled) return -ENODEV; - if (mstimeout <= 0) - return -EINVAL; + mutex_lock(&vop->vop_lock); + if (mstimeout <= 0) { + ret = -EINVAL; + goto out; + } - if (vop_line_flag_irq_is_enabled(vop)) - return -EBUSY; + if (vop_line_flag_irq_is_enabled(vop)) { + ret = -EBUSY; + goto out; + } reinit_completion(&vop->line_flag_completion); vop_line_flag_irq_enable(vop); @@ -1492,10 +1510,13 @@ int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout) if (jiffies_left == 0) { DRM_DEV_ERROR(vop->dev, "Timeout waiting for IRQ\n"); - return -ETIMEDOUT; + ret = -ETIMEDOUT; + goto out; } - return 0; +out: + mutex_unlock(&vop->vop_lock); + return ret; } EXPORT_SYMBOL(rockchip_drm_wait_vact_end); @@ -1545,18 +1566,11 @@ static int vop_bind(struct device *dev, struct device *master, void *data) spin_lock_init(&vop->reg_lock); spin_lock_init(&vop->irq_lock); - - ret = devm_request_irq(dev, vop->irq, vop_isr, - IRQF_SHARED, dev_name(dev), vop); - if (ret) - return ret; - - /* IRQ is initially disabled; it gets enabled in power_on */ - disable_irq(vop->irq); + mutex_init(&vop->vop_lock); ret = vop_create_crtc(vop); if (ret) - goto err_enable_irq; + return ret; pm_runtime_enable(&pdev->dev); @@ -1567,13 +1581,19 @@ static int vop_bind(struct device *dev, struct device *master, void *data) goto err_disable_pm_runtime; } + ret = devm_request_irq(dev, vop->irq, vop_isr, + IRQF_SHARED, dev_name(dev), vop); + if (ret) + goto err_disable_pm_runtime; + + /* IRQ is initially disabled; it gets enabled in power_on */ + disable_irq(vop->irq); + return 0; err_disable_pm_runtime: pm_runtime_disable(&pdev->dev); vop_destroy_crtc(vop); -err_enable_irq: - enable_irq(vop->irq); /* To balance out the disable_irq above */ return ret; } |