[PATCH v3] drm/gem: Fix GEM handle release errors
Currently we are assuming a one to one mapping between dmabuf and GEM handle when releasing GEM handles. But that is not always true, since we would create extra handles for the GEM obj in cases like gem_open() and getfb{,2}(). A similar issue was reported at: https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/ Another problem is that the imported dmabuf might not always have gem_obj->dma_buf set, which would cause leaks in drm_gem_remove_prime_handles(). Let's fix these for now by using handle to find the exact map to remove. Signed-off-by: Jeffy Chen Reviewed-by: Christian König --- Changes in v3: Rewrite commit message a bit. Changes in v2: Fix a typo of rbtree. drivers/gpu/drm/drm_gem.c | 17 + drivers/gpu/drm/drm_internal.h | 4 ++-- drivers/gpu/drm/drm_prime.c| 20 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index eb0c2d041f13..ed39da383570 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev, } EXPORT_SYMBOL(drm_gem_private_object_init); -static void -drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp) -{ - /* -* Note: obj->dma_buf can't disappear as long as we still hold a -* handle reference in obj->handle_count. -*/ - mutex_lock(>prime.lock); - if (obj->dma_buf) { - drm_prime_remove_buf_handle_locked(>prime, - obj->dma_buf); - } - mutex_unlock(>prime.lock); -} - /** * drm_gem_object_handle_free - release resources bound to userspace handles * @obj: GEM object to clean up. @@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) if (obj->funcs->close) obj->funcs->close(obj, file_priv); - drm_gem_remove_prime_handles(obj, file_priv); + drm_prime_remove_buf_handle(_priv->prime, id); drm_vma_node_revoke(>vma_node, file_priv); drm_gem_object_handle_put_unlocked(obj); diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 1fbbc19f1ac0..7bb98e6a446d 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv); void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv); -void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, - struct dma_buf *dma_buf); +void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, +uint32_t handle); /* drm_drv.c */ struct drm_minor *drm_minor_acquire(unsigned int minor_id); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index e3f09f18110c..bd5366b16381 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri return -ENOENT; } -void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, - struct dma_buf *dma_buf) +void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, +uint32_t handle) { struct rb_node *rb; - rb = prime_fpriv->dmabufs.rb_node; + mutex_lock(_fpriv->lock); + + rb = prime_fpriv->handles.rb_node; while (rb) { struct drm_prime_member *member; - member = rb_entry(rb, struct drm_prime_member, dmabuf_rb); - if (member->dma_buf == dma_buf) { + member = rb_entry(rb, struct drm_prime_member, handle_rb); + if (member->handle == handle) { rb_erase(>handle_rb, _fpriv->handles); rb_erase(>dmabuf_rb, _fpriv->dmabufs); - dma_buf_put(dma_buf); + dma_buf_put(member->dma_buf); kfree(member); - return; - } else if (member->dma_buf < dma_buf) { + break; + } else if (member->handle < handle) { rb = rb->rb_right; } else { rb = rb->rb_left; } } + + mutex_unlock(_fpriv->lock); } void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv) -- 2.20.1
[PATCH v2] drm/gem: Fix GEM handle release errors
Currently we are assuming a one to one mapping between dmabuf and handle when releasing GEM handles. But that is not always true, since we would create extra handles for the GEM obj in cases like gem_open() and getfb{,2}(). A similar issue was reported at: https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/ Another problem is that the drm_gem_remove_prime_handles() now only remove handle to the exported dmabuf (gem_obj->dma_buf), so the imported ones would leak: WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 drm_prime_destroy_file_private+0x18/0x24 Let's fix these by using handle to find the exact map to remove. Signed-off-by: Jeffy Chen --- Changes in v2: Fix a typo of rbtree. drivers/gpu/drm/drm_gem.c | 17 + drivers/gpu/drm/drm_internal.h | 4 ++-- drivers/gpu/drm/drm_prime.c| 20 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index eb0c2d041f13..ed39da383570 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev, } EXPORT_SYMBOL(drm_gem_private_object_init); -static void -drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp) -{ - /* -* Note: obj->dma_buf can't disappear as long as we still hold a -* handle reference in obj->handle_count. -*/ - mutex_lock(>prime.lock); - if (obj->dma_buf) { - drm_prime_remove_buf_handle_locked(>prime, - obj->dma_buf); - } - mutex_unlock(>prime.lock); -} - /** * drm_gem_object_handle_free - release resources bound to userspace handles * @obj: GEM object to clean up. @@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) if (obj->funcs->close) obj->funcs->close(obj, file_priv); - drm_gem_remove_prime_handles(obj, file_priv); + drm_prime_remove_buf_handle(_priv->prime, id); drm_vma_node_revoke(>vma_node, file_priv); drm_gem_object_handle_put_unlocked(obj); diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 1fbbc19f1ac0..7bb98e6a446d 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv); void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv); -void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, - struct dma_buf *dma_buf); +void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, +uint32_t handle); /* drm_drv.c */ struct drm_minor *drm_minor_acquire(unsigned int minor_id); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index e3f09f18110c..bd5366b16381 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri return -ENOENT; } -void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, - struct dma_buf *dma_buf) +void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, +uint32_t handle) { struct rb_node *rb; - rb = prime_fpriv->dmabufs.rb_node; + mutex_lock(_fpriv->lock); + + rb = prime_fpriv->handles.rb_node; while (rb) { struct drm_prime_member *member; - member = rb_entry(rb, struct drm_prime_member, dmabuf_rb); - if (member->dma_buf == dma_buf) { + member = rb_entry(rb, struct drm_prime_member, handle_rb); + if (member->handle == handle) { rb_erase(>handle_rb, _fpriv->handles); rb_erase(>dmabuf_rb, _fpriv->dmabufs); - dma_buf_put(dma_buf); + dma_buf_put(member->dma_buf); kfree(member); - return; - } else if (member->dma_buf < dma_buf) { + break; + } else if (member->handle < handle) { rb = rb->rb_right; } else { rb = rb->rb_left; } } + + mutex_unlock(_fpriv->lock); } void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv) -- 2.20.1
[PATCH] drm/gem: Fix GEM handle release errors
Currently we are assuming a one to one mapping between dmabuf and handle when releasing GEM handles. But that is not always true, since we would create extra handles for the GEM obj in cases like gem_open() and getfb{,2}(). A similar issue was reported at: https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/ Another problem is that the drm_gem_remove_prime_handles() now only remove handle to the exported dmabuf (gem_obj->dma_buf), so the imported ones would leak: WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 drm_prime_destroy_file_private+0x18/0x24 Let's fix these by using handle to find the exact map to remove. Signed-off-by: Jeffy Chen --- drivers/gpu/drm/drm_gem.c | 17 + drivers/gpu/drm/drm_internal.h | 4 ++-- drivers/gpu/drm/drm_prime.c| 16 ++-- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index eb0c2d041f13..ed39da383570 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev, } EXPORT_SYMBOL(drm_gem_private_object_init); -static void -drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp) -{ - /* -* Note: obj->dma_buf can't disappear as long as we still hold a -* handle reference in obj->handle_count. -*/ - mutex_lock(>prime.lock); - if (obj->dma_buf) { - drm_prime_remove_buf_handle_locked(>prime, - obj->dma_buf); - } - mutex_unlock(>prime.lock); -} - /** * drm_gem_object_handle_free - release resources bound to userspace handles * @obj: GEM object to clean up. @@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) if (obj->funcs->close) obj->funcs->close(obj, file_priv); - drm_gem_remove_prime_handles(obj, file_priv); + drm_prime_remove_buf_handle(_priv->prime, id); drm_vma_node_revoke(>vma_node, file_priv); drm_gem_object_handle_put_unlocked(obj); diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 1fbbc19f1ac0..7bb98e6a446d 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv); void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv); -void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, - struct dma_buf *dma_buf); +void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, +uint32_t handle); /* drm_drv.c */ struct drm_minor *drm_minor_acquire(unsigned int minor_id); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index e3f09f18110c..c28518ab62d0 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri return -ENOENT; } -void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, - struct dma_buf *dma_buf) +void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, +uint32_t handle) { struct rb_node *rb; + mutex_lock(_fpriv->lock); + rb = prime_fpriv->dmabufs.rb_node; while (rb) { struct drm_prime_member *member; member = rb_entry(rb, struct drm_prime_member, dmabuf_rb); - if (member->dma_buf == dma_buf) { + if (member->handle == handle) { rb_erase(>handle_rb, _fpriv->handles); rb_erase(>dmabuf_rb, _fpriv->dmabufs); - dma_buf_put(dma_buf); + dma_buf_put(member->dma_buf); kfree(member); - return; - } else if (member->dma_buf < dma_buf) { + break; + } else if (member->handle < handle) { rb = rb->rb_right; } else { rb = rb->rb_left; } } + + mutex_unlock(_fpriv->lock); } void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv) -- 2.20.1
[PATCH] drm/bridge/synopsys: dw-hdmi: Fix memleak in __dw_hdmi_remove
The platform_device_register_full() will allocate dma_mask for hdmi->audio, so we should free before platform_device_unregister(). Reported by kmemleak: unreferenced object 0xffc0ef70ff00 (size 128): comm "kworker/4:1", pid 123, jiffies 4294670080 (age 189.604s) hex dump (first 32 bytes): ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 backtrace: [<21946f44>] kmemleak_alloc+0x58/0x8c [<9c43890d>] kmem_cache_alloc_memcg_trace+0x18c/0x25c [<0e17cd06>] platform_device_register_full+0x64/0x108 [<418a0882>] __dw_hdmi_probe+0xb9c/0xcc0 [<e0b720fd>] dw_hdmi_bind+0x30/0x88 [<9af347f6>] dw_hdmi_rockchip_bind+0x260/0x2e8 Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index f9802399cc0d..d9afdc59d4f4 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2567,8 +2567,10 @@ __dw_hdmi_probe(struct platform_device *pdev, static void __dw_hdmi_remove(struct dw_hdmi *hdmi) { - if (hdmi->audio && !IS_ERR(hdmi->audio)) + if (hdmi->audio && !IS_ERR(hdmi->audio)) { + kfree(hdmi->audio->dev.dma_mask); platform_device_unregister(hdmi->audio); + } if (!IS_ERR(hdmi->cec)) platform_device_unregister(hdmi->cec); -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/rockchip: vop: Init vskiplines in scl_vop_cal_scale()
Currently we are calling scl_vop_cal_scale() to get vskiplines for yrgb and cbcr. So the cbcr's vskiplines might be an unexpected value if the second scl_vop_cal_scale() didn't update it. Init vskiplines in scl_vop_cal_scale() to avoid that. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 7715853ef90a..9b03c51903ab 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -259,6 +259,9 @@ static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, { uint16_t val = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT; + if (vskiplines) + *vskiplines = 0; + if (is_horizontal) { if (mode == SCALE_UP) val = GET_SCL_FT_BIC(src, dst); @@ -299,7 +302,7 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win, uint16_t vsu_mode; uint16_t lb_mode; uint32_t val; - int vskiplines = 0; + int vskiplines; if (dst_w > 3840) { DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n"); -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 09/10] drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata
Let plat drivers own the drvdata, so that they could cleanup resources in their unbind(). Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Neil Armstrong <narmstr...@baylibre.com> --- Changes in v6: None Changes in v5: None drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 43 ++--- drivers/gpu/drm/imx/dw_hdmi-imx.c | 22 +-- drivers/gpu/drm/meson/meson_dw_hdmi.c | 20 ++ drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 14 -- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 --- include/drm/bridge/dw_hdmi.h| 17 ++-- 6 files changed, 77 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ff1b3d2b5d06..6fbfafc5832b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2072,7 +2072,7 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) return ret; } -void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) +void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) { mutex_lock(>mutex); @@ -2098,13 +2098,6 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) } mutex_unlock(>mutex); } - -void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense) -{ - struct dw_hdmi *hdmi = dev_get_drvdata(dev); - - __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense); -} EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense); static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) @@ -2140,9 +2133,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) */ if (intr_stat & (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { - __dw_hdmi_setup_rx_sense(hdmi, -phy_stat & HDMI_PHY_HPD, -phy_stat & HDMI_PHY_RX_SENSE); + dw_hdmi_setup_rx_sense(hdmi, phy_stat & HDMI_PHY_HPD, + phy_stat & HDMI_PHY_RX_SENSE); if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) cec_notifier_set_phys_addr(hdmi->cec_notifier, @@ -2512,8 +2504,6 @@ __dw_hdmi_probe(struct platform_device *pdev, if (hdmi->i2c) dw_hdmi_i2c_init(hdmi); - platform_set_drvdata(pdev, hdmi); - return hdmi; err_iahb: @@ -2559,25 +2549,23 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) /* - * Probe/remove API, used from platforms based on the DRM bridge API. */ -int dw_hdmi_probe(struct platform_device *pdev, - const struct dw_hdmi_plat_data *plat_data) +struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, + const struct dw_hdmi_plat_data *plat_data) { struct dw_hdmi *hdmi; hdmi = __dw_hdmi_probe(pdev, plat_data); if (IS_ERR(hdmi)) - return PTR_ERR(hdmi); + return hdmi; drm_bridge_add(>bridge); - return 0; + return hdmi; } EXPORT_SYMBOL_GPL(dw_hdmi_probe); -void dw_hdmi_remove(struct platform_device *pdev) +void dw_hdmi_remove(struct dw_hdmi *hdmi) { - struct dw_hdmi *hdmi = platform_get_drvdata(pdev); - drm_bridge_remove(>bridge); __dw_hdmi_remove(hdmi); @@ -2587,31 +2575,30 @@ EXPORT_SYMBOL_GPL(dw_hdmi_remove); /* - * Bind/unbind API, used from platforms based on the component framework. */ -int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, -const struct dw_hdmi_plat_data *plat_data) +struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, + struct drm_encoder *encoder, + const struct dw_hdmi_plat_data *plat_data) { struct dw_hdmi *hdmi; int ret; hdmi = __dw_hdmi_probe(pdev, plat_data); if (IS_ERR(hdmi)) - return PTR_ERR(hdmi); + return hdmi; ret = drm_bridge_attach(encoder, >bridge, NULL); if (ret) { __dw_hdmi_remove(hdmi); DRM_ERROR("Failed to initialize bridge with drm\n"); - return ret; + return ERR_PTR(ret); } - return 0; + return hdmi; } EXPORT_SYMBOL_GPL(dw_hdmi_bind); -void dw_hdmi_unbind(struct device *dev) +void dw_hdmi_unbind(struct dw_hdmi *hdmi) { - struct dw_hdmi *hdmi = dev_get_drvdata(dev); - __dw_hdmi_remove(hdmi); } EXPORT_SYMBOL_GPL(dw_hdmi_unbind); diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index b62763aa8706
[PATCH v6 10/10] drm/rockchip: dw_hdmi: Fix error handling path
Add missing clk_disable_unprepare() in bind()'s error handling path and unbind(). Also inline clk_prepare_enable() with bind(). Fixes: 12b9f204e804 ("drm: bridge/dw_hdmi: add rockchip rk3288 support") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v6: None Changes in v5: Add disable to unbind(), and inline clk_prepare_enable() with bind(). drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 +--- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 791ab938f998..e936dfe6c03d 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -193,13 +193,6 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) return PTR_ERR(hdmi->grf_clk); } - ret = clk_prepare_enable(hdmi->vpll_clk); - if (ret) { - DRM_DEV_ERROR(hdmi->dev, - "Failed to enable HDMI vpll: %d\n", ret); - return ret; - } - return 0; } @@ -374,6 +367,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, return ret; } + ret = clk_prepare_enable(hdmi->vpll_clk); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, + "Failed to enable HDMI vpll: %d\n", ret); + return ret; + } + drm_encoder_helper_add(encoder, _hdmi_rockchip_encoder_helper_funcs); drm_encoder_init(drm, encoder, _hdmi_rockchip_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); @@ -381,6 +381,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); if (IS_ERR(hdmi->hdmi)) { encoder->funcs->destroy(encoder); + clk_disable_unprepare(hdmi->vpll_clk); return PTR_ERR(hdmi->hdmi); } @@ -396,6 +397,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, dw_hdmi_unbind(hdmi->hdmi); hdmi->encoder.funcs->destroy(>encoder); + clk_disable_unprepare(hdmi->vpll_clk); } static const struct component_ops dw_hdmi_rockchip_ops = { -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 05/10] drm/rockchip: analogix_dp: Add a sanity check for rockchip_drm_psr_register()
The rockchip_drm_psr_register() can fail, so add a sanity check for that. Also reorder the calls in unbind() to match bind(). Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v6: None Changes in v5: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 15 +++ 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 117585df73e1..bd3567ad8b53 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -356,15 +356,22 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; INIT_WORK(>psr_work, analogix_dp_psr_work); - rockchip_drm_psr_register(>encoder, analogix_dp_psr_set); + ret = rockchip_drm_psr_register(>encoder, analogix_dp_psr_set); + if (ret < 0) + goto err_cleanup_encoder; dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data); if (IS_ERR(dp->adp)) { - dp->encoder.funcs->destroy(>encoder); - return PTR_ERR(dp->adp); + ret = PTR_ERR(dp->adp); + goto err_unreg_psr; } return 0; +err_unreg_psr: + rockchip_drm_psr_unregister(>encoder); +err_cleanup_encoder: + dp->encoder.funcs->destroy(>encoder); + return ret; } static void rockchip_dp_unbind(struct device *dev, struct device *master, @@ -372,8 +379,8 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, { struct rockchip_dp_device *dp = dev_get_drvdata(dev); - rockchip_drm_psr_unregister(>encoder); analogix_dp_unbind(dp->adp); + rockchip_drm_psr_unregister(>encoder); dp->encoder.funcs->destroy(>encoder); } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 06/10] drm/rockchip: dw-mipi-dsi: Fix error handling path
Add missing pm_runtime_disable() in bind()'s error handling path. Also cleanup encoder & connector in unbind(). Fixes: 80a9a059d4e4 ("drm/rockchip/dsi: add dw-mipi power domain support") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v6: None Changes in v5: Call the destroy hook in the error handling path like in unbind(). drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index b15755b6129c..e72d4e2b61aa 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -1282,7 +1282,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = dw_mipi_dsi_register(drm, dsi); if (ret) { DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret); - goto err_pllref; + goto err_disable_pllref; } pm_runtime_enable(dev); @@ -1292,23 +1292,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = mipi_dsi_host_register(>dsi_host); if (ret) { DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret); - goto err_cleanup; + goto err_disable_pm_runtime; } if (!dsi->panel) { ret = -EPROBE_DEFER; - goto err_mipi_dsi_host; + goto err_unreg_mipi_dsi_host; } dev_set_drvdata(dev, dsi); return 0; -err_mipi_dsi_host: +err_unreg_mipi_dsi_host: mipi_dsi_host_unregister(>dsi_host); -err_cleanup: - drm_encoder_cleanup(>encoder); - drm_connector_cleanup(>connector); -err_pllref: +err_disable_pm_runtime: + pm_runtime_disable(dev); + dsi->connector.funcs->destroy(>connector); + dsi->encoder.funcs->destroy(>encoder); +err_disable_pllref: clk_disable_unprepare(dsi->pllref_clk); return ret; } @@ -1320,6 +1321,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master, mipi_dsi_host_unregister(>dsi_host); pm_runtime_disable(dev); + + dsi->connector.funcs->destroy(>connector); + dsi->encoder.funcs->destroy(>encoder); + clk_disable_unprepare(dsi->pllref_clk); } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 07/10] drm/rockchip: inno_hdmi: Fix error handling path
Add missing error handling in bind(). Fixes: 412d4ae6b7a5 ("drm/rockchip: hdmi: add Innosilicon HDMI support") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v6: None Changes in v5: Call the destroy hook in the error handling path like in unbind(). Update cleanup order in unbind(). drivers/gpu/drm/rockchip/inno_hdmi.c | 22 +- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index ee584d87111f..9a96ff6b022b 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -851,8 +851,10 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, } irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; + if (irq < 0) { + ret = irq; + goto err_disable_clk; + } inno_hdmi_reset(hdmi); @@ -860,7 +862,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, if (IS_ERR(hdmi->ddc)) { ret = PTR_ERR(hdmi->ddc); hdmi->ddc = NULL; - return ret; + goto err_disable_clk; } /* @@ -874,7 +876,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = inno_hdmi_register(drm, hdmi); if (ret) - return ret; + goto err_put_adapter; dev_set_drvdata(dev, hdmi); @@ -884,7 +886,17 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq, inno_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); + if (ret < 0) + goto err_cleanup_hdmi; + return 0; +err_cleanup_hdmi: + hdmi->connector.funcs->destroy(>connector); + hdmi->encoder.funcs->destroy(>encoder); +err_put_adapter: + i2c_put_adapter(hdmi->ddc); +err_disable_clk: + clk_disable_unprepare(hdmi->pclk); return ret; } @@ -896,8 +908,8 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, hdmi->connector.funcs->destroy(>connector); hdmi->encoder.funcs->destroy(>encoder); - clk_disable_unprepare(hdmi->pclk); i2c_put_adapter(hdmi->ddc); + clk_disable_unprepare(hdmi->pclk); } static const struct component_ops inno_hdmi_ops = { -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 03/10] drm/bridge: analogix: Do not use device's drvdata
The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Andrzej Hajda <a.ha...@samsung.com> Reviewed-by: Sean Paul <seanp...@chromium.org> Acked-by: Jingoo Han <jingooh...@gmail.com> Acked-by: Archit Taneja <arch...@codeaurora.org> --- Changes in v6: None Changes in v5: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 49 - include/drm/bridge/analogix_dp.h | 19 4 files changed, 74 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = >dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(>dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(>dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(>dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,
[PATCH v6 02/10] drm/rockchip: analogix_dp: Remove unnecessary init code
Remove unnecessary init code, since we would do it in the power_on() callback. Also move of parse code to probe(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v6: None Changes in v5: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 27 ++--- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..8cae5ad926cd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -269,7 +269,7 @@ static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { .destroy = rockchip_dp_drm_encoder_destroy, }; -static int rockchip_dp_init(struct rockchip_dp_device *dp) +static int rockchip_dp_of_probe(struct rockchip_dp_device *dp) { struct device *dev = dp->dev; struct device_node *np = dev->of_node; @@ -303,19 +303,6 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp) return PTR_ERR(dp->rst); } - ret = clk_prepare_enable(dp->pclk); - if (ret < 0) { - DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret); - return ret; - } - - ret = rockchip_dp_pre_init(dp); - if (ret < 0) { - DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret); - clk_disable_unprepare(dp->pclk); - return ret; - } - return 0; } @@ -361,10 +348,6 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, if (!dp_data) return -ENODEV; - ret = rockchip_dp_init(dp); - if (ret < 0) - return ret; - dp->data = dp_data; dp->drm_dev = drm_dev; @@ -398,7 +381,6 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, rockchip_drm_psr_unregister(>encoder); analogix_dp_unbind(dev, master, data); - clk_disable_unprepare(dp->pclk); } static const struct component_ops rockchip_dp_component_ops = { @@ -414,7 +396,7 @@ static int rockchip_dp_probe(struct platform_device *pdev) int ret; ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, , NULL); - if (ret) + if (ret < 0) return ret; dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); @@ -422,9 +404,12 @@ static int rockchip_dp_probe(struct platform_device *pdev) return -ENOMEM; dp->dev = dev; - dp->plat_data.panel = panel; + ret = rockchip_dp_of_probe(dp); + if (ret < 0) + return ret; + /* * We just use the drvdata until driver run into component * add function, and then we would set drvdata to null, so -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 08/10] drm/bridge/synopsys: dw-hdmi: Add missing bridge detach
We inited connector in attach(), so need a detach() to cleanup. Also fix wrong use of dw_hdmi_remove() in bind(). Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v6: None Changes in v5: None drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index bf14214fa464..ff1b3d2b5d06 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1966,6 +1966,13 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) return 0; } +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) +{ + struct dw_hdmi *hdmi = bridge->driver_private; + + drm_connector_cleanup(>connector); +} + static enum drm_mode_status dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_mode *mode) @@ -2022,6 +2029,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { .attach = dw_hdmi_bridge_attach, + .detach = dw_hdmi_bridge_detach, .enable = dw_hdmi_bridge_enable, .disable = dw_hdmi_bridge_disable, .mode_set = dw_hdmi_bridge_mode_set, @@ -2591,7 +2599,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, ret = drm_bridge_attach(encoder, >bridge, NULL); if (ret) { - dw_hdmi_remove(pdev); + __dw_hdmi_remove(hdmi); DRM_ERROR("Failed to initialize bridge with drm\n"); return ret; } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 04/10] drm/bridge: analogix_dp: Fix connector and encoder cleanup
Since we are initing connector in the core driver and encoder in the plat driver, let's clean them up in the right places. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Andrzej Hajda <a.ha...@samsung.com> --- Changes in v6: Don't change order of rockchip_drm_psr_register(). Changes in v5: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 -- drivers/gpu/drm/exynos/exynos_dp.c | 7 +-- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 12 +--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 74d274b6d31d..3f910ab36ff6 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1409,7 +1409,6 @@ analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_create_bridge(drm_dev, dp); if (ret) { DRM_ERROR("failed to create bridge (%d)\n", ret); - drm_encoder_cleanup(dp->encoder); goto err_disable_pm_runtime; } @@ -1432,7 +1431,6 @@ void analogix_dp_unbind(struct analogix_dp_device *dp) { analogix_dp_bridge_disable(dp->bridge); dp->connector.funcs->destroy(>connector); - dp->encoder->funcs->destroy(dp->encoder); if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c index f7e5b2c405ed..33319a858f3a 100644 --- a/drivers/gpu/drm/exynos/exynos_dp.c +++ b/drivers/gpu/drm/exynos/exynos_dp.c @@ -185,8 +185,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) dp->plat_data.encoder = encoder; dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data); - if (IS_ERR(dp->adp)) + if (IS_ERR(dp->adp)) { + dp->encoder.funcs->destroy(>encoder); return PTR_ERR(dp->adp); + } return 0; } @@ -196,7 +198,8 @@ static void exynos_dp_unbind(struct device *dev, struct device *master, { struct exynos_dp_device *dp = dev_get_drvdata(dev); - return analogix_dp_unbind(dp->adp); + analogix_dp_unbind(dp->adp); + dp->encoder.funcs->destroy(>encoder); } static const struct component_ops exynos_dp_ops = { diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index fa0365de31d2..117585df73e1 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -261,13 +261,8 @@ static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { .atomic_check = rockchip_dp_drm_encoder_atomic_check, }; -static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); -} - static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { - .destroy = rockchip_dp_drm_encoder_destroy, + .destroy = drm_encoder_cleanup, }; static int rockchip_dp_of_probe(struct rockchip_dp_device *dp) @@ -364,8 +359,10 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, rockchip_drm_psr_register(>encoder, analogix_dp_psr_set); dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data); - if (IS_ERR(dp->adp)) + if (IS_ERR(dp->adp)) { + dp->encoder.funcs->destroy(>encoder); return PTR_ERR(dp->adp); + } return 0; } @@ -377,6 +374,7 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, rockchip_drm_psr_unregister(>encoder); analogix_dp_unbind(dp->adp); + dp->encoder.funcs->destroy(>encoder); } static const struct component_ops rockchip_dp_component_ops = { -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 00/10] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Changes in v6: Don't change order of rockchip_drm_psr_register(). Changes in v5: Call the destroy hook in the error handling path like in unbind(). Call the destroy hook in the error handling path like in unbind(). Update cleanup order in unbind(). Add disable to unbind(), and inline clk_prepare_enable() with bind(). Jeffy Chen (10): arm64: dts: rockchip: Enable edp disaplay on kevin drm/rockchip: analogix_dp: Remove unnecessary init code drm/bridge: analogix: Do not use device's drvdata drm/bridge: analogix_dp: Fix connector and encoder cleanup drm/rockchip: analogix_dp: Add a sanity check for rockchip_drm_psr_register() drm/rockchip: dw-mipi-dsi: Fix error handling path drm/rockchip: inno_hdmi: Fix error handling path drm/bridge/synopsys: dw-hdmi: Add missing bridge detach drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata drm/rockchip: dw_hdmi: Fix error handling path arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 52 +--- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 53 ++-- drivers/gpu/drm/exynos/exynos_dp.c | 29 --- drivers/gpu/drm/imx/dw_hdmi-imx.c | 22 +++-- drivers/gpu/drm/meson/meson_dw_hdmi.c | 20 +++-- drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 14 +++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 95 +++--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 +++-- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 39 + drivers/gpu/drm/rockchip/inno_hdmi.c | 22 +++-- include/drm/bridge/analogix_dp.h | 19 +++-- include/drm/bridge/dw_hdmi.h | 17 ++-- 14 files changed, 265 insertions(+), 183 deletions(-) -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 8/9] drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata
Let plat drivers own the drvdata, so that they could cleanup resources in their unbind(). Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 43 ++--- drivers/gpu/drm/imx/dw_hdmi-imx.c | 22 +-- drivers/gpu/drm/meson/meson_dw_hdmi.c | 20 ++ drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 14 -- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 --- include/drm/bridge/dw_hdmi.h| 17 ++-- 6 files changed, 77 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ff1b3d2b5d06..6fbfafc5832b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2072,7 +2072,7 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) return ret; } -void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) +void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) { mutex_lock(>mutex); @@ -2098,13 +2098,6 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) } mutex_unlock(>mutex); } - -void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense) -{ - struct dw_hdmi *hdmi = dev_get_drvdata(dev); - - __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense); -} EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense); static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) @@ -2140,9 +2133,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) */ if (intr_stat & (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { - __dw_hdmi_setup_rx_sense(hdmi, -phy_stat & HDMI_PHY_HPD, -phy_stat & HDMI_PHY_RX_SENSE); + dw_hdmi_setup_rx_sense(hdmi, phy_stat & HDMI_PHY_HPD, + phy_stat & HDMI_PHY_RX_SENSE); if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) cec_notifier_set_phys_addr(hdmi->cec_notifier, @@ -2512,8 +2504,6 @@ __dw_hdmi_probe(struct platform_device *pdev, if (hdmi->i2c) dw_hdmi_i2c_init(hdmi); - platform_set_drvdata(pdev, hdmi); - return hdmi; err_iahb: @@ -2559,25 +2549,23 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) /* - * Probe/remove API, used from platforms based on the DRM bridge API. */ -int dw_hdmi_probe(struct platform_device *pdev, - const struct dw_hdmi_plat_data *plat_data) +struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, + const struct dw_hdmi_plat_data *plat_data) { struct dw_hdmi *hdmi; hdmi = __dw_hdmi_probe(pdev, plat_data); if (IS_ERR(hdmi)) - return PTR_ERR(hdmi); + return hdmi; drm_bridge_add(>bridge); - return 0; + return hdmi; } EXPORT_SYMBOL_GPL(dw_hdmi_probe); -void dw_hdmi_remove(struct platform_device *pdev) +void dw_hdmi_remove(struct dw_hdmi *hdmi) { - struct dw_hdmi *hdmi = platform_get_drvdata(pdev); - drm_bridge_remove(>bridge); __dw_hdmi_remove(hdmi); @@ -2587,31 +2575,30 @@ EXPORT_SYMBOL_GPL(dw_hdmi_remove); /* - * Bind/unbind API, used from platforms based on the component framework. */ -int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, -const struct dw_hdmi_plat_data *plat_data) +struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, + struct drm_encoder *encoder, + const struct dw_hdmi_plat_data *plat_data) { struct dw_hdmi *hdmi; int ret; hdmi = __dw_hdmi_probe(pdev, plat_data); if (IS_ERR(hdmi)) - return PTR_ERR(hdmi); + return hdmi; ret = drm_bridge_attach(encoder, >bridge, NULL); if (ret) { __dw_hdmi_remove(hdmi); DRM_ERROR("Failed to initialize bridge with drm\n"); - return ret; + return ERR_PTR(ret); } - return 0; + return hdmi; } EXPORT_SYMBOL_GPL(dw_hdmi_bind); -void dw_hdmi_unbind(struct device *dev) +void dw_hdmi_unbind(struct dw_hdmi *hdmi) { - struct dw_hdmi *hdmi = dev_get_drvdata(dev); - __dw_hdmi_remove(hdmi); } EXPORT_SYMBOL_GPL(dw_hdmi_unbind); diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index b62763aa8706..b01d03e02ce0 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/driver
[PATCH v5 9/9] drm/rockchip: dw_hdmi: Fix error handling path
Add missing clk_disable_unprepare() in bind()'s error handling path and unbind(). Also inline clk_prepare_enable() with bind(). Fixes: 12b9f204e804 ("drm: bridge/dw_hdmi: add rockchip rk3288 support") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: Add disable to unbind(), and inline clk_prepare_enable() with bind(). drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 +--- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 791ab938f998..e936dfe6c03d 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -193,13 +193,6 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) return PTR_ERR(hdmi->grf_clk); } - ret = clk_prepare_enable(hdmi->vpll_clk); - if (ret) { - DRM_DEV_ERROR(hdmi->dev, - "Failed to enable HDMI vpll: %d\n", ret); - return ret; - } - return 0; } @@ -374,6 +367,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, return ret; } + ret = clk_prepare_enable(hdmi->vpll_clk); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, + "Failed to enable HDMI vpll: %d\n", ret); + return ret; + } + drm_encoder_helper_add(encoder, _hdmi_rockchip_encoder_helper_funcs); drm_encoder_init(drm, encoder, _hdmi_rockchip_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); @@ -381,6 +381,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); if (IS_ERR(hdmi->hdmi)) { encoder->funcs->destroy(encoder); + clk_disable_unprepare(hdmi->vpll_clk); return PTR_ERR(hdmi->hdmi); } @@ -396,6 +397,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, dw_hdmi_unbind(hdmi->hdmi); hdmi->encoder.funcs->destroy(>encoder); + clk_disable_unprepare(hdmi->vpll_clk); } static const struct component_ops dw_hdmi_rockchip_ops = { -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 6/9] drm/rockchip: inno_hdmi: Fix error handling path
Add missing error handling in bind(). Fixes: 412d4ae6b7a5 ("drm/rockchip: hdmi: add Innosilicon HDMI support") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: Call the destroy hook in the error handling path like in unbind(). Update cleanup order in unbind(). drivers/gpu/drm/rockchip/inno_hdmi.c | 22 +- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index ee584d87111f..9a96ff6b022b 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -851,8 +851,10 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, } irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; + if (irq < 0) { + ret = irq; + goto err_disable_clk; + } inno_hdmi_reset(hdmi); @@ -860,7 +862,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, if (IS_ERR(hdmi->ddc)) { ret = PTR_ERR(hdmi->ddc); hdmi->ddc = NULL; - return ret; + goto err_disable_clk; } /* @@ -874,7 +876,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = inno_hdmi_register(drm, hdmi); if (ret) - return ret; + goto err_put_adapter; dev_set_drvdata(dev, hdmi); @@ -884,7 +886,17 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq, inno_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); + if (ret < 0) + goto err_cleanup_hdmi; + return 0; +err_cleanup_hdmi: + hdmi->connector.funcs->destroy(>connector); + hdmi->encoder.funcs->destroy(>encoder); +err_put_adapter: + i2c_put_adapter(hdmi->ddc); +err_disable_clk: + clk_disable_unprepare(hdmi->pclk); return ret; } @@ -896,8 +908,8 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, hdmi->connector.funcs->destroy(>connector); hdmi->encoder.funcs->destroy(>encoder); - clk_disable_unprepare(hdmi->pclk); i2c_put_adapter(hdmi->ddc); + clk_disable_unprepare(hdmi->pclk); } static const struct component_ops inno_hdmi_ops = { -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 7/9] drm/bridge/synopsys: dw-hdmi: Add missing bridge detach
We inited connector in attach(), so need a detach() to cleanup. Also fix wrong use of dw_hdmi_remove() in bind(). Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index bf14214fa464..ff1b3d2b5d06 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1966,6 +1966,13 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) return 0; } +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) +{ + struct dw_hdmi *hdmi = bridge->driver_private; + + drm_connector_cleanup(>connector); +} + static enum drm_mode_status dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_mode *mode) @@ -2022,6 +2029,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { .attach = dw_hdmi_bridge_attach, + .detach = dw_hdmi_bridge_detach, .enable = dw_hdmi_bridge_enable, .disable = dw_hdmi_bridge_disable, .mode_set = dw_hdmi_bridge_mode_set, @@ -2591,7 +2599,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, ret = drm_bridge_attach(encoder, >bridge, NULL); if (ret) { - dw_hdmi_remove(pdev); + __dw_hdmi_remove(hdmi); DRM_ERROR("Failed to initialize bridge with drm\n"); return ret; } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 2/9] drm/rockchip: analogix_dp: Remove unnecessary init code
Remove unnecessary init code, since we would do it in the power_on() callback. Also move of parse code to probe(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 27 ++--- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..8cae5ad926cd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -269,7 +269,7 @@ static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { .destroy = rockchip_dp_drm_encoder_destroy, }; -static int rockchip_dp_init(struct rockchip_dp_device *dp) +static int rockchip_dp_of_probe(struct rockchip_dp_device *dp) { struct device *dev = dp->dev; struct device_node *np = dev->of_node; @@ -303,19 +303,6 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp) return PTR_ERR(dp->rst); } - ret = clk_prepare_enable(dp->pclk); - if (ret < 0) { - DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret); - return ret; - } - - ret = rockchip_dp_pre_init(dp); - if (ret < 0) { - DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret); - clk_disable_unprepare(dp->pclk); - return ret; - } - return 0; } @@ -361,10 +348,6 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, if (!dp_data) return -ENODEV; - ret = rockchip_dp_init(dp); - if (ret < 0) - return ret; - dp->data = dp_data; dp->drm_dev = drm_dev; @@ -398,7 +381,6 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, rockchip_drm_psr_unregister(>encoder); analogix_dp_unbind(dev, master, data); - clk_disable_unprepare(dp->pclk); } static const struct component_ops rockchip_dp_component_ops = { @@ -414,7 +396,7 @@ static int rockchip_dp_probe(struct platform_device *pdev) int ret; ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, , NULL); - if (ret) + if (ret < 0) return ret; dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); @@ -422,9 +404,12 @@ static int rockchip_dp_probe(struct platform_device *pdev) return -ENOMEM; dp->dev = dev; - dp->plat_data.panel = panel; + ret = rockchip_dp_of_probe(dp); + if (ret < 0) + return ret; + /* * We just use the drvdata until driver run into component * add function, and then we would set drvdata to null, so -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 0/9] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Changes in v5: Call the destroy hook in the error handling path like in unbind(). Call the destroy hook in the error handling path like in unbind(). Update cleanup order in unbind(). Add disable to unbind(), and inline clk_prepare_enable() with bind(). Jeffy Chen (9): arm64: dts: rockchip: Enable edp disaplay on kevin drm/rockchip: analogix_dp: Remove unnecessary init code drm/bridge: analogix: Do not use device's drvdata drm/bridge: analogix_dp: Fix connector & encoder cleanup drm/rockchip: dw-mipi-dsi: Fix error handling path drm/rockchip: inno_hdmi: Fix error handling path drm/bridge/synopsys: dw-hdmi: Add missing bridge detach drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata drm/rockchip: dw_hdmi: Fix error handling path arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 52 + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 53 ++--- drivers/gpu/drm/exynos/exynos_dp.c | 29 +--- drivers/gpu/drm/imx/dw_hdmi-imx.c | 22 +++--- drivers/gpu/drm/meson/meson_dw_hdmi.c | 20 +++-- drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 14 +++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 87 ++ drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 -- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 39 +- drivers/gpu/drm/rockchip/inno_hdmi.c | 22 -- include/drm/bridge/analogix_dp.h | 19 +++-- include/drm/bridge/dw_hdmi.h | 17 +++-- 14 files changed, 257 insertions(+), 183 deletions(-) -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 5/9] drm/rockchip: dw-mipi-dsi: Fix error handling path
Add missing pm_runtime_disable() in bind()'s error handling path. Also cleanup encoder & connector in unbind(). Fixes: 80a9a059d4e4 ("drm/rockchip/dsi: add dw-mipi power domain support") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: Call the destroy hook in the error handling path like in unbind(). drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index b15755b6129c..e72d4e2b61aa 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -1282,7 +1282,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = dw_mipi_dsi_register(drm, dsi); if (ret) { DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret); - goto err_pllref; + goto err_disable_pllref; } pm_runtime_enable(dev); @@ -1292,23 +1292,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = mipi_dsi_host_register(>dsi_host); if (ret) { DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret); - goto err_cleanup; + goto err_disable_pm_runtime; } if (!dsi->panel) { ret = -EPROBE_DEFER; - goto err_mipi_dsi_host; + goto err_unreg_mipi_dsi_host; } dev_set_drvdata(dev, dsi); return 0; -err_mipi_dsi_host: +err_unreg_mipi_dsi_host: mipi_dsi_host_unregister(>dsi_host); -err_cleanup: - drm_encoder_cleanup(>encoder); - drm_connector_cleanup(>connector); -err_pllref: +err_disable_pm_runtime: + pm_runtime_disable(dev); + dsi->connector.funcs->destroy(>connector); + dsi->encoder.funcs->destroy(>encoder); +err_disable_pllref: clk_disable_unprepare(dsi->pllref_clk); return ret; } @@ -1320,6 +1321,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master, mipi_dsi_host_unregister(>dsi_host); pm_runtime_disable(dev); + + dsi->connector.funcs->destroy(>connector); + dsi->encoder.funcs->destroy(>encoder); + clk_disable_unprepare(dsi->pllref_clk); } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 4/9] drm/bridge: analogix_dp: Fix connector & encoder cleanup
Since we are initing connector in the core driver and encoder in the plat driver, let's clean them up in the right places. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 -- drivers/gpu/drm/exynos/exynos_dp.c | 7 +-- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 15 ++- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 74d274b6d31d..3f910ab36ff6 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1409,7 +1409,6 @@ analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_create_bridge(drm_dev, dp); if (ret) { DRM_ERROR("failed to create bridge (%d)\n", ret); - drm_encoder_cleanup(dp->encoder); goto err_disable_pm_runtime; } @@ -1432,7 +1431,6 @@ void analogix_dp_unbind(struct analogix_dp_device *dp) { analogix_dp_bridge_disable(dp->bridge); dp->connector.funcs->destroy(>connector); - dp->encoder->funcs->destroy(dp->encoder); if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c index f7e5b2c405ed..33319a858f3a 100644 --- a/drivers/gpu/drm/exynos/exynos_dp.c +++ b/drivers/gpu/drm/exynos/exynos_dp.c @@ -185,8 +185,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) dp->plat_data.encoder = encoder; dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data); - if (IS_ERR(dp->adp)) + if (IS_ERR(dp->adp)) { + dp->encoder.funcs->destroy(>encoder); return PTR_ERR(dp->adp); + } return 0; } @@ -196,7 +198,8 @@ static void exynos_dp_unbind(struct device *dev, struct device *master, { struct exynos_dp_device *dp = dev_get_drvdata(dev); - return analogix_dp_unbind(dp->adp); + analogix_dp_unbind(dp->adp); + dp->encoder.funcs->destroy(>encoder); } static const struct component_ops exynos_dp_ops = { diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index fa0365de31d2..c0fb3f3748f4 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -261,13 +261,8 @@ static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { .atomic_check = rockchip_dp_drm_encoder_atomic_check, }; -static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); -} - static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { - .destroy = rockchip_dp_drm_encoder_destroy, + .destroy = drm_encoder_cleanup, }; static int rockchip_dp_of_probe(struct rockchip_dp_device *dp) @@ -361,12 +356,13 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; INIT_WORK(>psr_work, analogix_dp_psr_work); - rockchip_drm_psr_register(>encoder, analogix_dp_psr_set); - dp->adp = analogix_dp_bind(dev, dp->drm_dev, >plat_data); - if (IS_ERR(dp->adp)) + if (IS_ERR(dp->adp)) { + dp->encoder.funcs->destroy(>encoder); return PTR_ERR(dp->adp); + } + rockchip_drm_psr_register(>encoder, analogix_dp_psr_set); return 0; } @@ -377,6 +373,7 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, rockchip_drm_psr_unregister(>encoder); analogix_dp_unbind(dp->adp); + dp->encoder.funcs->destroy(>encoder); } static const struct component_ops rockchip_dp_component_ops = { -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 3/9] drm/bridge: analogix: Do not use device's drvdata
The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Andrzej Hajda <a.ha...@samsung.com> Reviewed-by: Sean Paul <seanp...@chromium.org> Acked-by: Jingoo Han <jingooh...@gmail.com> Acked-by: Archit Taneja <arch...@codeaurora.org> --- Changes in v5: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 49 - include/drm/bridge/analogix_dp.h | 19 4 files changed, 74 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = >dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(>dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(>dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(>dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device
[RFC PATCH v4 8/8] drm/rockchip: Add device links for master and components
Since we are trying to access components' resources in the master's suspend/resume PM callbacks(e.g. panel), add device links to correct the suspend/resume and shutdown ordering. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v4: None Changes in v3: None Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 +--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 76d63de5921d..af18967f699b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -337,6 +337,8 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) if (!d) break; + + device_link_add(dev, d, DL_FLAG_STATELESS); component_match_add(dev, , compare_dev, d); } while (true); } @@ -406,6 +408,7 @@ static int rockchip_drm_platform_of_probe(struct device *dev) static int rockchip_drm_platform_probe(struct platform_device *pdev) { struct device *dev = >dev; + struct device_link *link; struct component_match *match = NULL; int ret; @@ -414,16 +417,31 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) return ret; match = rockchip_drm_match_add(dev); - if (IS_ERR(match)) - return PTR_ERR(match); + if (IS_ERR(match)) { + ret = PTR_ERR(match); + goto err_cleanup_dev_links; + } - return component_master_add_with_match(dev, _drm_ops, match); + ret = component_master_add_with_match(dev, _drm_ops, match); + if (ret < 0) + goto err_cleanup_dev_links; + + return 0; +err_cleanup_dev_links: + list_for_each_entry(link, >links.consumers, s_node) + device_link_del(link); + return ret; } static int rockchip_drm_platform_remove(struct platform_device *pdev) { + struct device_link *link; + component_master_del(>dev, _drm_ops); + list_for_each_entry(link, >dev.links.consumers, s_node) + device_link_del(link); + return 0; } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC PATCH v4 4/8] drm/rockchip: dw_hdmi: Fix error handling path
Add missing clk_disable_unprepare() in bind()'s error handling path. Fixes: 12b9f204e804 ("drm: bridge/dw_hdmi: add rockchip rk3288 support") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 1eb02a82fd91..582283da7861 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -383,8 +383,10 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), * which would have called the encoder cleanup. Do it manually. */ - if (ret) + if (ret) { drm_encoder_cleanup(encoder); + clk_disable_unprepare(hdmi->vpll_clk); + } return ret; } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC PATCH v4 6/8] drm/bridge/analogix: Do not use device's drvdata
From: Tomasz Figa <tf...@chromium.org> The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Andrzej Hajda <a.ha...@samsung.com> --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 47 +++- include/drm/bridge/analogix_dp.h | 19 4 files changed, 73 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = >dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(>dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(>dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(>dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
[RFC PATCH v4 5/8] drm/rockchip: inno_hdmi: Fix error handling path
Add missing error handling in bind(). Fixes: 412d4ae6b7a5 ("drm/rockchip: hdmi: add Innosilicon HDMI support") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/inno_hdmi.c | 20 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index ee584d87111f..9c258b05dfa5 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -851,8 +851,10 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, } irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; + if (irq < 0) { + ret = irq; + goto err_disable_clk; + } inno_hdmi_reset(hdmi); @@ -860,7 +862,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, if (IS_ERR(hdmi->ddc)) { ret = PTR_ERR(hdmi->ddc); hdmi->ddc = NULL; - return ret; + goto err_disable_clk; } /* @@ -874,7 +876,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = inno_hdmi_register(drm, hdmi); if (ret) - return ret; + goto err_put_adapter; dev_set_drvdata(dev, hdmi); @@ -884,7 +886,17 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq, inno_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); + if (ret < 0) + goto err_cleanup_hdmi; + return 0; +err_cleanup_hdmi: + drm_connector_cleanup(>connector); + drm_encoder_cleanup(>encoder); +err_put_adapter: + i2c_put_adapter(hdmi->ddc); +err_disable_clk: + clk_disable_unprepare(hdmi->pclk); return ret; } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC PATCH v4 0/8] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Changes in v4: Fix compile warning. Changes in v3: Assign orphan pwms to dummy pwmchip instead of adding device link in the customer driver. Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. Jeffy Chen (7): arm64: dts: rockchip: Enable edp disaplay on kevin drm/rockchip: analogix_dp: Fix error handling path drm/rockchip: dw-mipi-dsi: Fix error handling path drm/rockchip: dw_hdmi: Fix error handling path drm/rockchip: inno_hdmi: Fix error handling path pwm: Add dummy pwmchip for orphan pwms drm/rockchip: Add device links for master and components Tomasz Figa (1): drm/bridge/analogix: Do not use device's drvdata arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 + drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 ++--- drivers/gpu/drm/exynos/exynos_dp.c | 26 --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 +-- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 17 +++-- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 4 +- drivers/gpu/drm/rockchip/inno_hdmi.c | 20 -- drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 ++- drivers/pwm/core.c | 81 -- include/drm/bridge/analogix_dp.h | 19 ++--- 11 files changed, 254 insertions(+), 89 deletions(-) -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC PATCH v4 2/8] drm/rockchip: analogix_dp: Fix error handling path
Add missing error handling in rockchip_dp_bind(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..4b689c0f3fc1 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -371,7 +371,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, ret = rockchip_dp_drm_create_encoder(dp); if (ret) { DRM_ERROR("failed to create drm encoder\n"); - return ret; + goto err_disable_pclk; } dp->plat_data.encoder = >encoder; @@ -387,7 +387,17 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, rockchip_drm_psr_register(>encoder, analogix_dp_psr_set); - return analogix_dp_bind(dev, dp->drm_dev, >plat_data); + ret = analogix_dp_bind(dev, dp->drm_dev, >plat_data); + if (ret < 0) + goto err_unreg_psr; + return 0; + +err_unreg_psr: + rockchip_drm_psr_unregister(>encoder); + rockchip_dp_drm_encoder_destroy(>encoder); +err_disable_pclk: + clk_disable_unprepare(dp->pclk); + return ret; } static void rockchip_dp_unbind(struct device *dev, struct device *master, -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC PATCH v4 3/8] drm/rockchip: dw-mipi-dsi: Fix error handling path
Add missing pm_runtime_disable() in bind()'s error handling path. Also cleanup encoder & connector in unbind(). Fixes: 80a9a059d4e4 ("drm/rockchip/dsi: add dw-mipi power domain support") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index b15755b6129c..a17ff0f6f489 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -1282,7 +1282,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = dw_mipi_dsi_register(drm, dsi); if (ret) { DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret); - goto err_pllref; + goto err_disable_pllref; } pm_runtime_enable(dev); @@ -1292,23 +1292,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = mipi_dsi_host_register(>dsi_host); if (ret) { DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret); - goto err_cleanup; + goto err_disable_pm_runtime; } if (!dsi->panel) { ret = -EPROBE_DEFER; - goto err_mipi_dsi_host; + goto err_unreg_mipi_dsi_host; } dev_set_drvdata(dev, dsi); return 0; -err_mipi_dsi_host: +err_unreg_mipi_dsi_host: mipi_dsi_host_unregister(>dsi_host); -err_cleanup: +err_disable_pm_runtime: + pm_runtime_disable(dev); drm_encoder_cleanup(>encoder); drm_connector_cleanup(>connector); -err_pllref: +err_disable_pllref: clk_disable_unprepare(dsi->pllref_clk); return ret; } @@ -1320,6 +1321,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master, mipi_dsi_host_unregister(>dsi_host); pm_runtime_disable(dev); + + dsi->connector.funcs->destroy(>connector); + dsi->encoder.funcs->destroy(>encoder); + clk_disable_unprepare(dsi->pllref_clk); } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC PATCH v3 2/5] drm/rockchip: Fix error handling path in rockchip_dp_bind()
Add missing error handling in rockchip_dp_bind(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..cb8941e8bcdd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -371,7 +371,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, ret = rockchip_dp_drm_create_encoder(dp); if (ret) { DRM_ERROR("failed to create drm encoder\n"); - return ret; + goto err_deinit_dp; } dp->plat_data.encoder = >encoder; @@ -387,7 +387,17 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, rockchip_drm_psr_register(>encoder, analogix_dp_psr_set); - return analogix_dp_bind(dev, dp->drm_dev, >plat_data); + ret = analogix_dp_bind(dev, dp->drm_dev, >plat_data); + if (ret < 0) + goto err_unreg_psr; + return 0; + +err_unreg_psr: + rockchip_drm_psr_unregister(>encoder); + rockchip_dp_drm_encoder_destroy(>encoder); +err_deinit_dp: + clk_disable_unprepare(dp->pclk); + return ret; } static void rockchip_dp_unbind(struct device *dev, struct device *master, -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC PATCH v3 5/5] drm/rockchip: Add device links for master and components
Since we are trying to access components' resources in the master's suspend/resume PM callbacks(e.g. panel), add device links to correct the suspend/resume and shutdown ordering. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: None Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 +--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 76d63de5921d..af18967f699b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -337,6 +337,8 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) if (!d) break; + + device_link_add(dev, d, DL_FLAG_STATELESS); component_match_add(dev, , compare_dev, d); } while (true); } @@ -406,6 +408,7 @@ static int rockchip_drm_platform_of_probe(struct device *dev) static int rockchip_drm_platform_probe(struct platform_device *pdev) { struct device *dev = >dev; + struct device_link *link; struct component_match *match = NULL; int ret; @@ -414,16 +417,31 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) return ret; match = rockchip_drm_match_add(dev); - if (IS_ERR(match)) - return PTR_ERR(match); + if (IS_ERR(match)) { + ret = PTR_ERR(match); + goto err_cleanup_dev_links; + } - return component_master_add_with_match(dev, _drm_ops, match); + ret = component_master_add_with_match(dev, _drm_ops, match); + if (ret < 0) + goto err_cleanup_dev_links; + + return 0; +err_cleanup_dev_links: + list_for_each_entry(link, >links.consumers, s_node) + device_link_del(link); + return ret; } static int rockchip_drm_platform_remove(struct platform_device *pdev) { + struct device_link *link; + component_master_del(>dev, _drm_ops); + list_for_each_entry(link, >dev.links.consumers, s_node) + device_link_del(link); + return 0; } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC PATCH v3 3/5] drm/bridge/analogix: Do not use device's drvdata
From: Tomasz Figa <tf...@chromium.org> The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Andrzej Hajda <a.ha...@samsung.com> --- Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 47 +++- include/drm/bridge/analogix_dp.h | 19 4 files changed, 73 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = >dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(>dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(>dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(>dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
[RFC PATCH v3 0/5] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Changes in v3: Assign orphan pwms to dummy pwmchip instead of adding device link in the customer driver. Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. Jeffy Chen (4): arm64: dts: rockchip: Enable edp disaplay on kevin drm/rockchip: Fix error handling path in rockchip_dp_bind() pwm: Add dummy pwmchip for orphan pwms drm/rockchip: Add device links for master and components Tomasz Figa (1): drm/bridge/analogix: Do not use device's drvdata arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 + drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 ++--- drivers/gpu/drm/exynos/exynos_dp.c | 26 --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 +-- drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 ++- drivers/pwm/core.c | 84 -- include/drm/bridge/analogix_dp.h | 19 ++--- 8 files changed, 226 insertions(+), 79 deletions(-) -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RESEND PATCH v2 5/5] drm/rockchip: Add device links for master and components
Since we are trying to access components' resources in the master's suspend/resume PM callbacks(e.g. panel), add device links to correct the suspend/resume and shutdown ordering. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 +--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 76d63de5921d..af18967f699b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -337,6 +337,8 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) if (!d) break; + + device_link_add(dev, d, DL_FLAG_STATELESS); component_match_add(dev, , compare_dev, d); } while (true); } @@ -406,6 +408,7 @@ static int rockchip_drm_platform_of_probe(struct device *dev) static int rockchip_drm_platform_probe(struct platform_device *pdev) { struct device *dev = >dev; + struct device_link *link; struct component_match *match = NULL; int ret; @@ -414,16 +417,31 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) return ret; match = rockchip_drm_match_add(dev); - if (IS_ERR(match)) - return PTR_ERR(match); + if (IS_ERR(match)) { + ret = PTR_ERR(match); + goto err_cleanup_dev_links; + } - return component_master_add_with_match(dev, _drm_ops, match); + ret = component_master_add_with_match(dev, _drm_ops, match); + if (ret < 0) + goto err_cleanup_dev_links; + + return 0; +err_cleanup_dev_links: + list_for_each_entry(link, >links.consumers, s_node) + device_link_del(link); + return ret; } static int rockchip_drm_platform_remove(struct platform_device *pdev) { + struct device_link *link; + component_master_del(>dev, _drm_ops); + list_for_each_entry(link, >dev.links.consumers, s_node) + device_link_del(link); + return 0; } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RESEND PATCH v2 2/5] backlight: pwm_bl: Add device link for pwm_bl and pwm
When the pwm driver is unbound, the pwm_bl driver would still hold a reference to that pwm, and crash the kernel later(if someone trying to access that invalid pwm). Add a device link to avoid this. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: None drivers/video/backlight/pwm_bl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 9bd17682655a..a76f147a26e7 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -328,6 +328,8 @@ static int pwm_backlight_probe(struct platform_device *pdev) goto err_alloc; } + device_link_add(>dev, pb->pwm->chip->dev, DL_FLAG_AUTOREMOVE); + dev_dbg(>dev, "got pwm for backlight\n"); /* -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RESEND PATCH v2 3/5] drm/rockchip: Fix error handling path in rockchip_dp_bind()
Add missing error handling in rockchip_dp_bind(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..cb8941e8bcdd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -371,7 +371,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, ret = rockchip_dp_drm_create_encoder(dp); if (ret) { DRM_ERROR("failed to create drm encoder\n"); - return ret; + goto err_deinit_dp; } dp->plat_data.encoder = >encoder; @@ -387,7 +387,17 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, rockchip_drm_psr_register(>encoder, analogix_dp_psr_set); - return analogix_dp_bind(dev, dp->drm_dev, >plat_data); + ret = analogix_dp_bind(dev, dp->drm_dev, >plat_data); + if (ret < 0) + goto err_unreg_psr; + return 0; + +err_unreg_psr: + rockchip_drm_psr_unregister(>encoder); + rockchip_dp_drm_encoder_destroy(>encoder); +err_deinit_dp: + clk_disable_unprepare(dp->pclk); + return ret; } static void rockchip_dp_unbind(struct device *dev, struct device *master, -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RESEND PATCH v2 4/5] drm/bridge/analogix: Do not use device's drvdata
From: Tomasz Figa <tf...@chromium.org> The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa <tf...@chromium.org> Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 47 +++- include/drm/bridge/analogix_dp.h | 19 4 files changed, 73 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = >dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(>dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(>dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(>dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, "hpd_gpio"); if (ret) { dev_err(>dev, &
[RESEND PATCH v2 0/5] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. Jeffy Chen (4): arm64: dts: rockchip: Enable edp disaplay on kevin backlight: pwm_bl: Add device link for pwm_bl and pwm drm/rockchip: Fix error handling path in rockchip_dp_bind() drm/rockchip: Add device links for master and components Tomasz Figa (1): drm/bridge/analogix: Do not use device's drvdata arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 ++ drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 --- drivers/gpu/drm/exynos/exynos_dp.c | 26 +- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 ++ drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 +++-- drivers/video/backlight/pwm_bl.c | 2 + include/drm/bridge/analogix_dp.h | 19 +--- 8 files changed, 151 insertions(+), 72 deletions(-) -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/5] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Jeffy Chen (4): arm64: dts: rockchip: Enable edp disaplay on kevin backlight: pwm_bl: Add device link for pwm_bl and pwm drm/rockchip: Fix error handling path in rockchip_dp_bind() drm/rockchip: Add device links for master and components Tomasz Figa (1): drm/bridge/analogix: Do not use device's drvdata arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 ++ drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 --- drivers/gpu/drm/exynos/exynos_dp.c | 26 +- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 ++ drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 +++-- drivers/video/backlight/pwm_bl.c | 2 + include/drm/bridge/analogix_dp.h | 19 +--- 8 files changed, 151 insertions(+), 72 deletions(-) -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] drm/atomic: Unref duplicated drm_atomic_state in drm_atomic_helper_resume()
Kmemleak reported memory leak after suspend and resume: unreferenced object 0xffc0e31d8880 (size 128): comm "bash", pid 181, jiffies 4294763583 (age 24.694s) hex dump (first 32 bytes): 01 00 00 00 00 00 00 00 00 20 a2 eb c0 ff ff ff . .. 01 00 00 00 00 00 00 00 80 87 1d e3 c0 ff ff ff backtrace: [] __save_stack_trace+0x48/0x6c [] create_object+0x138/0x254 [] kmemleak_alloc+0x58/0x8c [] kmem_cache_alloc_trace+0x188/0x254 [] drm_atomic_state_alloc+0x3c/0x88 [] drm_atomic_helper_duplicate_state+0x28/0x158 [] drm_atomic_helper_suspend+0x5c/0xf0 Problem here is that we are duplicating the drm_atomic_state in drm_atomic_helper_suspend(), but not unreference it in the resume path. Fixes: 1494276000db ("drm/atomic-helper: Implement subsystem-level suspend/resume") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: Unref duplicated drm_atomic_state in drm_atomic_helper_resume() instead of specific drivers. drivers/gpu/drm/drm_atomic_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 01c34bc5b5b0..4a262380c631 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3052,6 +3052,7 @@ int drm_atomic_helper_resume(struct drm_device *dev, drm_modeset_backoff(); } + drm_atomic_state_put(state); drm_modeset_drop_locks(); drm_modeset_acquire_fini(); -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/rockchip: Fix memory leak in rockchip_drm_sys_resume()
Free the drm_atomic_state allocated by drm_atomic_helper_suspend(). Fixes: 5a5873830972 ("drm/rockchip: Use atomic PM helpers") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 76d63de5921d..80235b672deb 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -299,6 +300,7 @@ static int rockchip_drm_sys_resume(struct device *dev) priv = drm->dev_private; drm_atomic_helper_resume(drm, priv->state); + drm_atomic_state_put(priv->state); rockchip_drm_fb_resume(drm); drm_kms_helper_poll_enable(drm); -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm: Add missing field copy in compat_drm_version
DRM_IOCTL_VERSION is supposed to update the name_len/date_len/desc_len fields to user. Fixes: 012c6741c6aa("switch compat_drm_version() to drm_ioctl_kernel()") Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/drm_ioc32.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index 94acf51..2789356 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -112,6 +112,9 @@ static int compat_drm_version(struct file *file, unsigned int cmd, v32.version_major = v.version_major; v32.version_minor = v.version_minor; v32.version_patchlevel = v.version_patchlevel; + v32.name_len = v.name_len; + v32.date_len = v.date_len; + v32.desc_len = v.desc_len; if (copy_to_user((void __user *)arg, , sizeof(v32))) return -EFAULT; return 0; -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/rockchip: Don't allow zero sized gem buffer
The system would crash when trying to alloc zero sized gem buffer: [6.712435] Unable to handle kernel NULL pointer dereference at virtual address 0010 <--ZERO_SIZE_PTR ... [6.757502] PC is at sg_alloc_table_from_pages+0x170/0x1ec Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index df9e570..8917922 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -315,6 +315,11 @@ struct rockchip_gem_object * struct drm_gem_object *obj; int ret; + if (!size) { + DRM_ERROR("gem buffer size is zero\n"); + return ERR_PTR(-EINVAL); + } + size = round_up(size, PAGE_SIZE); rk_obj = kzalloc(sizeof(*rk_obj), GFP_KERNEL); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/rockchip: analogix_dp: Remove unused check and variables
Remove unused check and variables after: drm/rockchip: Set line flag config register in vop_crtc_enable Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 10 +- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 9bfdbc6..1bccd82 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -104,17 +104,9 @@ static void analogix_dp_psr_work(struct work_struct *work) { struct rockchip_dp_device *dp = container_of(work, typeof(*dp), psr_work); - struct drm_crtc *crtc = dp->encoder.crtc; - int psr_state = dp->psr_state; - int vact_end; int ret; unsigned long flags; - if (!crtc) - return; - - vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay; - ret = rockchip_drm_wait_vact_end(dp->encoder.crtc, PSR_WAIT_LINE_FLAG_TIMEOUT_MS); if (ret) { @@ -123,7 +115,7 @@ static void analogix_dp_psr_work(struct work_struct *work) } spin_lock_irqsave(>psr_lock, flags); - if (psr_state == EDP_VSC_PSR_STATE_ACTIVE) + if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE) analogix_dp_enable_psr(dp->dev); else analogix_dp_disable_psr(dp->dev); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] drm/rockchip: Set line flag config register in vop_crtc_enable
We need to set vop config done after update line flag config, it's a new requirement for chips newer than rk3368. Since we would only use line flag irq for vact_end, let's move it to vop_crtc_enable. v2: Remove unused check and variables. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: Remove unused check and variables. drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 +++--- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 3 +-- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 +--- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index d8fa7a9..1bccd82 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -104,26 +104,18 @@ static void analogix_dp_psr_work(struct work_struct *work) { struct rockchip_dp_device *dp = container_of(work, typeof(*dp), psr_work); - struct drm_crtc *crtc = dp->encoder.crtc; - int psr_state = dp->psr_state; - int vact_end; int ret; unsigned long flags; - if (!crtc) - return; - - vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay; - - ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end, - PSR_WAIT_LINE_FLAG_TIMEOUT_MS); + ret = rockchip_drm_wait_vact_end(dp->encoder.crtc, +PSR_WAIT_LINE_FLAG_TIMEOUT_MS); if (ret) { dev_err(dp->dev, "line flag interrupt did not arrive\n"); return; } spin_lock_irqsave(>psr_lock, flags); - if (psr_state == EDP_VSC_PSR_STATE_ACTIVE) + if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE) analogix_dp_enable_psr(dp->dev); else analogix_dp_disable_psr(dp->dev); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index a48fcce..47905fa 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -62,8 +62,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, struct device *dev); void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, struct device *dev); -int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, - unsigned int mstimeout); +int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout); extern struct platform_driver cdn_dp_driver; extern struct platform_driver dw_hdmi_rockchip_pltfm_driver; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 3f7a82d..40a5e6e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -468,7 +468,7 @@ static bool vop_line_flag_irq_is_enabled(struct vop *vop) return !!line_flag_irq; } -static void vop_line_flag_irq_enable(struct vop *vop, int line_num) +static void vop_line_flag_irq_enable(struct vop *vop) { unsigned long flags; @@ -477,7 +477,6 @@ static void vop_line_flag_irq_enable(struct vop *vop, int line_num) spin_lock_irqsave(>irq_lock, flags); - VOP_CTRL_SET(vop, line_flag_num[0], line_num); VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1); VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1); @@ -981,6 +980,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc) VOP_CTRL_SET(vop, vact_st_end, val); VOP_CTRL_SET(vop, vpost_st_end, val); + VOP_CTRL_SET(vop, line_flag_num[0], vact_end); + clk_set_rate(vop->dclk, adjusted_mode->clock * 1000); VOP_CTRL_SET(vop, standby, 0); @@ -1507,19 +1508,16 @@ static void vop_win_init(struct vop *vop) } /** - * rockchip_drm_wait_line_flag - acqiure the give line flag event + * rockchip_drm_wait_vact_end * @crtc: CRTC to enable line flag - * @line_num: interested line number * @mstimeout: millisecond for timeout * - * Driver would hold here until the interested line flag interrupt have - * happened or timeout to wait. + * Wait for vact_end line flag irq or timeout. * * Returns: * Zero on success, negative errno on failure. */ -int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, - unsigned int mstimeout) +int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout) { struct vop *vop = to_vop(crtc); unsigned long jiffies_left; @@ -1527,14 +1525,14 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, if (!crtc || !vop->is_enable
[PATCH] drm/rockchip: Set line flag config register in vop_crtc_enable
We need to set vop config done after update line flag config, it's a new requirement for chips newer than rk3368. Since we would only use line flag irq for vact_end, let's move it to vop_crtc_enable. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 4 ++-- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 3 +-- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 +--- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index d8fa7a9..9bfdbc6 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -115,8 +115,8 @@ static void analogix_dp_psr_work(struct work_struct *work) vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay; - ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end, - PSR_WAIT_LINE_FLAG_TIMEOUT_MS); + ret = rockchip_drm_wait_vact_end(dp->encoder.crtc, +PSR_WAIT_LINE_FLAG_TIMEOUT_MS); if (ret) { dev_err(dp->dev, "line flag interrupt did not arrive\n"); return; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index a48fcce..47905fa 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -62,8 +62,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, struct device *dev); void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, struct device *dev); -int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, - unsigned int mstimeout); +int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout); extern struct platform_driver cdn_dp_driver; extern struct platform_driver dw_hdmi_rockchip_pltfm_driver; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 3f7a82d..40a5e6e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -468,7 +468,7 @@ static bool vop_line_flag_irq_is_enabled(struct vop *vop) return !!line_flag_irq; } -static void vop_line_flag_irq_enable(struct vop *vop, int line_num) +static void vop_line_flag_irq_enable(struct vop *vop) { unsigned long flags; @@ -477,7 +477,6 @@ static void vop_line_flag_irq_enable(struct vop *vop, int line_num) spin_lock_irqsave(>irq_lock, flags); - VOP_CTRL_SET(vop, line_flag_num[0], line_num); VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1); VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1); @@ -981,6 +980,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc) VOP_CTRL_SET(vop, vact_st_end, val); VOP_CTRL_SET(vop, vpost_st_end, val); + VOP_CTRL_SET(vop, line_flag_num[0], vact_end); + clk_set_rate(vop->dclk, adjusted_mode->clock * 1000); VOP_CTRL_SET(vop, standby, 0); @@ -1507,19 +1508,16 @@ static void vop_win_init(struct vop *vop) } /** - * rockchip_drm_wait_line_flag - acqiure the give line flag event + * rockchip_drm_wait_vact_end * @crtc: CRTC to enable line flag - * @line_num: interested line number * @mstimeout: millisecond for timeout * - * Driver would hold here until the interested line flag interrupt have - * happened or timeout to wait. + * Wait for vact_end line flag irq or timeout. * * Returns: * Zero on success, negative errno on failure. */ -int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, - unsigned int mstimeout) +int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout) { struct vop *vop = to_vop(crtc); unsigned long jiffies_left; @@ -1527,14 +1525,14 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, if (!crtc || !vop->is_enabled) return -ENODEV; - if (line_num > crtc->mode.vtotal || mstimeout <= 0) + if (mstimeout <= 0) return -EINVAL; if (vop_line_flag_irq_is_enabled(vop)) return -EBUSY; reinit_completion(>line_flag_completion); - vop_line_flag_irq_enable(vop, line_num); + vop_line_flag_irq_enable(vop); jiffies_left = wait_for_completion_timeout(>line_flag_completion, msecs_to_jiffies(mstimeout)); @@ -1547,7 +1545,7 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, return 0; } -EXPORT_SYMBOL(rockchip_drm_wait_line_flag); +E
[PATCH v11] drm: Unplug drm device when unregistering it (v8)
After unbinding drm, the user space may still owns the drm dev fd, and may still be able to call drm ioctl. We're using an unplugged state to prevent something like that, so let's reuse it here. Also drop drm_unplug_dev, because it would be unused after other changes. Verified on rk3399 chromebook kevin(with cros 4.4 kernel), no more crashes when unbinding drm with ui service still running. v2: Fix some commit messages. v3: Reuse unplug status. v4: Add drm_device_set_plug_state helper. v5: Fix hang when unregistering drm dev with open_count 0. v6: Move drm_device_set_plug_state into drm_drv. v7: Add missing drm_dev_unref in udl_drv. v8: Fix compiler errors after enable udl. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/drm_drv.c | 26 ++ drivers/gpu/drm/udl/udl_drv.c | 3 ++- include/drm/drmP.h| 6 -- include/drm/drm_drv.h | 1 - 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b5c6bb4..e1da4d1 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -355,22 +355,6 @@ void drm_put_dev(struct drm_device *dev) } EXPORT_SYMBOL(drm_put_dev); -void drm_unplug_dev(struct drm_device *dev) -{ - /* for a USB device */ - drm_dev_unregister(dev); - - mutex_lock(_global_mutex); - - drm_device_set_unplugged(dev); - - if (dev->open_count == 0) { - drm_put_dev(dev); - } - mutex_unlock(_global_mutex); -} -EXPORT_SYMBOL(drm_unplug_dev); - /* * DRM internal mount * We want to be able to allocate our own "struct address_space" to control @@ -733,6 +717,13 @@ static void remove_compat_control_link(struct drm_device *dev) kfree(name); } +static inline void drm_device_set_plug_state(struct drm_device *dev, +bool plugged) +{ + smp_wmb(); + atomic_set(>unplugged, !plugged); +} + /** * drm_dev_register - Register DRM device * @dev: Device to register @@ -787,6 +778,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_register_all(dev); + drm_device_set_plug_state(dev, true); + ret = 0; DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", @@ -826,6 +819,7 @@ void drm_dev_unregister(struct drm_device *dev) drm_lastclose(dev); dev->registered = false; + drm_device_set_plug_state(dev, false); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_unregister_all(dev); diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index cd8b017..fc73e24 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -108,7 +108,8 @@ static void udl_usb_disconnect(struct usb_interface *interface) drm_kms_helper_poll_disable(dev); udl_fbdev_unplug(dev); udl_drop_usb(dev); - drm_unplug_dev(dev); + drm_dev_unregister(dev); + drm_dev_unref(dev); } /* diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 3bfafcd..980a204 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -488,12 +488,6 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, return ((dev->driver->driver_features & feature) ? 1 : 0); } -static inline void drm_device_set_unplugged(struct drm_device *dev) -{ - smp_wmb(); - atomic_set(>unplugged, 1); -} - static inline int drm_device_is_unplugged(struct drm_device *dev) { int ret = atomic_read(>unplugged); diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 0fefc3f..eb63078 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -544,7 +544,6 @@ void drm_dev_unregister(struct drm_device *dev); void drm_dev_ref(struct drm_device *dev); void drm_dev_unref(struct drm_device *dev); void drm_put_dev(struct drm_device *dev); -void drm_unplug_dev(struct drm_device *dev); int drm_dev_set_unique(struct drm_device *dev, const char *name); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9] drm: Unplug drm device when unregistering it
After unbinding drm, the user space may still owns the drm dev fd, and may still be able to call drm ioctl. We're using an unplugged state to prevent something like that, so let's reuse it here. Also drop drm_unplug_dev, because it would be unused after other changes. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Changes in v9: Move drm_device_set_plug_state into drm_drv.c . Changes in v8: Fix hang when unregistering drm dev with open_count 0. Changes in v7: Add drm_device_set_plug_state helper. Changes in v6: Reuse unplug status. Changes in v5: Fix wrong git account. Changes in v2: Fix some commit messages. --- drivers/gpu/drm/drm_drv.c | 26 ++ drivers/gpu/drm/udl/udl_drv.c | 2 +- include/drm/drmP.h| 6 -- include/drm/drm_drv.h | 1 - 4 files changed, 11 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b5c6bb4..e1da4d1 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -355,22 +355,6 @@ void drm_put_dev(struct drm_device *dev) } EXPORT_SYMBOL(drm_put_dev); -void drm_unplug_dev(struct drm_device *dev) -{ - /* for a USB device */ - drm_dev_unregister(dev); - - mutex_lock(_global_mutex); - - drm_device_set_unplugged(dev); - - if (dev->open_count == 0) { - drm_put_dev(dev); - } - mutex_unlock(_global_mutex); -} -EXPORT_SYMBOL(drm_unplug_dev); - /* * DRM internal mount * We want to be able to allocate our own "struct address_space" to control @@ -733,6 +717,13 @@ static void remove_compat_control_link(struct drm_device *dev) kfree(name); } +static inline void drm_device_set_plug_state(struct drm_device *dev, +bool plugged) +{ + smp_wmb(); + atomic_set(>unplugged, !plugged); +} + /** * drm_dev_register - Register DRM device * @dev: Device to register @@ -787,6 +778,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_register_all(dev); + drm_device_set_plug_state(dev, true); + ret = 0; DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", @@ -826,6 +819,7 @@ void drm_dev_unregister(struct drm_device *dev) drm_lastclose(dev); dev->registered = false; + drm_device_set_plug_state(dev, false); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_unregister_all(dev); diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index cd8b017..5dbd916 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface *interface) drm_kms_helper_poll_disable(dev); udl_fbdev_unplug(dev); udl_drop_usb(dev); - drm_unplug_dev(dev); + drm_dev_unregister(dev); } /* diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 3bfafcd..980a204 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -488,12 +488,6 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, return ((dev->driver->driver_features & feature) ? 1 : 0); } -static inline void drm_device_set_unplugged(struct drm_device *dev) -{ - smp_wmb(); - atomic_set(>unplugged, 1); -} - static inline int drm_device_is_unplugged(struct drm_device *dev) { int ret = atomic_read(>unplugged); diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 0fefc3f..eb63078 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -544,7 +544,6 @@ void drm_dev_unregister(struct drm_device *dev); void drm_dev_ref(struct drm_device *dev); void drm_dev_unref(struct drm_device *dev); void drm_put_dev(struct drm_device *dev); -void drm_unplug_dev(struct drm_device *dev); int drm_dev_set_unique(struct drm_device *dev, const char *name); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v8 1/2] drm: Unplug drm device when unregistering it
After unbinding drm, the user space may still owns the drm dev fd, and may still be able to call drm ioctl. We're using an unplugged state to prevent something like that, so let's reuse it here. Also drop drm_unplug_dev, because it would be unused after other changes. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Sean Paul <seanp...@chromium.org> --- Changes in v8: Fix hang when unregistering drm dev with open_count 0 Changes in v7: Address Sean Paul <seanp...@chromium.org>'s comments. Changes in v6: Address Daniel Vetter <dan...@ffwll.ch>'s comments. Changes in v5: Fix wrong git account. Changes in v2: Fix some commit messages. drivers/gpu/drm/drm_drv.c | 19 +++ drivers/gpu/drm/udl/udl_drv.c | 2 +- include/drm/drmP.h| 5 +++-- include/drm/drm_drv.h | 1 - 4 files changed, 7 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b5c6bb4..cc2d018 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -355,22 +355,6 @@ void drm_put_dev(struct drm_device *dev) } EXPORT_SYMBOL(drm_put_dev); -void drm_unplug_dev(struct drm_device *dev) -{ - /* for a USB device */ - drm_dev_unregister(dev); - - mutex_lock(_global_mutex); - - drm_device_set_unplugged(dev); - - if (dev->open_count == 0) { - drm_put_dev(dev); - } - mutex_unlock(_global_mutex); -} -EXPORT_SYMBOL(drm_unplug_dev); - /* * DRM internal mount * We want to be able to allocate our own "struct address_space" to control @@ -787,6 +771,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_register_all(dev); + drm_device_set_plug_state(dev, true); + ret = 0; DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", @@ -826,6 +812,7 @@ void drm_dev_unregister(struct drm_device *dev) drm_lastclose(dev); dev->registered = false; + drm_device_set_plug_state(dev, false); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_unregister_all(dev); diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index cd8b017..5dbd916 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface *interface) drm_kms_helper_poll_disable(dev); udl_fbdev_unplug(dev); udl_drop_usb(dev); - drm_unplug_dev(dev); + drm_dev_unregister(dev); } /* diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 3bfafcd..a9a5a64 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -488,10 +488,11 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, return ((dev->driver->driver_features & feature) ? 1 : 0); } -static inline void drm_device_set_unplugged(struct drm_device *dev) +static inline void drm_device_set_plug_state(struct drm_device *dev, +bool plugged) { smp_wmb(); - atomic_set(>unplugged, 1); + atomic_set(>unplugged, !plugged); } static inline int drm_device_is_unplugged(struct drm_device *dev) diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 0fefc3f..eb63078 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -544,7 +544,6 @@ void drm_dev_unregister(struct drm_device *dev); void drm_dev_ref(struct drm_device *dev); void drm_dev_unref(struct drm_device *dev); void drm_put_dev(struct drm_device *dev); -void drm_unplug_dev(struct drm_device *dev); int drm_dev_set_unique(struct drm_device *dev, const char *name); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v8 0/2] drm: rockchip: Fix rockchip drm unbind crash error
Verified on rk3399 chromebook kevin(with cros 4.4 kernel), no more crashes during unbind/bind drm with/out ui service running. Changes in v8: Fix hang when unregistering drm dev with open_count 0 Changes in v7: Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Changes in v6: Address Daniel Vetter <dan...@ffwll.ch>'s comments. Changes in v5: Fix wrong git account. Changes in v2: Fix some commit messages. Jeffy Chen (2): drm: Unplug drm device when unregistering it drm: Prevent release fb after cleanup drm_mode_config drivers/gpu/drm/drm_drv.c | 19 +++ drivers/gpu/drm/drm_framebuffer.c | 5 + drivers/gpu/drm/udl/udl_drv.c | 2 +- include/drm/drmP.h| 5 +++-- include/drm/drm_drv.h | 1 - 5 files changed, 12 insertions(+), 20 deletions(-) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 0/1] drm: rockchip: Fix rockchip drm unbind crash error
Verified on rk3399 chromebook kevin(with cros 4.4 kernel), no more crashes during unbind/bind drm with/out ui service running. Changes in v9: Move drm_device_set_plug_state into drm_drv.c . Changes in v8: Fix hang when unregistering drm dev with open_count 0. Changes in v7: Add drm_device_set_plug_state helper. Changes in v6: Reuse unplug status. Changes in v5: Fix wrong git account. Changes in v2: Fix some commit messages. Jeffy Chen (1): drm: Unplug drm device when unregistering it drivers/gpu/drm/drm_drv.c | 26 ++ drivers/gpu/drm/udl/udl_drv.c | 2 +- include/drm/drmP.h| 6 -- include/drm/drm_drv.h | 1 - 4 files changed, 11 insertions(+), 24 deletions(-) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v8 2/2] drm: Prevent release fb after cleanup drm_mode_config
We are freeing all framebuffers in drm_mode_config_cleanup without sync the drm_file's fbs list. So if someone try to unbind drm before release drm dev fd, the fbs list would remain some invalid fb references. And that would cause crash later in drm_fb_release. Add a sanity check to prevent that. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v8: None Changes in v7: Update commit message. Changes in v6: None Changes in v5: None Changes in v2: None drivers/gpu/drm/drm_framebuffer.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index e8f9c13..03c1632 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -583,6 +583,11 @@ void drm_fb_release(struct drm_file *priv) { struct drm_framebuffer *fb, *tfb; struct drm_mode_rmfb_work arg; + struct drm_minor *minor = priv->minor; + struct drm_device *dev = minor->dev; + + if (WARN_ON(!dev->mode_config.num_fb && !list_empty(>fbs))) + return; INIT_LIST_HEAD(); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v7 1/2] drm: Unplug drm device when unregistering it
After unbinding drm, the user space may still owns the drm dev fd, and may still be able to call drm ioctl. We're using an unplugged state to prevent something like that, so let's reuse it here. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Sean Paul <seanp...@chromium.org> --- Changes in v7: Address Sean Paul <seanp...@chromium.org>'s comments. Changes in v6: Address Daniel Vetter <dan...@ffwll.ch>'s comments. Changes in v5: Fix wrong git account. Changes in v2: Fix some commit messages. drivers/gpu/drm/drm_drv.c | 8 drivers/gpu/drm/udl/udl_drv.c | 2 +- include/drm/drmP.h| 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b5c6bb4..ad13e20 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -357,12 +357,9 @@ EXPORT_SYMBOL(drm_put_dev); void drm_unplug_dev(struct drm_device *dev) { - /* for a USB device */ - drm_dev_unregister(dev); - mutex_lock(_global_mutex); - drm_device_set_unplugged(dev); + drm_device_set_plug_state(dev, false); if (dev->open_count == 0) { drm_put_dev(dev); @@ -787,6 +784,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_register_all(dev); + drm_device_set_plug_state(dev, true); + ret = 0; DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", @@ -826,6 +825,7 @@ void drm_dev_unregister(struct drm_device *dev) drm_lastclose(dev); dev->registered = false; + drm_unplug_dev(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_unregister_all(dev); diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index cd8b017..5dbd916 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface *interface) drm_kms_helper_poll_disable(dev); udl_fbdev_unplug(dev); udl_drop_usb(dev); - drm_unplug_dev(dev); + drm_dev_unregister(dev); } /* diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 3bfafcd..a9a5a64 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -488,10 +488,11 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, return ((dev->driver->driver_features & feature) ? 1 : 0); } -static inline void drm_device_set_unplugged(struct drm_device *dev) +static inline void drm_device_set_plug_state(struct drm_device *dev, +bool plugged) { smp_wmb(); - atomic_set(>unplugged, 1); + atomic_set(>unplugged, !plugged); } static inline int drm_device_is_unplugged(struct drm_device *dev) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm: Fixup hang when unregistering drm dev with open_count 0
My previous patch (c5d8fac2bf drm: Unplug drm device when unregistering it) calls drm_unplug_dev when unregistering drm dev. But if open_count is 0, the unplug will try to unregister the drm dev again and cause deadlock. Fix it by dropping drm_unplug_dev and use drm_device_set_plug_state directly. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/drm_drv.c | 15 +-- include/drm/drm_drv.h | 1 - 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index ad13e20..cc2d018 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -355,19 +355,6 @@ void drm_put_dev(struct drm_device *dev) } EXPORT_SYMBOL(drm_put_dev); -void drm_unplug_dev(struct drm_device *dev) -{ - mutex_lock(_global_mutex); - - drm_device_set_plug_state(dev, false); - - if (dev->open_count == 0) { - drm_put_dev(dev); - } - mutex_unlock(_global_mutex); -} -EXPORT_SYMBOL(drm_unplug_dev); - /* * DRM internal mount * We want to be able to allocate our own "struct address_space" to control @@ -825,7 +812,7 @@ void drm_dev_unregister(struct drm_device *dev) drm_lastclose(dev); dev->registered = false; - drm_unplug_dev(dev); + drm_device_set_plug_state(dev, false); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_unregister_all(dev); diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 0fefc3f..eb63078 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -544,7 +544,6 @@ void drm_dev_unregister(struct drm_device *dev); void drm_dev_ref(struct drm_device *dev); void drm_dev_unref(struct drm_device *dev); void drm_put_dev(struct drm_device *dev); -void drm_unplug_dev(struct drm_device *dev); int drm_dev_set_unique(struct drm_device *dev, const char *name); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v7 0/2] drm: rockchip: Fix rockchip drm unbind crash error
Verified on rk3399 chromebook kevin(with cros 4.4 kernel), no more crashes during unbind/bind drm. Changes in v7: Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Changes in v6: Address Daniel Vetter <dan...@ffwll.ch>'s comments. Changes in v5: Fix wrong git account. Changes in v2: Fix some commit messages. Jeffy Chen (2): drm: Unplug drm device when unregistering it drm: Prevent release fb after cleanup drm_mode_config drivers/gpu/drm/drm_drv.c | 8 drivers/gpu/drm/drm_framebuffer.c | 5 + drivers/gpu/drm/udl/udl_drv.c | 2 +- include/drm/drmP.h| 5 +++-- 4 files changed, 13 insertions(+), 7 deletions(-) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v7 2/2] drm: Prevent release fb after cleanup drm_mode_config
We are freeing all framebuffers in drm_mode_config_cleanup without sync the drm_file's fbs list. So if someone try to unbind drm before release drm dev fd, the fbs list would remain some invalid fb references. And that would cause crash later in drm_fb_release. Add a sanity check to prevent that. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v7: Update commit message. Changes in v6: None Changes in v5: None Changes in v2: None drivers/gpu/drm/drm_framebuffer.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index e8f9c13..03c1632 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -583,6 +583,11 @@ void drm_fb_release(struct drm_file *priv) { struct drm_framebuffer *fb, *tfb; struct drm_mode_rmfb_work arg; + struct drm_minor *minor = priv->minor; + struct drm_device *dev = minor->dev; + + if (WARN_ON(!dev->mode_config.num_fb && !list_empty(>fbs))) + return; INIT_LIST_HEAD(); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 2/2] drm: Prevent release fb after cleanup mode config
After unbinding drm, the user space may still owns the drm dev fd, and may trigger fb release after cleanup mode config. Add a sanity check to prevent that. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v6: None Changes in v5: None Changes in v2: None drivers/gpu/drm/drm_framebuffer.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index e8f9c13..03c1632 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -583,6 +583,11 @@ void drm_fb_release(struct drm_file *priv) { struct drm_framebuffer *fb, *tfb; struct drm_mode_rmfb_work arg; + struct drm_minor *minor = priv->minor; + struct drm_device *dev = minor->dev; + + if (WARN_ON(!dev->mode_config.num_fb && !list_empty(>fbs))) + return; INIT_LIST_HEAD(); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 0/2] drm: rockchip: Fix rockchip drm unbind crash error
Verified on rk3399 chromebook kevin, no more crashes during unbind/bind drm. Changes in v6: Address Daniel Vetter <dan...@ffwll.ch>'s comments. Changes in v5: Fix wrong git account. Changes in v2: Fix some commit messages. Jeffy Chen (2): drm: Unplug drm device when unregistering it drm: Prevent release fb after cleanup mode config drivers/gpu/drm/drm_drv.c | 6 +++--- drivers/gpu/drm/drm_framebuffer.c | 5 + drivers/gpu/drm/udl/udl_drv.c | 2 +- include/drm/drmP.h| 6 ++ 4 files changed, 15 insertions(+), 4 deletions(-) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 1/2] drm: Unplug drm device when unregistering it
After unbinding drm, the user space may still owns the drm dev fd, and may still be able to call drm ioctl. We're using an unplugged state to prevent something like that, so let's reuse it here. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v6: Address Daniel Vetter <dan...@ffwll.ch>'s comments. Changes in v5: Fix wrong git account. Changes in v2: Fix some commit messages. drivers/gpu/drm/drm_drv.c | 6 +++--- drivers/gpu/drm/udl/udl_drv.c | 2 +- include/drm/drmP.h| 6 ++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b5c6bb4..f38de26 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -357,9 +357,6 @@ EXPORT_SYMBOL(drm_put_dev); void drm_unplug_dev(struct drm_device *dev) { - /* for a USB device */ - drm_dev_unregister(dev); - mutex_lock(_global_mutex); drm_device_set_unplugged(dev); @@ -787,6 +784,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_register_all(dev); + drm_device_set_plugged(dev); + ret = 0; DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", @@ -826,6 +825,7 @@ void drm_dev_unregister(struct drm_device *dev) drm_lastclose(dev); dev->registered = false; + drm_unplug_dev(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_unregister_all(dev); diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index cd8b017..5dbd916 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -108,7 +108,7 @@ static void udl_usb_disconnect(struct usb_interface *interface) drm_kms_helper_poll_disable(dev); udl_fbdev_unplug(dev); udl_drop_usb(dev); - drm_unplug_dev(dev); + drm_dev_unregister(dev); } /* diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 3bfafcd..c930a77 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -488,6 +488,12 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, return ((dev->driver->driver_features & feature) ? 1 : 0); } +static inline void drm_device_set_plugged(struct drm_device *dev) +{ + smp_wmb(); + atomic_set(>unplugged, 0); +} + static inline void drm_device_set_unplugged(struct drm_device *dev) { smp_wmb(); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 10/12] drm/rockchip: Reoder drm bind/unbind sequence
Current drm bind/unbind sequence would cause some memory issues. For example we should not cleanup iommu before cleanup mode config. Reorder bind/unbind sequence, follow exynos drm. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: None Changes in v3: Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 49 +++-- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index cd7d02e1..f24968f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -136,21 +136,24 @@ static int rockchip_drm_bind(struct device *dev) INIT_LIST_HEAD(>psr_list); spin_lock_init(>psr_list_lock); + ret = rockchip_drm_init_iommu(drm_dev); + if (ret) + goto err_free; + drm_mode_config_init(drm_dev); rockchip_drm_mode_config_init(drm_dev); - ret = rockchip_drm_init_iommu(drm_dev); - if (ret) - goto err_config_cleanup; - /* Try to bind all sub drivers. */ ret = component_bind_all(dev, drm_dev); if (ret) - goto err_iommu_cleanup; + goto err_mode_config_cleanup; - /* init kms poll for handling hpd */ - drm_kms_helper_poll_init(drm_dev); + ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); + if (ret) + goto err_unbind_all; + + drm_mode_config_reset(drm_dev); /* * enable drm irq mode. @@ -158,15 +161,12 @@ static int rockchip_drm_bind(struct device *dev) */ drm_dev->irq_enabled = true; - ret = drm_vblank_init(drm_dev, ROCKCHIP_MAX_CRTC); - if (ret) - goto err_kms_helper_poll_fini; - - drm_mode_config_reset(drm_dev); + /* init kms poll for handling hpd */ + drm_kms_helper_poll_init(drm_dev); ret = rockchip_drm_fbdev_init(drm_dev); if (ret) - goto err_vblank_cleanup; + goto err_kms_helper_poll_fini; ret = drm_dev_register(drm_dev, 0); if (ret) @@ -175,17 +175,17 @@ static int rockchip_drm_bind(struct device *dev) return 0; err_fbdev_fini: rockchip_drm_fbdev_fini(drm_dev); -err_vblank_cleanup: - drm_vblank_cleanup(drm_dev); err_kms_helper_poll_fini: drm_kms_helper_poll_fini(drm_dev); + drm_vblank_cleanup(drm_dev); +err_unbind_all: component_unbind_all(dev, drm_dev); -err_iommu_cleanup: - rockchip_iommu_cleanup(drm_dev); -err_config_cleanup: +err_mode_config_cleanup: drm_mode_config_cleanup(drm_dev); - drm_dev->dev_private = NULL; + rockchip_iommu_cleanup(drm_dev); err_free: + drm_dev->dev_private = NULL; + dev_set_drvdata(dev, NULL); drm_dev_unref(drm_dev); return ret; } @@ -194,16 +194,19 @@ static void rockchip_drm_unbind(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + drm_dev_unregister(drm_dev); + rockchip_drm_fbdev_fini(drm_dev); - drm_vblank_cleanup(drm_dev); drm_kms_helper_poll_fini(drm_dev); + + drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); - rockchip_iommu_cleanup(drm_dev); drm_mode_config_cleanup(drm_dev); + rockchip_iommu_cleanup(drm_dev); + drm_dev->dev_private = NULL; - drm_dev_unregister(drm_dev); - drm_dev_unref(drm_dev); dev_set_drvdata(dev, NULL); + drm_dev_unref(drm_dev); } static void rockchip_drm_lastclose(struct drm_device *dev) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 01/12] drm: bridge: analogix: Detach panel when unbinding analogix dp
The panel is attached when binding analogix dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Andrzej Hajda <a.ha...@samsung.com> --- Changes in v5: Fix wrong git account. Changes in v4: None Changes in v3: None Changes in v2: Fix some commit messages. drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index c26997a..28144a1 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1443,6 +1443,8 @@ void analogix_dp_unbind(struct device *dev, struct device *master, if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) DRM_ERROR("failed to turnoff the panel\n"); + if (drm_panel_detach(dp->plat_data->panel)) + DRM_ERROR("failed to detach the panel\n"); } pm_runtime_disable(dev); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 03/12] drm: bridge: analogix: Disable clock when unbinding
The clock is enabled when binding analogix dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 7b75f82..d05ade4 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1449,6 +1449,7 @@ void analogix_dp_unbind(struct device *dev, struct device *master, drm_dp_aux_unregister(>aux); pm_runtime_disable(dev); + clk_disable_unprepare(dp->clock); } EXPORT_SYMBOL_GPL(analogix_dp_unbind); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 08/12] drm/rockchip: vop: Unprepare clocks when unbinding
The clocks are prepared when binding vop. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index b65b296..3f7a82d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1634,6 +1634,10 @@ static void vop_unbind(struct device *dev, struct device *master, void *data) pm_runtime_disable(dev); vop_destroy_crtc(vop); + + clk_unprepare(vop->aclk); + clk_unprepare(vop->hclk); + clk_unprepare(vop->dclk); } const struct component_ops vop_component_ops = { -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 07/12] drm/rockchip: vop: Enable pm domain before vop_initial
We're trying to access vop registers here, so need to make sure the pm domain is on. Normally it should be enabled by the bootloader, but there's no guarantee of it. And if we wanna do unbind/bind, it would also cause the device to hang. And this patch also does these: 1/ move vop_initial to the end of vop_bind for eaiser error handling. 2/ correct the err_put_pm_runtime of vop_enable. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: None Changes in v3: Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 + 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 2151e1c..b65b296 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -506,7 +506,7 @@ static int vop_enable(struct drm_crtc *crtc) ret = pm_runtime_get_sync(vop->dev); if (ret < 0) { dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); - goto err_put_pm_runtime; + return ret; } ret = clk_enable(vop->hclk); @@ -1405,10 +1405,16 @@ static int vop_initial(struct vop *vop) return PTR_ERR(vop->dclk); } + ret = pm_runtime_get_sync(vop->dev); + if (ret < 0) { + dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + return ret; + } + ret = clk_prepare(vop->dclk); if (ret < 0) { dev_err(vop->dev, "failed to prepare dclk\n"); - return ret; + goto err_put_pm_runtime; } /* Enable both the hclk and aclk to setup the vop */ @@ -1468,6 +1474,8 @@ static int vop_initial(struct vop *vop) vop->is_enabled = false; + pm_runtime_put_sync(vop->dev); + return 0; err_disable_aclk: @@ -1476,6 +1484,8 @@ static int vop_initial(struct vop *vop) clk_disable_unprepare(vop->hclk); err_unprepare_dclk: clk_unprepare(vop->dclk); +err_put_pm_runtime: + pm_runtime_put_sync(vop->dev); return ret; } @@ -1576,12 +1586,6 @@ static int vop_bind(struct device *dev, struct device *master, void *data) if (!vop->regsbak) return -ENOMEM; - ret = vop_initial(vop); - if (ret < 0) { - dev_err(>dev, "cannot initial vop dev - err %d\n", ret); - return ret; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "cannot find irq for vop\n"); @@ -1608,8 +1612,17 @@ static int vop_bind(struct device *dev, struct device *master, void *data) pm_runtime_enable(>dev); + ret = vop_initial(vop); + if (ret < 0) { + dev_err(>dev, "cannot initial vop dev - err %d\n", ret); + goto err_disable_pm_runtime; + } + return 0; +err_disable_pm_runtime: + pm_runtime_disable(>dev); + vop_destroy_crtc(vop); err_enable_irq: enable_irq(vop->irq); /* To balance out the disable_irq above */ return ret; -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 06/12] drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding
After snd_soc_unregister_codec, the dai link would remain bound to the invalid codec. That would cause crashes after unbind dp driver. Let's unregister audio codec when removing dp driver to prevent that. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: None Changes in v3: Update commit message. Changes in v2: None drivers/gpu/drm/rockchip/cdn-dp-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index ee4195d..a2169dd 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1092,8 +1092,6 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) goto err_free_connector; } - cdn_dp_audio_codec_init(dp, dev); - for (i = 0; i < dp->ports; i++) { port = dp->port[i]; @@ -1128,7 +1126,6 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) struct drm_connector *connector = >connector; cancel_work_sync(>event_work); - platform_device_unregister(dp->audio_pdev); cdn_dp_encoder_disable(encoder); encoder->funcs->destroy(encoder); connector->funcs->destroy(connector); @@ -1221,6 +1218,8 @@ static int cdn_dp_probe(struct platform_device *pdev) mutex_init(>lock); dev_set_drvdata(dev, dp); + cdn_dp_audio_codec_init(dp, dev); + return component_add(dev, _dp_component_ops); } @@ -1228,6 +1227,7 @@ static int cdn_dp_remove(struct platform_device *pdev) { struct cdn_dp_device *dp = platform_get_drvdata(pdev); + platform_device_unregister(dp->audio_pdev); cdn_dp_suspend(dp->dev); component_del(>dev, _dp_component_ops); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 11/12] drm/rockchip: Shutdown all crtcs when unbinding drm
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: None Changes in v3: Address Daniel Vetter <dan...@ffwll.ch>'s comments. Update commit message. Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index f24968f..c6b1b7f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -199,6 +199,7 @@ static void rockchip_drm_unbind(struct device *dev) rockchip_drm_fbdev_fini(drm_dev); drm_kms_helper_poll_fini(drm_dev); + drm_atomic_helper_shutdown(drm_dev); drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); drm_mode_config_cleanup(drm_dev); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 09/12] drm/rockchip: analogix_dp: Disable clock when unbinding
The clock is enabled when binding cdn dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 91ebe5c..c3b9f1d 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -417,7 +417,8 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, rockchip_drm_psr_unregister(>encoder); - return analogix_dp_unbind(dev, master, data); + analogix_dp_unbind(dev, master, data); + clk_disable_unprepare(dp->pclk); } static const struct component_ops rockchip_dp_component_ops = { -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 00/12] drm: rockchip: Fix rockchip drm unbind crash error
Verified on rk3399 chromebook kevin: 1/ stop ui && pkill -9 frecon 2/ unbind/bind drm Changes in v5: Fix wrong git account. Changes in v4: Address Andrzej Hajda <a.ha...@samsung.com>'s comments. Changes in v3: Update commit message. Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Address Daniel Vetter <dan...@ffwll.ch>'s comments. Update commit message. Changes in v2: Fix some commit messages. Jeffy Chen (12): drm: bridge: analogix: Detach panel when unbinding analogix dp drm: bridge: analogix: Unregister dp aux when unbinding drm: bridge: analogix: Disable clock when unbinding drm: bridge: analogix: Destroy connector & encoder when unbinding drm/rockchip: cdn-dp: Don't try to release firmware when not loaded drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding drm/rockchip: vop: Enable pm domain before vop_initial drm/rockchip: vop: Unprepare clocks when unbinding drm/rockchip: analogix_dp: Disable clock when unbinding drm/rockchip: Reoder drm bind/unbind sequence drm/rockchip: Shutdown all crtcs when unbinding drm drm/drm_ioctl.c: Break ioctl when drm device not registered drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 6 +++ drivers/gpu/drm/drm_ioctl.c| 2 +- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 3 +- drivers/gpu/drm/rockchip/cdn-dp-core.c | 10 +++-- drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 50 -- drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 33 ++ 6 files changed, 67 insertions(+), 37 deletions(-) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 04/12] drm: bridge: analogix: Destroy connector & encoder when unbinding
Normally we do this in drm_mode_config_cleanup. But: 1/ analogix dp's connector is allocated in bind, and freed after unbind. So we need to destroy it in unbind to avoid further access. 2/ the drm bridge is attached in bind, and detached in encoder cleanup. So we need to destroy encoder in unbind. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: Address Andrzej Hajda <a.ha...@samsung.com>'s comments. Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index d05ade4..4c758ed 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1439,6 +1439,8 @@ void analogix_dp_unbind(struct device *dev, struct device *master, struct analogix_dp_device *dp = dev_get_drvdata(dev); analogix_dp_bridge_disable(dp->bridge); + dp->connector.funcs->destroy(>connector); + dp->encoder->funcs->destroy(dp->encoder); if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 12/12] drm/drm_ioctl.c: Break ioctl when drm device not registered
After unbinding drm, the user space may still owns the drm dev fd, and may still be able to call drm ioctl. Add a sanity check here to prevent that from happening. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/drm_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 7d6deaa..15beb11 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -674,7 +674,7 @@ long drm_ioctl(struct file *filp, dev = file_priv->minor->dev; - if (drm_device_is_unplugged(dev)) + if (drm_device_is_unplugged(dev) || !dev->registered) return -ENODEV; is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END; -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 02/12] drm: bridge: analogix: Unregister dp aux when unbinding
The dp aux is registered when binding analogix dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> Reviewed-by: Andrzej Hajda <a.ha...@samsung.com> --- Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 28144a1..7b75f82 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1447,6 +1447,7 @@ void analogix_dp_unbind(struct device *dev, struct device *master, DRM_ERROR("failed to detach the panel\n"); } + drm_dp_aux_unregister(>aux); pm_runtime_disable(dev); } EXPORT_SYMBOL_GPL(analogix_dp_unbind); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 05/12] drm/rockchip: cdn-dp: Don't try to release firmware when not loaded
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/cdn-dp-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index 4e55d63..ee4195d 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1053,6 +1053,7 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) dp->connected = false; dp->active = false; dp->active_port = -1; + dp->fw_loaded = false; INIT_WORK(>event_work, cdn_dp_pd_event_work); @@ -1133,7 +1134,8 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) connector->funcs->destroy(connector); pm_runtime_disable(dev); - release_firmware(dp->fw); + if (dp->fw_loaded) + release_firmware(dp->fw); kfree(dp->edid); dp->edid = NULL; } -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 0/9] drm: rockchip: Fix rockchip drm unbind crash error
Verified on rk3399 chromebook kevin: 1/ stop ui && pkill -9 frecon 2/ unbind/bind drm Changes in v3: Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Address Daniel Vetter <dan...@ffwll.ch>'s comments. Update commit message. Address Daniel Vetter <dan...@ffwll.ch>'s comments. Update commit message. Update commit message. Changes in v2: Fix some commit messages. Jeffy Chen (9): drm: bridge: analogix: Detach panel when unbinding analogix dp drm: bridge: analogix: Unregister dp aux when unbinding drm: bridge: analogix: Destroy connector when unbinding drm/rockchip: cdn-dp: Don't try to release firmware when not loaded drm/rockchip: vop: Enable pm domain before vop_initial drm/rockchip: Reoder drm bind/unbind sequence drm/rockchip: Shutdown all crtcs when unbinding drm drm/rockchip: gem: Don't alloc/free gem buf when dev_private is invalid drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 ++ drivers/gpu/drm/rockchip/cdn-dp-core.c | 10 +++-- drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 50 -- drivers/gpu/drm/rockchip/rockchip_drm_gem.c| 8 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 29 + 5 files changed, 66 insertions(+), 35 deletions(-) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 2/9] drm: bridge: analogix: Unregister dp aux when unbinding
The dp aux is registered when binding analogix dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 28144a1..7b75f82 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1447,6 +1447,7 @@ void analogix_dp_unbind(struct device *dev, struct device *master, DRM_ERROR("failed to detach the panel\n"); } + drm_dp_aux_unregister(>aux); pm_runtime_disable(dev); } EXPORT_SYMBOL_GPL(analogix_dp_unbind); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 8/9] drm/rockchip: gem: Don't alloc/free gem buf when dev_private is invalid
After unbinding drm, the userspace may still has a chance to access gem buf. Add a sanity check for a NULL dev_private to prevent that from happening. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: Address Daniel Vetter <dan...@ffwll.ch>'s comments. Update commit message. Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index df9e570..205a3dc 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -184,6 +184,9 @@ static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj, struct drm_device *drm = obj->dev; struct rockchip_drm_private *private = drm->dev_private; + if (!private) + return -ENODEV; + if (private->domain) return rockchip_gem_alloc_iommu(rk_obj, alloc_kmap); else @@ -208,6 +211,11 @@ static void rockchip_gem_free_dma(struct rockchip_gem_object *rk_obj) static void rockchip_gem_free_buf(struct rockchip_gem_object *rk_obj) { + struct drm_device *drm = rk_obj->base.dev; + + if (!drm->dev_private) + return; + if (rk_obj->pages) rockchip_gem_free_iommu(rk_obj); else -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 9/9] drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding
After snd_soc_unregister_codec, the dai link would remain bound to the invalid codec. That would cause crashes after unbind dp driver. Let's unregister audio codec when removing dp driver to prevent that. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: Update commit message. Changes in v2: None drivers/gpu/drm/rockchip/cdn-dp-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index ee4195d..a2169dd 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1092,8 +1092,6 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) goto err_free_connector; } - cdn_dp_audio_codec_init(dp, dev); - for (i = 0; i < dp->ports; i++) { port = dp->port[i]; @@ -1128,7 +1126,6 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) struct drm_connector *connector = >connector; cancel_work_sync(>event_work); - platform_device_unregister(dp->audio_pdev); cdn_dp_encoder_disable(encoder); encoder->funcs->destroy(encoder); connector->funcs->destroy(connector); @@ -1221,6 +1218,8 @@ static int cdn_dp_probe(struct platform_device *pdev) mutex_init(>lock); dev_set_drvdata(dev, dp); + cdn_dp_audio_codec_init(dp, dev); + return component_add(dev, _dp_component_ops); } @@ -1228,6 +1227,7 @@ static int cdn_dp_remove(struct platform_device *pdev) { struct cdn_dp_device *dp = platform_get_drvdata(pdev); + platform_device_unregister(dp->audio_pdev); cdn_dp_suspend(dp->dev); component_del(>dev, _dp_component_ops); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 7/9] drm/rockchip: Shutdown all crtcs when unbinding drm
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: Address Daniel Vetter <dan...@ffwll.ch>'s comments. Update commit message. Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index f24968f..c6b1b7f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -199,6 +199,7 @@ static void rockchip_drm_unbind(struct device *dev) rockchip_drm_fbdev_fini(drm_dev); drm_kms_helper_poll_fini(drm_dev); + drm_atomic_helper_shutdown(drm_dev); drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); drm_mode_config_cleanup(drm_dev); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 5/9] drm/rockchip: vop: Enable pm domain before vop_initial
We're trying to access vop registers here, so need to make sure the pm domain is on. Normally it should be enabled by the bootloader, but there's no guarantee of it. And if we wanna do unbind/bind, it would also cause the device to hang. And this patch also does these: 1/ move vop_initial to the end of vop_bind for eaiser error handling. 2/ correct the err_put_pm_runtime of vop_enable. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 + 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 2151e1c..b65b296 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -506,7 +506,7 @@ static int vop_enable(struct drm_crtc *crtc) ret = pm_runtime_get_sync(vop->dev); if (ret < 0) { dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); - goto err_put_pm_runtime; + return ret; } ret = clk_enable(vop->hclk); @@ -1405,10 +1405,16 @@ static int vop_initial(struct vop *vop) return PTR_ERR(vop->dclk); } + ret = pm_runtime_get_sync(vop->dev); + if (ret < 0) { + dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + return ret; + } + ret = clk_prepare(vop->dclk); if (ret < 0) { dev_err(vop->dev, "failed to prepare dclk\n"); - return ret; + goto err_put_pm_runtime; } /* Enable both the hclk and aclk to setup the vop */ @@ -1468,6 +1474,8 @@ static int vop_initial(struct vop *vop) vop->is_enabled = false; + pm_runtime_put_sync(vop->dev); + return 0; err_disable_aclk: @@ -1476,6 +1484,8 @@ static int vop_initial(struct vop *vop) clk_disable_unprepare(vop->hclk); err_unprepare_dclk: clk_unprepare(vop->dclk); +err_put_pm_runtime: + pm_runtime_put_sync(vop->dev); return ret; } @@ -1576,12 +1586,6 @@ static int vop_bind(struct device *dev, struct device *master, void *data) if (!vop->regsbak) return -ENOMEM; - ret = vop_initial(vop); - if (ret < 0) { - dev_err(>dev, "cannot initial vop dev - err %d\n", ret); - return ret; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "cannot find irq for vop\n"); @@ -1608,8 +1612,17 @@ static int vop_bind(struct device *dev, struct device *master, void *data) pm_runtime_enable(>dev); + ret = vop_initial(vop); + if (ret < 0) { + dev_err(>dev, "cannot initial vop dev - err %d\n", ret); + goto err_disable_pm_runtime; + } + return 0; +err_disable_pm_runtime: + pm_runtime_disable(>dev); + vop_destroy_crtc(vop); err_enable_irq: enable_irq(vop->irq); /* To balance out the disable_irq above */ return ret; -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 3/9] drm: bridge: analogix: Destroy connector when unbinding
Normally we do this in drm_mode_config_cleanup. But analogix dp's connector is allocated in bind, and freed after unbind. So we need to destroy it in unbind to avoid further access. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 7b75f82..a96fd55 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1439,6 +1439,7 @@ void analogix_dp_unbind(struct device *dev, struct device *master, struct analogix_dp_device *dp = dev_get_drvdata(dev); analogix_dp_bridge_disable(dp->bridge); + dp->connector.funcs->destroy(>connector); if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 4/9] drm/rockchip: cdn-dp: Don't try to release firmware when not loaded
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/cdn-dp-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index 4e55d63..ee4195d 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1053,6 +1053,7 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) dp->connected = false; dp->active = false; dp->active_port = -1; + dp->fw_loaded = false; INIT_WORK(>event_work, cdn_dp_pd_event_work); @@ -1133,7 +1134,8 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) connector->funcs->destroy(connector); pm_runtime_disable(dev); - release_firmware(dp->fw); + if (dp->fw_loaded) + release_firmware(dp->fw); kfree(dp->edid); dp->edid = NULL; } -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 6/9] drm/rockchip: Reoder drm bind/unbind sequence
Current drm bind/unbind sequence would cause some memory issues. For example we should not cleanup iommu before cleanup mode config. Reorder bind/unbind sequence, follow exynos drm. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: Address Sean Paul <seanp...@chromium.org>'s comments. Update commit message. Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 49 +++-- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index cd7d02e1..f24968f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -136,21 +136,24 @@ static int rockchip_drm_bind(struct device *dev) INIT_LIST_HEAD(>psr_list); spin_lock_init(>psr_list_lock); + ret = rockchip_drm_init_iommu(drm_dev); + if (ret) + goto err_free; + drm_mode_config_init(drm_dev); rockchip_drm_mode_config_init(drm_dev); - ret = rockchip_drm_init_iommu(drm_dev); - if (ret) - goto err_config_cleanup; - /* Try to bind all sub drivers. */ ret = component_bind_all(dev, drm_dev); if (ret) - goto err_iommu_cleanup; + goto err_mode_config_cleanup; - /* init kms poll for handling hpd */ - drm_kms_helper_poll_init(drm_dev); + ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); + if (ret) + goto err_unbind_all; + + drm_mode_config_reset(drm_dev); /* * enable drm irq mode. @@ -158,15 +161,12 @@ static int rockchip_drm_bind(struct device *dev) */ drm_dev->irq_enabled = true; - ret = drm_vblank_init(drm_dev, ROCKCHIP_MAX_CRTC); - if (ret) - goto err_kms_helper_poll_fini; - - drm_mode_config_reset(drm_dev); + /* init kms poll for handling hpd */ + drm_kms_helper_poll_init(drm_dev); ret = rockchip_drm_fbdev_init(drm_dev); if (ret) - goto err_vblank_cleanup; + goto err_kms_helper_poll_fini; ret = drm_dev_register(drm_dev, 0); if (ret) @@ -175,17 +175,17 @@ static int rockchip_drm_bind(struct device *dev) return 0; err_fbdev_fini: rockchip_drm_fbdev_fini(drm_dev); -err_vblank_cleanup: - drm_vblank_cleanup(drm_dev); err_kms_helper_poll_fini: drm_kms_helper_poll_fini(drm_dev); + drm_vblank_cleanup(drm_dev); +err_unbind_all: component_unbind_all(dev, drm_dev); -err_iommu_cleanup: - rockchip_iommu_cleanup(drm_dev); -err_config_cleanup: +err_mode_config_cleanup: drm_mode_config_cleanup(drm_dev); - drm_dev->dev_private = NULL; + rockchip_iommu_cleanup(drm_dev); err_free: + drm_dev->dev_private = NULL; + dev_set_drvdata(dev, NULL); drm_dev_unref(drm_dev); return ret; } @@ -194,16 +194,19 @@ static void rockchip_drm_unbind(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + drm_dev_unregister(drm_dev); + rockchip_drm_fbdev_fini(drm_dev); - drm_vblank_cleanup(drm_dev); drm_kms_helper_poll_fini(drm_dev); + + drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); - rockchip_iommu_cleanup(drm_dev); drm_mode_config_cleanup(drm_dev); + rockchip_iommu_cleanup(drm_dev); + drm_dev->dev_private = NULL; - drm_dev_unregister(drm_dev); - drm_dev_unref(drm_dev); dev_set_drvdata(dev, NULL); + drm_dev_unref(drm_dev); } static void rockchip_drm_lastclose(struct drm_device *dev) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 1/9] drm: bridge: analogix: Detach panel when unbinding analogix dp
The panel is attached when binding analogix dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v3: None Changes in v2: Fix some commit messages. drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index c26997a..28144a1 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1443,6 +1443,8 @@ void analogix_dp_unbind(struct device *dev, struct device *master, if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) DRM_ERROR("failed to turnoff the panel\n"); + if (drm_panel_detach(dp->plat_data->panel)) + DRM_ERROR("failed to detach the panel\n"); } pm_runtime_disable(dev); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/9] drm: bridge: analogix: Detach panel when unbinding analogix dp
The panel is attached when binding analogix dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index e7cd105..a3db290 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1443,6 +1443,8 @@ void analogix_dp_unbind(struct device *dev, struct device *master, if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) DRM_ERROR("failed to turnoff the panel\n"); + if (drm_panel_detach(dp->plat_data->panel)) + DRM_ERROR("failed to detach the panel\n"); } pm_runtime_disable(dev); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/9] drm/rockchip: cdn-dp: Don't try to release firmware when not loaded
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/rockchip/cdn-dp-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index fd79a70..a97f3f4 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1052,6 +1052,7 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) dp->connected = false; dp->active = false; dp->active_port = -1; + dp->fw_loaded = false; INIT_WORK(>event_work, cdn_dp_pd_event_work); @@ -1132,7 +1133,8 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) connector->funcs->destroy(connector); pm_runtime_disable(dev); - release_firmware(dp->fw); + if (dp->fw_loaded) + release_firmware(dp->fw); kfree(dp->edid); dp->edid = NULL; } -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 8/9] drm/rockchip: gem: Don't alloc/free gem buf before drm dev registered
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index df9e570..2bf8024 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -184,6 +184,9 @@ static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj, struct drm_device *drm = obj->dev; struct rockchip_drm_private *private = drm->dev_private; + if (!drm->registered) + return -ENODEV; + if (private->domain) return rockchip_gem_alloc_iommu(rk_obj, alloc_kmap); else @@ -208,6 +211,11 @@ static void rockchip_gem_free_dma(struct rockchip_gem_object *rk_obj) static void rockchip_gem_free_buf(struct rockchip_gem_object *rk_obj) { + struct drm_device *drm = rk_obj->base.dev; + + if (!drm->registered) + return; + if (rk_obj->pages) rockchip_gem_free_iommu(rk_obj); else -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/9] drm: rockchip: Fix rockchip drm unbind crash error
Verified on rk3399 chromebook kevin: 1/ stop ui && pkill -9 frecon 2/ unbind/bind drm Jeffy Chen (9): drm: bridge: analogix: Detach panel when unbinding analogix dp drm: bridge: analogix: Unregister dp aux when unbinding drm: bridge: analogix: Destroy connector when unbinding drm/rockchip: cdn-dp: Don't try to release firmware when not loaded drm/rockchip: vop: Enable pm domain when resetting vop drm/rockchip: Reoder unload sequence drm/rockchip: Force disable all crtc when unload drm/rockchip: gem: Don't alloc/free gem buf before drm dev registered drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 +++ drivers/gpu/drm/rockchip/cdn-dp-core.c | 10 --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 7 +++-- drivers/gpu/drm/rockchip/rockchip_drm_gem.c| 8 ++ drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 31 +++--- 5 files changed, 44 insertions(+), 16 deletions(-) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 5/9] drm/rockchip: vop: Enable pm domain when resetting vop
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 31 +++-- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 76c79ac..1d85319 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1365,6 +1365,12 @@ static int vop_initial(struct vop *vop) return ret; } + ret = pm_runtime_get_sync(vop->dev); + if (ret < 0) { + dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + goto err_put_pm_runtime; + } + /* Enable both the hclk and aclk to setup the vop */ ret = clk_prepare_enable(vop->hclk); if (ret < 0) { @@ -1422,6 +1428,8 @@ static int vop_initial(struct vop *vop) vop->is_enabled = false; + pm_runtime_put_sync(vop->dev); + return 0; err_disable_aclk: @@ -1430,6 +1438,8 @@ static int vop_initial(struct vop *vop) clk_disable_unprepare(vop->hclk); err_unprepare_dclk: clk_unprepare(vop->dclk); +err_put_pm_runtime: + pm_runtime_put_sync(vop->dev); return ret; } @@ -1530,12 +1540,6 @@ static int vop_bind(struct device *dev, struct device *master, void *data) if (!vop->regsbak) return -ENOMEM; - ret = vop_initial(vop); - if (ret < 0) { - dev_err(>dev, "cannot initial vop dev - err %d\n", ret); - return ret; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "cannot find irq for vop\n"); @@ -1556,15 +1560,22 @@ static int vop_bind(struct device *dev, struct device *master, void *data) /* IRQ is initially disabled; it gets enabled in power_on */ disable_irq(vop->irq); + pm_runtime_enable(>dev); + + ret = vop_initial(vop); + if (ret < 0) { + dev_err(>dev, "cannot initial vop dev - err %d\n", ret); + goto err_disable_pm_runtime; + } + ret = vop_create_crtc(vop); if (ret) - goto err_enable_irq; - - pm_runtime_enable(>dev); + goto err_disable_pm_runtime; return 0; -err_enable_irq: +err_disable_pm_runtime: + pm_runtime_disable(>dev); enable_irq(vop->irq); /* To balance out the disable_irq above */ return ret; } -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 7/9] drm/rockchip: Force disable all crtc when unload
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index a5d83cb..5dbf011 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -246,6 +246,7 @@ static void rockchip_drm_unbind(struct device *dev) rockchip_drm_fbdev_fini(drm_dev); drm_kms_helper_poll_fini(drm_dev); + drm_crtc_force_disable_all(drm_dev); drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); drm_mode_config_cleanup(drm_dev); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 2/9] drm: bridge: analogix: Unregister dp aux when unbinding
The dp aux is registered when binding analogix dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index a3db290..ec47fc2 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1447,6 +1447,7 @@ void analogix_dp_unbind(struct device *dev, struct device *master, DRM_ERROR("failed to detach the panel\n"); } + drm_dp_aux_unregister(>aux); pm_runtime_disable(dev); } EXPORT_SYMBOL_GPL(analogix_dp_unbind); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/9] drm: bridge: analogix: Destroy connector when unbinding
Normally we do this in drm_mode_config_cleanup. But analogix dp's connector is allocated when binding, and would be freed after unbind. So we need to destroy it when unbinding, to avoid further access. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index ec47fc2..084ee8f 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1439,6 +1439,7 @@ void analogix_dp_unbind(struct device *dev, struct device *master, struct analogix_dp_device *dp = dev_get_drvdata(dev); analogix_dp_bridge_disable(dp->bridge); + dp->connector.funcs->destroy(>connector); if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 9/9] drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding
In current sound framework, there's no way to unbind dai link after unregister codec. So don't unregister the codec when unbinding for now. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/rockchip/cdn-dp-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index a97f3f4..1deab9f 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1091,8 +1091,6 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) goto err_free_connector; } - cdn_dp_audio_codec_init(dp, dev); - for (i = 0; i < dp->ports; i++) { port = dp->port[i]; @@ -1127,7 +1125,6 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) struct drm_connector *connector = >connector; cancel_work_sync(>event_work); - platform_device_unregister(dp->audio_pdev); cdn_dp_encoder_disable(encoder); encoder->funcs->destroy(encoder); connector->funcs->destroy(connector); @@ -1220,6 +1217,8 @@ static int cdn_dp_probe(struct platform_device *pdev) mutex_init(>lock); dev_set_drvdata(dev, dp); + cdn_dp_audio_codec_init(dp, dev); + return component_add(dev, _dp_component_ops); } @@ -1227,6 +1226,7 @@ static int cdn_dp_remove(struct platform_device *pdev) { struct cdn_dp_device *dp = platform_get_drvdata(pdev); + platform_device_unregister(dp->audio_pdev); cdn_dp_suspend(dp->dev); component_del(>dev, _dp_component_ops); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 7/9] drm/rockchip: Force disable all crtc when unload
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: None drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index a5d83cb..5dbf011 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -246,6 +246,7 @@ static void rockchip_drm_unbind(struct device *dev) rockchip_drm_fbdev_fini(drm_dev); drm_kms_helper_poll_fini(drm_dev); + drm_crtc_force_disable_all(drm_dev); drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); drm_mode_config_cleanup(drm_dev); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/9] drm/rockchip: vop: Enable pm domain when resetting vop
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 31 +++-- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 76c79ac..1d85319 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1365,6 +1365,12 @@ static int vop_initial(struct vop *vop) return ret; } + ret = pm_runtime_get_sync(vop->dev); + if (ret < 0) { + dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + goto err_put_pm_runtime; + } + /* Enable both the hclk and aclk to setup the vop */ ret = clk_prepare_enable(vop->hclk); if (ret < 0) { @@ -1422,6 +1428,8 @@ static int vop_initial(struct vop *vop) vop->is_enabled = false; + pm_runtime_put_sync(vop->dev); + return 0; err_disable_aclk: @@ -1430,6 +1438,8 @@ static int vop_initial(struct vop *vop) clk_disable_unprepare(vop->hclk); err_unprepare_dclk: clk_unprepare(vop->dclk); +err_put_pm_runtime: + pm_runtime_put_sync(vop->dev); return ret; } @@ -1530,12 +1540,6 @@ static int vop_bind(struct device *dev, struct device *master, void *data) if (!vop->regsbak) return -ENOMEM; - ret = vop_initial(vop); - if (ret < 0) { - dev_err(>dev, "cannot initial vop dev - err %d\n", ret); - return ret; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "cannot find irq for vop\n"); @@ -1556,15 +1560,22 @@ static int vop_bind(struct device *dev, struct device *master, void *data) /* IRQ is initially disabled; it gets enabled in power_on */ disable_irq(vop->irq); + pm_runtime_enable(>dev); + + ret = vop_initial(vop); + if (ret < 0) { + dev_err(>dev, "cannot initial vop dev - err %d\n", ret); + goto err_disable_pm_runtime; + } + ret = vop_create_crtc(vop); if (ret) - goto err_enable_irq; - - pm_runtime_enable(>dev); + goto err_disable_pm_runtime; return 0; -err_enable_irq: +err_disable_pm_runtime: + pm_runtime_disable(>dev); enable_irq(vop->irq); /* To balance out the disable_irq above */ return ret; } -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 0/9] drm: rockchip: Fix rockchip drm unbind crash error
Verified on rk3399 chromebook kevin: 1/ stop ui && pkill -9 frecon 2/ unbind/bind drm Changes in v2: Fix some commit messages. Jeffy Chen (9): drm: bridge: analogix: Detach panel when unbinding analogix dp drm: bridge: analogix: Unregister dp aux when unbinding drm: bridge: analogix: Destroy connector when unbinding drm/rockchip: cdn-dp: Don't try to release firmware when not loaded drm/rockchip: vop: Enable pm domain when resetting vop drm/rockchip: Reoder unload sequence drm/rockchip: Force disable all crtc when unload drm/rockchip: gem: Don't alloc/free gem buf before drm dev registered drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 +++ drivers/gpu/drm/rockchip/cdn-dp-core.c | 10 --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 7 +++-- drivers/gpu/drm/rockchip/rockchip_drm_gem.c| 8 ++ drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 31 +++--- 5 files changed, 44 insertions(+), 16 deletions(-) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 3/9] drm: bridge: analogix: Destroy connector when unbinding
Normally we do this in drm_mode_config_cleanup. But analogix dp's connector is allocated in bind, and freed after unbind. So we need to destroy it in unbind to avoid further access. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index ec47fc2..084ee8f 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1439,6 +1439,7 @@ void analogix_dp_unbind(struct device *dev, struct device *master, struct analogix_dp_device *dp = dev_get_drvdata(dev); analogix_dp_bridge_disable(dp->bridge); + dp->connector.funcs->destroy(>connector); if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/9] drm: bridge: analogix: Unregister dp aux when unbinding
The dp aux is registered when binding analogix dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index a3db290..ec47fc2 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1447,6 +1447,7 @@ void analogix_dp_unbind(struct device *dev, struct device *master, DRM_ERROR("failed to detach the panel\n"); } + drm_dp_aux_unregister(>aux); pm_runtime_disable(dev); } EXPORT_SYMBOL_GPL(analogix_dp_unbind); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 1/9] drm: bridge: analogix: Detach panel when unbinding analogix dp
The panel is attached when binding analogix dp. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: Fix some commit messages. drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index e7cd105..a3db290 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1443,6 +1443,8 @@ void analogix_dp_unbind(struct device *dev, struct device *master, if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) DRM_ERROR("failed to turnoff the panel\n"); + if (drm_panel_detach(dp->plat_data->panel)) + DRM_ERROR("failed to detach the panel\n"); } pm_runtime_disable(dev); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 9/9] drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding
In current sound framework, there's no way to unbind dai link after unregister codec. So move unregister codec to driver remove for now. Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com> --- Changes in v2: None drivers/gpu/drm/rockchip/cdn-dp-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index a97f3f4..1deab9f 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1091,8 +1091,6 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) goto err_free_connector; } - cdn_dp_audio_codec_init(dp, dev); - for (i = 0; i < dp->ports; i++) { port = dp->port[i]; @@ -1127,7 +1125,6 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) struct drm_connector *connector = >connector; cancel_work_sync(>event_work); - platform_device_unregister(dp->audio_pdev); cdn_dp_encoder_disable(encoder); encoder->funcs->destroy(encoder); connector->funcs->destroy(connector); @@ -1220,6 +1217,8 @@ static int cdn_dp_probe(struct platform_device *pdev) mutex_init(>lock); dev_set_drvdata(dev, dp); + cdn_dp_audio_codec_init(dp, dev); + return component_add(dev, _dp_component_ops); } @@ -1227,6 +1226,7 @@ static int cdn_dp_remove(struct platform_device *pdev) { struct cdn_dp_device *dp = platform_get_drvdata(pdev); + platform_device_unregister(dp->audio_pdev); cdn_dp_suspend(dp->dev); component_del(>dev, _dp_component_ops); -- 2.1.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel