.. | .. |
---|
17 | 17 | |
---|
18 | 18 | #include <linux/devfreq_cooling.h> |
---|
19 | 19 | #include <soc/rockchip/rockchip_ipa.h> |
---|
| 20 | +#include <soc/rockchip/rockchip_dmc.h> |
---|
20 | 21 | #include <soc/rockchip/rockchip_opp_select.h> |
---|
21 | 22 | #include <soc/rockchip/rockchip_system_monitor.h> |
---|
| 23 | +#include <soc/rockchip/rockchip_iommu.h> |
---|
22 | 24 | |
---|
23 | 25 | #ifdef CONFIG_PM_DEVFREQ |
---|
24 | 26 | #include "../../../devfreq/governor.h" |
---|
.. | .. |
---|
304 | 306 | static int rkvdec2_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) |
---|
305 | 307 | { |
---|
306 | 308 | struct rkvdec2_task *task = to_rkvdec2_task(mpp_task); |
---|
| 309 | + u32 timing_en = mpp->srv->timing_en; |
---|
307 | 310 | u32 reg_en = mpp_task->hw_info->reg_en; |
---|
308 | 311 | /* set cache size */ |
---|
309 | 312 | u32 reg = RKVDEC_CACHE_PERMIT_CACHEABLE_ACCESS | |
---|
.. | .. |
---|
332 | 335 | e = s + req->size / sizeof(u32); |
---|
333 | 336 | mpp_write_req(mpp, task->reg, s, e, reg_en); |
---|
334 | 337 | } |
---|
| 338 | + |
---|
| 339 | + /* flush tlb before starting hardware */ |
---|
| 340 | + mpp_iommu_flush_tlb(mpp->iommu_info); |
---|
| 341 | + |
---|
335 | 342 | /* init current task */ |
---|
336 | 343 | mpp->cur_task = mpp_task; |
---|
337 | | - mpp_time_record(mpp_task); |
---|
| 344 | + |
---|
| 345 | + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); |
---|
| 346 | + |
---|
338 | 347 | /* Flush the register before the start the device */ |
---|
339 | 348 | wmb(); |
---|
340 | 349 | mpp_write(mpp, RKVDEC_REG_START_EN_BASE, task->reg[reg_en] | RKVDEC_START_EN); |
---|
| 350 | + |
---|
| 351 | + mpp_task_run_end(mpp_task, timing_en); |
---|
341 | 352 | |
---|
342 | 353 | mpp_debug_leave(); |
---|
343 | 354 | |
---|
.. | .. |
---|
381 | 392 | u32 err_mask; |
---|
382 | 393 | struct rkvdec2_task *task = NULL; |
---|
383 | 394 | struct mpp_task *mpp_task = mpp->cur_task; |
---|
| 395 | + struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
384 | 396 | |
---|
385 | 397 | /* FIXME use a spin lock here */ |
---|
386 | 398 | if (!mpp_task) { |
---|
387 | 399 | dev_err(mpp->dev, "no current task\n"); |
---|
388 | 400 | return IRQ_HANDLED; |
---|
389 | 401 | } |
---|
390 | | - mpp_time_diff(mpp_task); |
---|
| 402 | + mpp_task->hw_cycles = mpp_read(mpp, RKVDEC_PERF_WORKING_CNT); |
---|
| 403 | + mpp_time_diff_with_hw_time(mpp_task, dec->core_clk_info.real_rate_hz); |
---|
391 | 404 | mpp->cur_task = NULL; |
---|
392 | 405 | task = to_rkvdec2_task(mpp_task); |
---|
393 | 406 | task->irq_status = mpp->irq_status; |
---|
.. | .. |
---|
552 | 565 | } |
---|
553 | 566 | } |
---|
554 | 567 | } break; |
---|
| 568 | + case MPP_CMD_SET_ERR_REF_HACK: { |
---|
| 569 | + struct rkvdec2_dev *dec = to_rkvdec2_dev(session->mpp); |
---|
| 570 | + u32 err_ref_hack_en = 0; |
---|
| 571 | + |
---|
| 572 | + if (copy_from_user(&err_ref_hack_en, req->data, sizeof(u32))) { |
---|
| 573 | + mpp_err("copy_from_user failed\n"); |
---|
| 574 | + return -EINVAL; |
---|
| 575 | + } |
---|
| 576 | + dec->err_ref_hack = err_ref_hack_en; |
---|
| 577 | + } break; |
---|
555 | 578 | default: { |
---|
556 | 579 | mpp_err("unknown mpp ioctl cmd %x\n", req->cmd); |
---|
557 | 580 | } break; |
---|
.. | .. |
---|
617 | 640 | dec->procfs = NULL; |
---|
618 | 641 | return -EIO; |
---|
619 | 642 | } |
---|
| 643 | + |
---|
| 644 | + /* for common mpp_dev options */ |
---|
| 645 | + mpp_procfs_create_common(dec->procfs, mpp); |
---|
| 646 | + |
---|
620 | 647 | mpp_procfs_create_u32("aclk", 0644, |
---|
621 | 648 | dec->procfs, &dec->aclk_info.debug_rate_hz); |
---|
622 | 649 | mpp_procfs_create_u32("clk_core", 0644, |
---|
.. | .. |
---|
1067 | 1094 | return 0; |
---|
1068 | 1095 | } |
---|
1069 | 1096 | |
---|
| 1097 | +static int rkvdec2_soft_reset(struct mpp_dev *mpp) |
---|
| 1098 | +{ |
---|
| 1099 | + int ret = 0; |
---|
| 1100 | + |
---|
| 1101 | + /* |
---|
| 1102 | + * for rk3528 and rk3562 |
---|
| 1103 | + * use mmu reset instead of rkvdec soft reset |
---|
| 1104 | + * rkvdec will reset together when rkvdec_mmu force reset |
---|
| 1105 | + */ |
---|
| 1106 | + ret = rockchip_iommu_force_reset(mpp->dev); |
---|
| 1107 | + if (ret) |
---|
| 1108 | + mpp_err("soft mmu reset fail, ret %d\n", ret); |
---|
| 1109 | + mpp_write(mpp, RKVDEC_REG_INT_EN, 0); |
---|
| 1110 | + |
---|
| 1111 | + return ret; |
---|
| 1112 | + |
---|
| 1113 | +} |
---|
| 1114 | + |
---|
1070 | 1115 | static int rkvdec2_reset(struct mpp_dev *mpp) |
---|
1071 | 1116 | { |
---|
1072 | 1117 | struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
| 1118 | + int ret = 0; |
---|
1073 | 1119 | |
---|
1074 | 1120 | mpp_debug_enter(); |
---|
1075 | 1121 | #ifdef CONFIG_PM_DEVFREQ |
---|
1076 | 1122 | if (dec->devfreq) |
---|
1077 | 1123 | mutex_lock(&dec->devfreq->lock); |
---|
1078 | 1124 | #endif |
---|
1079 | | - if (dec->rst_a && dec->rst_h) { |
---|
1080 | | - rockchip_pmu_idle_request(mpp->dev, true); |
---|
| 1125 | + /* safe reset first*/ |
---|
| 1126 | + ret = rkvdec2_soft_reset(mpp); |
---|
| 1127 | + |
---|
| 1128 | + /* cru reset */ |
---|
| 1129 | + if (ret && dec->rst_a && dec->rst_h) { |
---|
| 1130 | + mpp_err("soft reset timeout, use cru reset\n"); |
---|
| 1131 | + mpp_pmu_idle_request(mpp, true); |
---|
1081 | 1132 | mpp_safe_reset(dec->rst_niu_a); |
---|
1082 | 1133 | mpp_safe_reset(dec->rst_niu_h); |
---|
1083 | 1134 | mpp_safe_reset(dec->rst_a); |
---|
.. | .. |
---|
1093 | 1144 | mpp_safe_unreset(dec->rst_core); |
---|
1094 | 1145 | mpp_safe_unreset(dec->rst_cabac); |
---|
1095 | 1146 | mpp_safe_unreset(dec->rst_hevc_cabac); |
---|
1096 | | - rockchip_pmu_idle_request(mpp->dev, false); |
---|
| 1147 | + mpp_pmu_idle_request(mpp, false); |
---|
1097 | 1148 | } |
---|
1098 | 1149 | #ifdef CONFIG_PM_DEVFREQ |
---|
1099 | 1150 | if (dec->devfreq) |
---|
1100 | 1151 | mutex_unlock(&dec->devfreq->lock); |
---|
1101 | 1152 | #endif |
---|
| 1153 | + mpp_debug_leave(); |
---|
| 1154 | + |
---|
| 1155 | + return 0; |
---|
| 1156 | +} |
---|
| 1157 | + |
---|
| 1158 | +static int rkvdec2_sip_reset(struct mpp_dev *mpp) |
---|
| 1159 | +{ |
---|
| 1160 | + mpp_debug_enter(); |
---|
| 1161 | + |
---|
| 1162 | + if (IS_REACHABLE(CONFIG_ROCKCHIP_SIP)) { |
---|
| 1163 | + /* sip reset */ |
---|
| 1164 | + rockchip_dmcfreq_lock(); |
---|
| 1165 | + sip_smc_vpu_reset(0, 0, 0); |
---|
| 1166 | + rockchip_dmcfreq_unlock(); |
---|
| 1167 | + } else { |
---|
| 1168 | + rkvdec2_reset(mpp); |
---|
| 1169 | + } |
---|
| 1170 | + |
---|
1102 | 1171 | mpp_debug_leave(); |
---|
1103 | 1172 | |
---|
1104 | 1173 | return 0; |
---|
.. | .. |
---|
1120 | 1189 | .clk_off = rkvdec2_clk_off, |
---|
1121 | 1190 | .get_freq = rkvdec2_get_freq, |
---|
1122 | 1191 | .set_freq = rkvdec2_set_freq, |
---|
1123 | | - .reset = rkvdec2_reset, |
---|
| 1192 | + .reset = rkvdec2_sip_reset, |
---|
1124 | 1193 | }; |
---|
1125 | 1194 | |
---|
1126 | 1195 | static struct mpp_dev_ops rkvdec_v2_dev_ops = { |
---|