From bd678582621d8450797f910fead8f47f87604466 Mon Sep 17 00:00:00 2001 From: Chandler Chen Date: Thu, 29 Dec 2022 18:09:48 +0800 Subject: [PATCH] video: rockchip: mpp: workaround for rk3036 hevc & vdpu combo Signed-off-by: Chandler Chen Change-Id: I42844249859f3a3dad8013f6ca7dc0f4e9a4e743 --- drivers/video/rockchip/mpp/mpp_common.c | 1 + drivers/video/rockchip/mpp/mpp_common.h | 1 + drivers/video/rockchip/mpp/mpp_rkvdec.c | 74 +++++++++++++++++++++++++ drivers/video/rockchip/mpp/mpp_vdpu1.c | 73 ++++++++++++++++++++++++ 4 files changed, 149 insertions(+) diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index e7c7e50a994c..200b78e76114 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -1029,6 +1029,7 @@ struct mpp_taskqueue *mpp_taskqueue_init(struct device *dev) atomic_set(&queue->reset_request, 0); atomic_set(&queue->detach_count, 0); atomic_set(&queue->task_id, 0); + queue->dev_active_flags = 0; return queue; } diff --git a/drivers/video/rockchip/mpp/mpp_common.h b/drivers/video/rockchip/mpp/mpp_common.h index 4aa35a43752e..3bdde224cdda 100644 --- a/drivers/video/rockchip/mpp/mpp_common.h +++ b/drivers/video/rockchip/mpp/mpp_common.h @@ -540,6 +540,7 @@ struct mpp_taskqueue { unsigned long core_idle; u32 core_id_max; u32 core_count; + unsigned long dev_active_flags; }; struct mpp_reset_group { diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec.c b/drivers/video/rockchip/mpp/mpp_rkvdec.c index bbf1b1e81673..302dd355e508 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec.c @@ -36,6 +36,7 @@ #include "mpp_debug.h" #include "mpp_common.h" #include "mpp_iommu.h" +#include #include "hack/mpp_hack_px30.h" @@ -1280,6 +1281,13 @@ static int rkvdec_px30_init(struct mpp_dev *mpp) return px30_workaround_combo_init(mpp); } +static int rkvdec_3036_init(struct mpp_dev *mpp) +{ + rkvdec_init(mpp); + set_bit(mpp->var->device_type, &mpp->queue->dev_active_flags); + return 0; +} + static int rkvdec_3328_iommu_hdl(struct iommu_domain *iommu, struct device *iommu_dev, unsigned long iova, @@ -1533,6 +1541,47 @@ static int rkvdec_3368_set_grf(struct mpp_dev *mpp) return 0; } +static int rkvdec_3036_set_grf(struct mpp_dev *mpp) +{ + int grf_changed; + struct mpp_dev *loop = NULL, *n; + struct mpp_taskqueue *queue = mpp->queue; + bool pd_is_on; + + grf_changed = mpp_grf_is_changed(mpp->grf_info); + if (grf_changed) { + + /* + * in this case, devices share the queue also share the same pd&clk, + * so use mpp->dev's pd to control all the process is okay + */ + pd_is_on = rockchip_pmu_pd_is_on(mpp->dev); + if (!pd_is_on) + rockchip_pmu_pd_on(mpp->dev); + mpp->hw_ops->clk_on(mpp); + + list_for_each_entry_safe(loop, n, &queue->dev_list, queue_link) { + if (test_bit(loop->var->device_type, &queue->dev_active_flags)) { + if (loop->hw_ops->reset) + loop->hw_ops->reset(loop); + rockchip_iommu_disable(loop->dev); + clear_bit(loop->var->device_type, &queue->dev_active_flags); + } + } + + mpp_set_grf(mpp->grf_info); + rockchip_iommu_enable(mpp->dev); + set_bit(mpp->var->device_type, &queue->dev_active_flags); + + mpp->hw_ops->clk_off(mpp); + if (!pd_is_on) + rockchip_pmu_pd_off(mpp->dev); + } + + + return 0; +} + static int rkvdec_set_freq(struct mpp_dev *mpp, struct mpp_task *mpp_task) { @@ -1708,6 +1757,17 @@ static struct mpp_hw_ops rkvdec_px30_hw_ops = { .set_grf = px30_workaround_combo_switch_grf, }; +static struct mpp_hw_ops rkvdec_3036_hw_ops = { + .init = rkvdec_3036_init, + .clk_on = rkvdec_clk_on, + .clk_off = rkvdec_clk_off, + .get_freq = rkvdec_get_freq, + .set_freq = rkvdec_set_freq, + .reduce_freq = rkvdec_reduce_freq, + .reset = rkvdec_reset, + .set_grf = rkvdec_3036_set_grf, +}; + static struct mpp_hw_ops rkvdec_3399_hw_ops = { .init = rkvdec_init, .clk_on = rkvdec_clk_on, @@ -1798,6 +1858,14 @@ static const struct mpp_dev_var rk_hevcdec_data = { .dev_ops = &rkvdec_v1_dev_ops, }; +static const struct mpp_dev_var rk_hevcdec_3036_data = { + .device_type = MPP_DEVICE_HEVC_DEC, + .hw_info = &rk_hevcdec_hw_info, + .trans_info = rk_hevcdec_trans, + .hw_ops = &rkvdec_3036_hw_ops, + .dev_ops = &rkvdec_v1_dev_ops, +}; + static const struct mpp_dev_var rk_hevcdec_3368_data = { .device_type = MPP_DEVICE_HEVC_DEC, .hw_info = &rk_hevcdec_hw_info, @@ -1857,6 +1925,12 @@ static const struct of_device_id mpp_rkvdec_dt_match[] = { .data = &rk_hevcdec_px30_data, }, #endif +#ifdef CONFIG_CPU_RK3036 + { + .compatible = "rockchip,hevc-decoder-rk3036", + .data = &rk_hevcdec_3036_data, + }, +#endif #ifdef CONFIG_CPU_RK3368 { .compatible = "rockchip,hevc-decoder-rk3368", diff --git a/drivers/video/rockchip/mpp/mpp_vdpu1.c b/drivers/video/rockchip/mpp/mpp_vdpu1.c index 926be9d7834f..1367596e059c 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu1.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu1.c @@ -25,6 +25,7 @@ #include "mpp_debug.h" #include "mpp_common.h" #include "mpp_iommu.h" +#include #define VDPU1_DRIVER_NAME "mpp_vdpu1" @@ -563,6 +564,13 @@ static int vdpu_init(struct mpp_dev *mpp) return 0; } +static int vdpu_3036_init(struct mpp_dev *mpp) +{ + vdpu_init(mpp); + set_bit(mpp->var->device_type, &mpp->queue->dev_active_flags); + return 0; +} + static int vdpu_clk_on(struct mpp_dev *mpp) { struct vdpu_dev *dec = to_vdpu_dev(mpp); @@ -699,6 +707,46 @@ static int vdpu_reset(struct mpp_dev *mpp) return 0; } +static int vdpu_3036_set_grf(struct mpp_dev *mpp) +{ + int grf_changed; + struct mpp_dev *loop = NULL, *n; + struct mpp_taskqueue *queue = mpp->queue; + bool pd_is_on; + + grf_changed = mpp_grf_is_changed(mpp->grf_info); + if (grf_changed) { + + /* + * in this case, devices share the queue also share the same pd&clk, + * so use mpp->dev's pd to control all the process is okay + */ + pd_is_on = rockchip_pmu_pd_is_on(mpp->dev); + if (!pd_is_on) + rockchip_pmu_pd_on(mpp->dev); + mpp->hw_ops->clk_on(mpp); + + list_for_each_entry_safe(loop, n, &queue->dev_list, queue_link) { + if (test_bit(loop->var->device_type, &queue->dev_active_flags)) { + if (loop->hw_ops->reset) + loop->hw_ops->reset(loop); + rockchip_iommu_disable(loop->dev); + clear_bit(loop->var->device_type, &queue->dev_active_flags); + } + } + + mpp_set_grf(mpp->grf_info); + rockchip_iommu_enable(mpp->dev); + set_bit(mpp->var->device_type, &queue->dev_active_flags); + + mpp->hw_ops->clk_off(mpp); + if (!pd_is_on) + rockchip_pmu_pd_off(mpp->dev); + } + + return 0; +} + static struct mpp_hw_ops vdpu_v1_hw_ops = { .init = vdpu_init, .clk_on = vdpu_clk_on, @@ -706,6 +754,17 @@ static struct mpp_hw_ops vdpu_v1_hw_ops = { .set_freq = vdpu_set_freq, .reduce_freq = vdpu_reduce_freq, .reset = vdpu_reset, + .set_grf = vdpu_3036_set_grf, +}; + +static struct mpp_hw_ops vdpu_3036_hw_ops = { + .init = vdpu_3036_init, + .clk_on = vdpu_clk_on, + .clk_off = vdpu_clk_off, + .set_freq = vdpu_set_freq, + .reduce_freq = vdpu_reduce_freq, + .reset = vdpu_reset, + .set_grf = vdpu_3036_set_grf, }; static struct mpp_hw_ops vdpu_3288_hw_ops = { @@ -746,6 +805,14 @@ static const struct mpp_dev_var vdpu_v1_data = { .dev_ops = &vdpu_v1_dev_ops, }; +static const struct mpp_dev_var vdpu_3036_data = { + .device_type = MPP_DEVICE_VDPU1, + .hw_info = &vdpu_v1_hw_info, + .trans_info = vdpu_v1_trans, + .hw_ops = &vdpu_3036_hw_ops, + .dev_ops = &vdpu_v1_dev_ops, +}; + static const struct mpp_dev_var vdpu_3288_data = { .device_type = MPP_DEVICE_VDPU1, .hw_info = &vdpu_v1_hw_info, @@ -781,6 +848,12 @@ static const struct of_device_id mpp_vdpu1_dt_match[] = { .data = &vdpu_3288_data, }, #endif +#ifdef CONFIG_CPU_RK3036 + { + .compatible = "rockchip,vpu-decoder-rk3036", + .data = &vdpu_3036_data, + }, +#endif #ifdef CONFIG_CPU_RK3368 { .compatible = "rockchip,vpu-decoder-rk3368",