From 5ead424137e896147d03ed5592c708ad37604d9e Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Mon, 21 Mar 2022 11:43:13 +0800 Subject: [PATCH] video: rockchip: mpp: Fix av1d reset failed issue Signed-off-by: Yandong Lin Change-Id: Icab414d04ae6e13c95e62d4c44a4ef50dc23d309 --- drivers/video/rockchip/mpp/mpp_av1dec.c | 22 +++++++++++--------- drivers/video/rockchip/mpp/mpp_iommu.c | 10 +++++++-- drivers/video/rockchip/mpp/mpp_iommu.h | 4 +++- drivers/video/rockchip/mpp/mpp_iommu_av1d.c | 23 +++++++++++++++++++++ 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_av1dec.c b/drivers/video/rockchip/mpp/mpp_av1dec.c index cb7e9e4f6a36..dd38e0134b06 100644 --- a/drivers/video/rockchip/mpp/mpp_av1dec.c +++ b/drivers/video/rockchip/mpp/mpp_av1dec.c @@ -529,17 +529,19 @@ static int av1dec_set_l2_cache(struct av1dec_dev *dec, struct av1dec_task *task) /* shaper enable */ writel_relaxed(AV1_L2_CACHE_SHAPER_EN, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_SHAPER_CTRL); + + /* TODO: set exception list */ + + /* multi id enable bit */ + writel_relaxed(0x00000001, dec->reg_base[AV1DEC_CLASS_CACHE] + + AV1_L2_CACHE_RD_ONLY_CONFIG); + /* reorder_e and cache_e */ + writel_relaxed(0x00000081, dec->reg_base[AV1DEC_CLASS_CACHE] + + AV1_L2_CACHE_RD_ONLY_CTRL); + /* wmb */ + wmb(); } - /* TODO: set exception list */ - - /* multi id enable bit */ - writel_relaxed(0x00000001, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_RD_ONLY_CONFIG); - /* reorder_e and cache_e */ - writel_relaxed(0x00000081, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_RD_ONLY_CTRL); - /* wmb */ - wmb(); - return 0; } #define REG_CONTROL 0x20 @@ -1272,7 +1274,7 @@ static int av1dec_probe(struct platform_device *pdev) /* iommu may disabled */ if (mpp->iommu_info) - mpp->iommu_info->skip_refresh = 1; + mpp->iommu_info->av1d_iommu = 1; dec->reg_base[AV1DEC_CLASS_VCD] = mpp->reg_base; ret = devm_request_threaded_irq(dev, mpp->irq, diff --git a/drivers/video/rockchip/mpp/mpp_iommu.c b/drivers/video/rockchip/mpp/mpp_iommu.c index 876e22686d89..97a2445e2202 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.c +++ b/drivers/video/rockchip/mpp/mpp_iommu.c @@ -469,9 +469,15 @@ int mpp_iommu_refresh(struct mpp_iommu_info *info, struct device *dev) { int ret; - if (!info || info->skip_refresh) + if (!info) return 0; - + /* call av1 iommu ops */ + if (IS_ENABLED(CONFIG_ROCKCHIP_MPP_AV1DEC) && info->av1d_iommu) { + ret = mpp_av1_iommu_disable(dev); + if (ret) + return ret; + return mpp_av1_iommu_enable(dev); + } /* disable iommu */ ret = rockchip_iommu_disable(dev); if (ret) diff --git a/drivers/video/rockchip/mpp/mpp_iommu.h b/drivers/video/rockchip/mpp/mpp_iommu.h index 34ff97a92ec2..0be63b2a8502 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.h +++ b/drivers/video/rockchip/mpp/mpp_iommu.h @@ -73,7 +73,7 @@ struct mpp_iommu_info { struct iommu_group *group; struct mpp_rk_iommu *iommu; iommu_fault_handler_t hdl; - u32 skip_refresh; + u32 av1d_iommu; }; struct mpp_dma_session * @@ -105,6 +105,8 @@ int mpp_iommu_detach(struct mpp_iommu_info *info); int mpp_iommu_refresh(struct mpp_iommu_info *info, struct device *dev); int mpp_iommu_flush_tlb(struct mpp_iommu_info *info); +int mpp_av1_iommu_disable(struct device *dev); +int mpp_av1_iommu_enable(struct device *dev); static inline int mpp_iommu_down_read(struct mpp_iommu_info *info) { diff --git a/drivers/video/rockchip/mpp/mpp_iommu_av1d.c b/drivers/video/rockchip/mpp/mpp_iommu_av1d.c index e09ce4cdf96a..9d21cb7874b5 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu_av1d.c +++ b/drivers/video/rockchip/mpp/mpp_iommu_av1d.c @@ -31,6 +31,7 @@ #include #include "mpp_debug.h" #include "mpp_common.h" +#include "mpp_iommu.h" struct av1_iommu_domain { struct list_head iommus; @@ -196,6 +197,18 @@ static void av1_iommu_disable(struct av1_iommu *iommu) clk_bulk_disable(iommu->num_clocks, iommu->clocks); } +int mpp_av1_iommu_disable(struct device *dev) +{ + struct av1_iommu *iommu = av1_iommu_from_dev(dev); + + if (!iommu->domain) + return 0; + + av1_iommu_disable(iommu); + + return 0; +} + static int av1_iommu_enable(struct av1_iommu *iommu) { struct iommu_domain *domain = iommu->domain; @@ -221,6 +234,16 @@ static int av1_iommu_enable(struct av1_iommu *iommu) return ret; } +int mpp_av1_iommu_enable(struct device *dev) +{ + struct av1_iommu *iommu = av1_iommu_from_dev(dev); + + if (!iommu->domain) + return 0; + + return av1_iommu_enable(iommu); +} + static inline void av1_table_flush(struct av1_iommu_domain *dom, dma_addr_t dma, unsigned int count) {