From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sat, 23 May 2020 10:16:01 +0000 Subject: WIP: media: rkvdec: pm runtime dont use autosuspend before disable and cleanup Signed-off-by: Jonas Karlman --- drivers/staging/media/rkvdec/rkvdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c index 111111111111..222222222222 100644 --- a/drivers/staging/media/rkvdec/rkvdec.c +++ b/drivers/staging/media/rkvdec/rkvdec.c @@ -1176,9 +1176,9 @@ static void rkvdec_remove(struct platform_device *pdev) cancel_delayed_work_sync(&rkvdec->watchdog_work); - rkvdec_v4l2_cleanup(rkvdec); - pm_runtime_disable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_disable(&pdev->dev); + rkvdec_v4l2_cleanup(rkvdec); } #ifdef CONFIG_PM -- Armbian From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Randy Li Date: Sun, 6 Jan 2019 01:48:37 +0800 Subject: soc: rockchip: power-domain: export idle request We need to put the power status of HEVC IP into IDLE unless we can't reset that IP or the SoC would crash down. rockchip_pmu_idle_request(dev, true)---> enter idle rockchip_pmu_idle_request(dev, false)---> exit idle Signed-off-by: Caesar Wang Signed-off-by: Jeffy Chen Signed-off-by: Randy Li --- drivers/pmdomain/rockchip/pm-domains.c | 23 ++++++++++ include/linux/rockchip_pmu.h | 15 ++++++ include/soc/rockchip/pm_domains.h | 6 +++ 3 files changed, 44 insertions(+) diff --git a/drivers/pmdomain/rockchip/pm-domains.c b/drivers/pmdomain/rockchip/pm-domains.c index 111111111111..222222222222 100644 --- a/drivers/pmdomain/rockchip/pm-domains.c +++ b/drivers/pmdomain/rockchip/pm-domains.c @@ -417,6 +417,29 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, return 0; } +int rockchip_pmu_idle_request(struct device *dev, bool idle) +{ + struct generic_pm_domain *genpd; + struct rockchip_pm_domain *pd; + int ret; + + if (IS_ERR_OR_NULL(dev)) + return -EINVAL; + + if (IS_ERR_OR_NULL(dev->pm_domain)) + return -EINVAL; + + genpd = pd_to_genpd(dev->pm_domain); + pd = to_rockchip_pd(genpd); + + mutex_lock(&pd->pmu->mutex); + ret = rockchip_pmu_set_idle_request(pd, idle); + mutex_unlock(&pd->pmu->mutex); + + return ret; +} +EXPORT_SYMBOL(rockchip_pmu_idle_request); + static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd) { int i; diff --git a/include/linux/rockchip_pmu.h b/include/linux/rockchip_pmu.h new file mode 100644 index 000000000000..111111111111 --- /dev/null +++ b/include/linux/rockchip_pmu.h @@ -0,0 +1,15 @@ +/* + * pm_domain.h - Definitions and headers related to device power domains. + * + * Copyright (C) 2017 Randy Li . + * + * This file is released under the GPLv2. + */ + +#ifndef _LINUX_ROCKCHIP_PM_H +#define _LINUX_ROCKCHIP_PM_H +#include + +int rockchip_pmu_idle_request(struct device *dev, bool idle); + +#endif /* _LINUX_ROCKCHIP_PM_H */ diff --git a/include/soc/rockchip/pm_domains.h b/include/soc/rockchip/pm_domains.h index 111111111111..222222222222 100644 --- a/include/soc/rockchip/pm_domains.h +++ b/include/soc/rockchip/pm_domains.h @@ -10,6 +10,7 @@ int rockchip_pmu_block(void); void rockchip_pmu_unblock(void); +int rockchip_pmu_idle_request(struct device *dev, bool idle); #else /* CONFIG_ROCKCHIP_PM_DOMAINS */ @@ -20,6 +21,11 @@ static inline int rockchip_pmu_block(void) static inline void rockchip_pmu_unblock(void) { } +static inline int rockchip_pmu_idle_request(struct device *dev, bool idle) +{ + return -ENOTSUPP; +} + #endif /* CONFIG_ROCKCHIP_PM_DOMAINS */ #endif /* __SOC_ROCKCHIP_PM_DOMAINS_H__ */ -- Armbian From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alex Bee Date: Wed, 20 May 2020 17:04:47 +0200 Subject: WIP: media: rkvdec: implement reset controls --- Documentation/devicetree/bindings/media/rockchip,vdec.yaml | 19 ++++ drivers/staging/media/rkvdec/rkvdec-regs.h | 5 + drivers/staging/media/rkvdec/rkvdec.c | 53 ++++++++++ drivers/staging/media/rkvdec/rkvdec.h | 11 +- 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml index 111111111111..222222222222 100644 --- a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml +++ b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml @@ -53,6 +53,18 @@ properties: iommus: maxItems: 1 + resets: + maxItems: 6 + + reset-names: + items: + - const: video_h + - const: video_a + - const: video_core + - const: video_cabac + - const: niu_a + - const: niu_h + required: - compatible - reg @@ -60,6 +72,8 @@ required: - clocks - clock-names - power-domains + - resets + - reset-names additionalProperties: false @@ -78,6 +92,11 @@ examples: clock-names = "axi", "ahb", "cabac", "core"; power-domains = <&power RK3399_PD_VDU>; iommus = <&vdec_mmu>; + resets = <&cru SRST_H_VDU>, <&cru SRST_A_VDU>, + <&cru SRST_VDU_CORE>, <&cru SRST_VDU_CA>, + <&cru SRST_A_VDU_NOC>, <&cru SRST_H_VDU_NOC>; + reset-names = "video_h", "video_a", "video_core", "video_cabac", + "niu_a", "niu_h"; }; ... diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h index 111111111111..222222222222 100644 --- a/drivers/staging/media/rkvdec/rkvdec-regs.h +++ b/drivers/staging/media/rkvdec/rkvdec-regs.h @@ -28,6 +28,11 @@ #define RKVDEC_SOFTRST_EN_P BIT(20) #define RKVDEC_FORCE_SOFTRESET_VALID BIT(21) #define RKVDEC_SOFTRESET_RDY BIT(22) +#define RKVDEC_ERR_MASK (RKVDEC_BUS_STA \ + | RKVDEC_ERR_STA \ + | RKVDEC_TIMEOUT_STA \ + | RKVDEC_BUF_EMPTY_STA \ + | RKVDEC_COLMV_REF_ERR_STA ) #define RKVDEC_REG_SYSCTRL 0x008 #define RKVDEC_IN_ENDIAN BIT(0) diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c index 111111111111..222222222222 100644 --- a/drivers/staging/media/rkvdec/rkvdec.c +++ b/drivers/staging/media/rkvdec/rkvdec.c @@ -10,12 +10,15 @@ */ #include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -766,6 +769,11 @@ static void rkvdec_job_finish(struct rkvdec_ctx *ctx, pm_runtime_mark_last_busy(rkvdec->dev); pm_runtime_put_autosuspend(rkvdec->dev); + + if (result == VB2_BUF_STATE_ERROR && + rkvdec->reset_mask == RESET_NONE) + rkvdec->reset_mask |= RESET_SOFT; + rkvdec_job_finish_no_pm(ctx, result); } @@ -803,6 +811,33 @@ static void rkvdec_device_run(void *priv) if (WARN_ON(!desc)) return; + if (rkvdec->reset_mask != RESET_NONE) { + + if (rkvdec->reset_mask & RESET_SOFT) { + writel(RKVDEC_SOFTRST_EN_P, + rkvdec->regs + RKVDEC_REG_INTERRUPT); + udelay(RKVDEC_RESET_DELAY); + if (readl(rkvdec->regs + RKVDEC_REG_INTERRUPT) + & RKVDEC_SOFTRESET_RDY) + dev_info_ratelimited(rkvdec->dev, + "softreset failed\n"); + } + + if (rkvdec->reset_mask & RESET_HARD) { + rockchip_pmu_idle_request(rkvdec->dev, true); + ret = reset_control_assert(rkvdec->rstc); + if (!ret) { + udelay(RKVDEC_RESET_DELAY); + ret = reset_control_deassert(rkvdec->rstc); + } + rockchip_pmu_idle_request(rkvdec->dev, false); + if (ret) + dev_notice_ratelimited(rkvdec->dev, + "hardreset failed\n"); + } + rkvdec->reset_mask = RESET_NONE; + pm_runtime_suspend(rkvdec->dev); + } ret = pm_runtime_resume_and_get(rkvdec->dev); if (ret < 0) { @@ -1069,6 +1104,11 @@ static irqreturn_t rkvdec_irq_handler(int irq, void *priv) if (cancel_delayed_work(&rkvdec->watchdog_work)) { struct rkvdec_ctx *ctx; + if (state == VB2_BUF_STATE_ERROR) { + rkvdec->reset_mask |= (status & RKVDEC_ERR_MASK) ? + RESET_HARD : RESET_SOFT; + } + ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); rkvdec_job_finish(ctx, state); } @@ -1086,6 +1126,7 @@ static void rkvdec_watchdog_func(struct work_struct *work) ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev); if (ctx) { dev_err(rkvdec->dev, "Frame processing timed out!\n"); + rkvdec->reset_mask |= RESET_HARD; writel(RKVDEC_IRQ_DIS, rkvdec->regs + RKVDEC_REG_INTERRUPT); writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL); rkvdec_job_finish(ctx, VB2_BUF_STATE_ERROR); @@ -1154,6 +1195,18 @@ static int rkvdec_probe(struct platform_device *pdev) return ret; } + + rkvdec->rstc = devm_reset_control_array_get_optional_exclusive(&pdev->dev); + if (IS_ERR(rkvdec->rstc)) { + dev_err(&pdev->dev, + "get resets failed %ld\n", PTR_ERR(rkvdec->rstc)); + return PTR_ERR(rkvdec->rstc); + } else { + dev_dbg(&pdev->dev, + "requested %d resets\n", + reset_control_get_count(&pdev->dev)); + } + pm_runtime_set_autosuspend_delay(&pdev->dev, 100); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h index 111111111111..222222222222 100644 --- a/drivers/staging/media/rkvdec/rkvdec.h +++ b/drivers/staging/media/rkvdec/rkvdec.h @@ -11,10 +11,11 @@ #ifndef RKVDEC_H_ #define RKVDEC_H_ +#include #include +#include #include #include -#include #include #include @@ -22,6 +23,12 @@ #include #include +#define RESET_NONE 0 +#define RESET_SOFT BIT(0) +#define RESET_HARD BIT(1) + +#define RKVDEC_RESET_DELAY 5 + struct rkvdec_ctx; struct rkvdec_ctrl_desc { @@ -110,6 +117,8 @@ struct rkvdec_dev { void __iomem *regs; struct mutex vdev_lock; /* serializes ioctls */ struct delayed_work watchdog_work; + struct reset_control *rstc; + u8 reset_mask; }; struct rkvdec_ctx { -- Armbian From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alex Bee Date: Sat, 21 Aug 2021 16:12:36 +0200 Subject: media: hantro: rockchip: Increase RK3288's max ACLK Required to proper decode H.264@4K Signed-off-by: Alex Bee --- drivers/media/platform/verisilicon/rockchip_vpu_hw.c | 14 ++++++++-- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c index 111111111111..222222222222 100644 --- a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c +++ b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c @@ -16,7 +16,8 @@ #include "rockchip_vpu981_regs.h" #define RK3066_ACLK_MAX_FREQ (300 * 1000 * 1000) -#define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000) +#define RK3288_ACLK_MAX_FREQ (600 * 1000 * 1000) +#define RK3399_ACLK_MAX_FREQ (400 * 1000 * 1000) #define RK3588_ACLK_MAX_FREQ (300 * 1000 * 1000) #define ROCKCHIP_VPU981_MIN_SIZE 64 @@ -461,13 +462,20 @@ static int rk3588_vpu981_hw_init(struct hantro_dev *vpu) return 0; } -static int rockchip_vpu_hw_init(struct hantro_dev *vpu) +static int rk3288_vpu_hw_init(struct hantro_dev *vpu) { /* Bump ACLK to max. possible freq. to improve performance. */ clk_set_rate(vpu->clocks[0].clk, RK3288_ACLK_MAX_FREQ); return 0; } +static int rockchip_vpu_hw_init(struct hantro_dev *vpu) +{ + /* Bump ACLK to max. possible freq. to improve performance. */ + clk_set_rate(vpu->clocks[0].clk, RK3399_ACLK_MAX_FREQ); + return 0; +} + static void rk3066_vpu_dec_reset(struct hantro_ctx *ctx) { struct hantro_dev *vpu = ctx->dev; @@ -723,7 +731,7 @@ const struct hantro_variant rk3288_vpu_variant = { .codec_ops = rk3288_vpu_codec_ops, .irqs = rockchip_vpu1_irqs, .num_irqs = ARRAY_SIZE(rockchip_vpu1_irqs), - .init = rockchip_vpu_hw_init, + .init = rk3288_vpu_hw_init, .clk_names = rockchip_vpu_clk_names, .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names) }; -- Armbian From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alex Bee Date: Sun, 4 Jul 2021 15:19:44 +0200 Subject: media: rkvdec: disable QoS for VP9 (corruptions on RK3328 otherwise) Signed-off-by: Alex Bee --- drivers/staging/media/rkvdec/rkvdec-regs.h | 2 ++ drivers/staging/media/rkvdec/rkvdec-vp9.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h index 111111111111..222222222222 100644 --- a/drivers/staging/media/rkvdec/rkvdec-regs.h +++ b/drivers/staging/media/rkvdec/rkvdec-regs.h @@ -222,6 +222,8 @@ #define RKVDEC_REG_H264_ERR_E 0x134 #define RKVDEC_H264_ERR_EN_HIGHBITS(x) ((x) & 0x3fffffff) +#define RKVDEC_QOS_CTRL 0x18C + #define RKVDEC_REG_PREF_LUMA_CACHE_COMMAND 0x410 #define RKVDEC_REG_PREF_CHR_CACHE_COMMAND 0x450 diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c index 111111111111..222222222222 100644 --- a/drivers/staging/media/rkvdec/rkvdec-vp9.c +++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c @@ -803,6 +803,7 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx) struct rkvdec_dev *rkvdec = ctx->dev; struct rkvdec_vp9_run run = { }; int ret; + u32 reg; ret = rkvdec_vp9_run_preamble(ctx, &run); if (ret) { @@ -824,6 +825,13 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx) writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); + + /* disable QOS for RK3328 - no effect on other SoCs */ + reg = readl(rkvdec->regs + RKVDEC_QOS_CTRL); + reg |= 0xFFFF; + reg &= (~BIT(12)); + writel(reg, rkvdec->regs + RKVDEC_QOS_CTRL); + /* Start decoding! */ writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E | RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E, -- Armbian From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alex Bee Date: Thu, 16 Jun 2022 13:18:22 +0200 Subject: WIP: arm64: dts: add resets to vdec for RK3328 --- arch/arm64/boot/dts/rockchip/rk3328.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -705,6 +705,11 @@ vdec: video-codec@ff360000 { assigned-clocks = <&cru ACLK_RKVDEC>, <&cru SCLK_VDEC_CABAC>, <&cru SCLK_VDEC_CORE>; assigned-clock-rates = <400000000>, <400000000>, <300000000>; + resets = <&cru SRST_VDEC_H>, <&cru SRST_VDEC_A>, + <&cru SRST_VDEC_CORE>, <&cru SRST_VDEC_CABAC>, + <&cru SRST_VDEC_NIU_A>, <&cru SRST_VDEC_NIU_H>; + reset-names = "video_h", "video_a", "video_core", "video_cabac", + "niu_a", "niu_h"; iommus = <&vdec_mmu>; power-domains = <&power RK3328_PD_VIDEO>; }; -- Armbian