diff --git a/drivers/video/rockchip/vcodec/vcodec_hw_info.h b/drivers/video/rockchip/vcodec/vcodec_hw_info.h index cc7d9dbfe434..003ac331050e 100644 --- a/drivers/video/rockchip/vcodec/vcodec_hw_info.h +++ b/drivers/video/rockchip/vcodec/vcodec_hw_info.h @@ -174,6 +174,13 @@ struct vpu_task_info { */ int reg_pps; + /* + * soft reset register + * special register for soft reset + * valid on vpu & vpu2 & rkv + */ + int reg_reset; + /* * decoder pipeline mode register * @@ -200,6 +207,9 @@ struct vpu_task_info { /* task error bit mask for irq register */ u32 error_mask; + /* task reset bit mask for reset register */ + u32 reset_mask; + enum FORMAT_TYPE (*get_fmt)(u32 *regs); }; diff --git a/drivers/video/rockchip/vcodec/vcodec_hw_rkv.h b/drivers/video/rockchip/vcodec/vcodec_hw_rkv.h index 7a9acbc24d72..30e9aea2d866 100644 --- a/drivers/video/rockchip/vcodec/vcodec_hw_rkv.h +++ b/drivers/video/rockchip/vcodec/vcodec_hw_rkv.h @@ -58,6 +58,10 @@ | RKV_DEC_BUFFER_EMPTY_BIT \ | RKV_DEC_COLMV_ERROR_BIT) +/* enable and soft reset register */ +#define RKV_REG_DEC_RESET 1 +#define RKV_REG_DEC_RESET_BIT BIT(20) + static const enum FORMAT_TYPE rkv_dec_fmt_tbl[] = { [0] = FMT_H265D, [1] = FMT_H264D, @@ -80,6 +84,7 @@ static struct vpu_task_info task_rkv[TASK_TYPE_BUTT] = { .reg_len = 0, .reg_dir_mv = 0, .reg_pps = -1, + .reg_reset = -1, .reg_pipe = 0, .enable_mask = 0, .gating_mask = 0, @@ -87,6 +92,7 @@ static struct vpu_task_info task_rkv[TASK_TYPE_BUTT] = { .irq_mask = 0, .ready_mask = 0, .error_mask = 0, + .reset_mask = 0, .get_fmt = NULL, }, { @@ -97,6 +103,7 @@ static struct vpu_task_info task_rkv[TASK_TYPE_BUTT] = { .reg_len = 4, .reg_dir_mv = 52, .reg_pps = 42, + .reg_reset = RKV_REG_DEC_RESET, .reg_pipe = 0, .enable_mask = 0, .gating_mask = RKV_REG_DEC_GATING_BIT, @@ -104,6 +111,7 @@ static struct vpu_task_info task_rkv[TASK_TYPE_BUTT] = { .pipe_mask = 0, .ready_mask = HEVC_READY_BIT, .error_mask = HEVC_DEC_ERR_MASK, + .reset_mask = RKV_REG_DEC_RESET_BIT, .get_fmt = rkv_dec_get_fmt, }, { @@ -113,6 +121,7 @@ static struct vpu_task_info task_rkv[TASK_TYPE_BUTT] = { .reg_len = 0, .reg_dir_mv = 0, .reg_pps = -1, + .reg_reset = -1, .reg_pipe = 0, .enable_mask = 0, .gating_mask = 0, @@ -120,6 +129,7 @@ static struct vpu_task_info task_rkv[TASK_TYPE_BUTT] = { .irq_mask = 0, .ready_mask = 0, .error_mask = 0, + .reset_mask = 0, .get_fmt = NULL, }, { @@ -129,6 +139,7 @@ static struct vpu_task_info task_rkv[TASK_TYPE_BUTT] = { .reg_len = 0, .reg_dir_mv = 0, .reg_pps = -1, + .reg_reset = -1, .reg_pipe = 0, .enable_mask = 0, .gating_mask = 0, @@ -136,6 +147,7 @@ static struct vpu_task_info task_rkv[TASK_TYPE_BUTT] = { .irq_mask = 0, .ready_mask = 0, .error_mask = 0, + .reset_mask = 0, .get_fmt = NULL, },}; diff --git a/drivers/video/rockchip/vcodec/vcodec_hw_vpu.h b/drivers/video/rockchip/vcodec/vcodec_hw_vpu.h index a00c97320911..3b5eeb35c919 100644 --- a/drivers/video/rockchip/vcodec/vcodec_hw_vpu.h +++ b/drivers/video/rockchip/vcodec/vcodec_hw_vpu.h @@ -61,6 +61,10 @@ | VPU_DEC_STREAM_ERROR_BIT \ | VPU_DEC_TIMEOUT_BIT) +/* enable and soft reset register*/ +#define VPU_REG_DEC_RESET 101 +#define VPU_REG_DEC_RESET_BIT BIT(0) + #define VPU_PP_INTERRUPT_REGISTER 60 #define VPU_PP_PIPELINE_MODE_BIT BIT(1) #define VPU_PP_INTERRUPT_BIT BIT(8) @@ -132,6 +136,7 @@ static struct vpu_task_info task_vpu[TASK_TYPE_BUTT] = { .reg_len = -1, .reg_dir_mv = -1, .reg_pps = -1, + .reg_reset = -1, .reg_pipe = -1, .enable_mask = 0x6, .gating_mask = 0, @@ -139,6 +144,7 @@ static struct vpu_task_info task_vpu[TASK_TYPE_BUTT] = { .irq_mask = VPU_ENC_INTERRUPT_BIT, .ready_mask = VPU_ENC_READY_BIT, .error_mask = VPU_ENC_ERR_MASK, + .reset_mask = 0, .get_fmt = vpu_enc_get_fmt, }, { @@ -149,6 +155,7 @@ static struct vpu_task_info task_vpu[TASK_TYPE_BUTT] = { .reg_len = 12, .reg_dir_mv = 41, .reg_pps = -1, + .reg_reset = VPU_REG_DEC_RESET, .reg_pipe = VPU_PP_INTERRUPT_REGISTER, .enable_mask = 0, .gating_mask = 0, @@ -156,6 +163,7 @@ static struct vpu_task_info task_vpu[TASK_TYPE_BUTT] = { .irq_mask = VPU_DEC_INTERRUPT_BIT, .ready_mask = VPU_DEC_READY_BIT, .error_mask = VPU_DEC_ERR_MASK, + .reset_mask = VPU_REG_DEC_RESET_BIT, .get_fmt = vpu_dec_get_fmt, }, { @@ -165,6 +173,7 @@ static struct vpu_task_info task_vpu[TASK_TYPE_BUTT] = { .reg_len = -1, .reg_dir_mv = -1, .reg_pps = -1, + .reg_reset = -1, .reg_pipe = VPU_PP_INTERRUPT_REGISTER, .enable_mask = 0, .gating_mask = 0, @@ -172,6 +181,7 @@ static struct vpu_task_info task_vpu[TASK_TYPE_BUTT] = { .irq_mask = VPU_PP_INTERRUPT_BIT, .ready_mask = VPU_PP_READY_BIT, .error_mask = VPU_PP_ERR_MASK, + .reset_mask = 0, .get_fmt = vpu_pp_get_fmt, }, { @@ -182,6 +192,7 @@ static struct vpu_task_info task_vpu[TASK_TYPE_BUTT] = { .reg_len = 12, .reg_dir_mv = 41, .reg_pps = -1, + .reg_reset = -1, .reg_pipe = VPU_PP_INTERRUPT_REGISTER, .enable_mask = 0, .gating_mask = 0, @@ -189,6 +200,7 @@ static struct vpu_task_info task_vpu[TASK_TYPE_BUTT] = { .irq_mask = VPU_DEC_INTERRUPT_BIT, .ready_mask = VPU_DEC_READY_BIT, .error_mask = VPU_DEC_ERR_MASK, + .reset_mask = 0, .get_fmt = vpu_dec_get_fmt, }, }; diff --git a/drivers/video/rockchip/vcodec/vcodec_hw_vpu2.h b/drivers/video/rockchip/vcodec/vcodec_hw_vpu2.h index a37cbc481704..5bbde3768bce 100644 --- a/drivers/video/rockchip/vcodec/vcodec_hw_vpu2.h +++ b/drivers/video/rockchip/vcodec/vcodec_hw_vpu2.h @@ -58,6 +58,10 @@ | VPU2_DEC_STREAM_ERROR_BIT \ | VPU2_DEC_TIMEOUT_BIT) +/*enable and soft reset register*/ +#define VPU2_REG_DEC_RESET 58 +#define VPU2_REG_DEC_RESET_BIT BIT(0) + #define VPU2_PP_INTERRUPT_REGISTER 40 #define VPU2_PP_INTERRUPT_BIT BIT(0) #define VPU2_PP_READY_BIT BIT(2) @@ -131,6 +135,7 @@ static struct vpu_task_info task_vpu2[TASK_TYPE_BUTT] = { .reg_len = -1, .reg_dir_mv = -1, .reg_pps = -1, + .reg_reset = -1, .reg_pipe = -1, .enable_mask = 0x30, .gating_mask = VPU2_REG_ENC_GATE_BIT, @@ -138,6 +143,7 @@ static struct vpu_task_info task_vpu2[TASK_TYPE_BUTT] = { .irq_mask = VPU2_ENC_INTERRUPT_BIT, .ready_mask = VPU2_ENC_READY_BIT, .error_mask = VPU2_ENC_ERR_MASK, + .reset_mask = 0, .get_fmt = vpu2_enc_get_fmt, }, { @@ -148,6 +154,7 @@ static struct vpu_task_info task_vpu2[TASK_TYPE_BUTT] = { .reg_len = 64, .reg_dir_mv = 62, .reg_pps = -1, + .reg_reset = VPU2_REG_DEC_RESET, .reg_pipe = VPU2_PP_PIPELINE_REGISTER, .enable_mask = 0, .gating_mask = VPU2_REG_DEC_GATE_BIT, @@ -155,6 +162,7 @@ static struct vpu_task_info task_vpu2[TASK_TYPE_BUTT] = { .irq_mask = VPU2_DEC_INTERRUPT_BIT, .ready_mask = VPU2_DEC_READY_BIT, .error_mask = VPU2_DEC_ERR_MASK, + .reset_mask = VPU2_REG_DEC_RESET_BIT, .get_fmt = vpu2_dec_get_fmt, }, { @@ -171,6 +179,7 @@ static struct vpu_task_info task_vpu2[TASK_TYPE_BUTT] = { .irq_mask = VPU2_PP_INTERRUPT_BIT, .ready_mask = VPU2_PP_READY_BIT, .error_mask = VPU2_PP_ERR_MASK, + .reset_mask = 0, .get_fmt = vpu2_pp_get_fmt, }, { @@ -188,6 +197,7 @@ static struct vpu_task_info task_vpu2[TASK_TYPE_BUTT] = { .irq_mask = VPU2_DEC_INTERRUPT_BIT, .ready_mask = VPU2_DEC_READY_BIT, .error_mask = VPU2_DEC_ERR_MASK, + .reset_mask = 0, .get_fmt = vpu2_dec_get_fmt, }, }; diff --git a/drivers/video/rockchip/vcodec/vcodec_service.c b/drivers/video/rockchip/vcodec/vcodec_service.c index d151d6b978b5..c7c3d38f057e 100644 --- a/drivers/video/rockchip/vcodec/vcodec_service.c +++ b/drivers/video/rockchip/vcodec/vcodec_service.c @@ -461,14 +461,12 @@ struct compat_vpu_request { }; #endif -#define VDPU_SOFT_RESET_REG 101 #define VDPU_CLEAN_CACHE_REG 516 #define VEPU_CLEAN_CACHE_REG 772 #define HEVC_CLEAN_CACHE_REG 260 #define VPU_REG_ENABLE(base, reg) writel_relaxed(1, base + reg) -#define VDPU_SOFT_RESET(base) VPU_REG_ENABLE(base, VDPU_SOFT_RESET_REG) #define VDPU_CLEAN_CACHE(base) VPU_REG_ENABLE(base, VDPU_CLEAN_CACHE_REG) #define VEPU_CLEAN_CACHE(base) VPU_REG_ENABLE(base, VEPU_CLEAN_CACHE_REG) #define HEVC_CLEAN_CACHE(base) VPU_REG_ENABLE(base, HEVC_CLEAN_CACHE_REG) @@ -755,6 +753,27 @@ static void vpu_reset(struct vpu_subdev_data *data) dev_info(pservice->dev, "reset done\n"); } +static void vpu_soft_reset(struct vpu_subdev_data *data) +{ + struct vpu_device *dev = &data->dec_dev; + struct vpu_service_info *pservice = data->pservice; + struct vpu_task_info *task = &data->task_info[TASK_DEC]; + + if (task->reg_reset < 0) + return; + + writel(task->reset_mask, dev->regs + task->reg_reset); + if (data->mmu_dev && test_bit(MMU_ACTIVATED, &data->state)) { + clear_bit(MMU_ACTIVATED, &data->state); + clear_bit(MMU_PAGEFAULT, &data->state); + if (atomic_read(&pservice->enabled)) + /* Need to reset iommu */ + vcodec_iommu_detach(data->iommu_info); + else + WARN_ON(!atomic_read(&pservice->enabled)); + } +} + static void reg_deinit(struct vpu_subdev_data *data, struct vpu_reg *reg); static void vpu_service_session_clear(struct vpu_subdev_data *data, struct vpu_session *session) @@ -3798,8 +3817,7 @@ static irqreturn_t vdpu_isr(int irq, void *dev_id) } reg_from_run_to_done(data, pservice->reg_codec); /* avoid vpu timeout and can't recover problem */ - if (data->mode == VCODEC_RUNNING_MODE_VPU) - VDPU_SOFT_RESET(data->regs); + vpu_soft_reset(data); } }