From 36323c448136ecbc9f3b51e64264a84781fe14fe Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Tue, 5 Aug 2025 14:45:59 +0800 Subject: [PATCH] media: i2c: rk628: fix release resources when remove Signed-off-by: Jianwei Fan Change-Id: Ie4264548e56ea7d718ed87c5648e15d2481d9336 --- drivers/media/i2c/rk628/rk628_bt1120_v4l2.c | 35 +++++++++++------- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 41 ++++++++++++--------- drivers/media/i2c/rk628/rk628_hdmirx.c | 1 + 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c index 637028a2cf59..bb0c22f871f8 100644 --- a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c @@ -2182,33 +2182,40 @@ power_off: static void rk628_bt1120_remove(struct i2c_client *client) { - struct rk628_bt1120 *bt1120 = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct rk628_bt1120 *bt1120 = to_bt1120(sd); + + if (bt1120->hdmirx_irq) + disable_irq(bt1120->hdmirx_irq); + if (bt1120->plugin_irq) + disable_irq(bt1120->plugin_irq); - rk628_debugfs_remove(bt1120->rk628); if (!bt1120->hdmirx_irq) { del_timer_sync(&bt1120->timer); flush_work(&bt1120->work_i2c_poll); } - if (bt1120->cec_enable && bt1120->cec) - rk628_hdmirx_cec_unregister(bt1120->cec); - cancel_delayed_work_sync(&bt1120->delayed_work_enable_hotplug); cancel_delayed_work_sync(&bt1120->delayed_work_res_change); rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true); - rk628_hdmirx_audio_cancel_work_rate_change(bt1120->audio_info, true); + if (bt1120->rk628->version < RK628F_VERSION) + rk628_hdmirx_audio_cancel_work_rate_change(bt1120->audio_info, true); + rk628_hdmirx_hpd_ctrl(sd, false); - if (bt1120->rxphy_pwron) - rk628_rxphy_power_off(bt1120->rk628); + if (bt1120->cec_enable && bt1120->cec) + rk628_hdmirx_cec_unregister(bt1120->cec); + + rk628_debugfs_remove(bt1120->rk628); + rk628_hdmirx_audio_destroy(bt1120->audio_info); + + v4l2_async_unregister_subdev(sd); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif + v4l2_ctrl_handler_free(&bt1120->hdl); mutex_destroy(&bt1120->confctl_mutex); - rk628_control_assert(bt1120->rk628, RGU_HDMIRX); - rk628_control_assert(bt1120->rk628, RGU_HDMIRX_PON); - rk628_control_assert(bt1120->rk628, RGU_DECODER); - rk628_control_assert(bt1120->rk628, RGU_CLK_RX); - rk628_control_assert(bt1120->rk628, RGU_VOP); - rk628_control_assert(bt1120->rk628, RGU_BT1120DEC); rk628_bt1120_power_off(bt1120); } diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index f424a3cec945..c320465737b0 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -3767,37 +3767,42 @@ static void rk628_csi_remove(struct i2c_client *client) static int rk628_csi_remove(struct i2c_client *client) #endif { - struct rk628_csi *csi = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct rk628_csi *csi = to_csi(sd); + + if (csi->hdmirx_irq) + disable_irq(csi->hdmirx_irq); + if (csi->plugin_irq) + disable_irq(csi->plugin_irq); - rk628_debugfs_remove(csi->rk628); if (!csi->hdmirx_irq) { del_timer_sync(&csi->timer); flush_work(&csi->work_i2c_poll); } + cancel_delayed_work_sync(&csi->delayed_work_enable_hotplug); + cancel_delayed_work_sync(&csi->delayed_work_res_change); + rk628_hdmirx_audio_cancel_work_audio(csi->audio_info, true); + if (csi->rk628->version < RK628F_VERSION) + rk628_hdmirx_audio_cancel_work_rate_change(csi->audio_info, true); + rk628_hdmirx_hpd_ctrl(sd, false); if (csi->cec_enable && csi->cec) rk628_hdmirx_cec_unregister(csi->cec); - rk628_hdmirx_audio_cancel_work_audio(csi->audio_info, true); - rk628_hdmirx_audio_cancel_work_rate_change(csi->audio_info, true); - cancel_delayed_work_sync(&csi->delayed_work_enable_hotplug); - cancel_delayed_work_sync(&csi->delayed_work_res_change); + rk628_debugfs_remove(csi->rk628); + rk628_hdmirx_audio_destroy(csi->audio_info); - if (csi->rxphy_pwron) - rk628_rxphy_power_off(csi->rk628); - if (csi->txphy_pwron) - mipi_dphy_power_off(csi); + v4l2_async_unregister_subdev(sd); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif + v4l2_ctrl_handler_free(&csi->hdl); + + if (csi->classdev) + device_destroy(rk_hdmirx_class(), MKDEV(0, 0)); mutex_destroy(&csi->confctl_mutex); - rk628_control_assert(csi->rk628, RGU_HDMIRX); - rk628_control_assert(csi->rk628, RGU_HDMIRX_PON); - rk628_control_assert(csi->rk628, RGU_DECODER); - rk628_control_assert(csi->rk628, RGU_CLK_RX); - rk628_control_assert(csi->rk628, RGU_VOP); - rk628_control_assert(csi->rk628, RGU_CSI); - if (csi->rk628->version >= RK628F_VERSION) - rk628_control_assert(csi->rk628, RGU_CSI1); rk628_csi_power_off(csi); #if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE return 0; diff --git a/drivers/media/i2c/rk628/rk628_hdmirx.c b/drivers/media/i2c/rk628/rk628_hdmirx.c index ece94b9ea381..9c48ab6257fd 100644 --- a/drivers/media/i2c/rk628/rk628_hdmirx.c +++ b/drivers/media/i2c/rk628/rk628_hdmirx.c @@ -1373,6 +1373,7 @@ void rk628_hdmirx_cec_unregister(struct rk628_hdmirx_cec *cec) if (!cec) return; + cancel_delayed_work_sync(&cec->delayed_work_cec); cec_notifier_cec_adap_unregister(cec->notify, cec->adap); cec_unregister_adapter(cec->adap); }