.. | .. |
---|
28 | 28 | #include <linux/nospec.h> |
---|
29 | 29 | #include <linux/workqueue.h> |
---|
30 | 30 | #include <linux/dma-iommu.h> |
---|
| 31 | +#include <linux/mfd/syscon.h> |
---|
| 32 | +#include <linux/rockchip/cpu.h> |
---|
31 | 33 | #include <soc/rockchip/pm_domains.h> |
---|
32 | 34 | #include <soc/rockchip/rockchip_ipa.h> |
---|
33 | 35 | #include <soc/rockchip/rockchip_opp_select.h> |
---|
.. | .. |
---|
41 | 43 | |
---|
42 | 44 | #define RKVENC_SESSION_MAX_BUFFERS 40 |
---|
43 | 45 | #define RKVENC_MAX_CORE_NUM 4 |
---|
| 46 | +#define RKVENC_SCLR_DONE_STA BIT(2) |
---|
44 | 47 | |
---|
45 | 48 | #define to_rkvenc_info(info) \ |
---|
46 | 49 | container_of(info, struct rkvenc_hw_info, hw) |
---|
.. | .. |
---|
187 | 190 | dma_addr_t sram_iova; |
---|
188 | 191 | u32 sram_enabled; |
---|
189 | 192 | struct page *rcb_page; |
---|
| 193 | + struct regmap *grf; |
---|
190 | 194 | }; |
---|
191 | 195 | |
---|
192 | 196 | |
---|
.. | .. |
---|
699 | 703 | struct rkvenc_dev *enc = to_rkvenc_dev(mpp); |
---|
700 | 704 | struct rkvenc_task *task = to_rkvenc_task(mpp_task); |
---|
701 | 705 | struct rkvenc_hw_info *hw = enc->hw_info; |
---|
| 706 | + u32 timing_en = mpp->srv->timing_en; |
---|
702 | 707 | |
---|
703 | 708 | mpp_debug_enter(); |
---|
704 | 709 | |
---|
.. | .. |
---|
735 | 740 | } |
---|
736 | 741 | } |
---|
737 | 742 | |
---|
| 743 | + /* flush tlb before starting hardware */ |
---|
| 744 | + mpp_iommu_flush_tlb(mpp->iommu_info); |
---|
| 745 | + |
---|
738 | 746 | /* init current task */ |
---|
739 | 747 | mpp->cur_task = mpp_task; |
---|
| 748 | + |
---|
| 749 | + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); |
---|
| 750 | + |
---|
740 | 751 | /* Flush the register before the start the device */ |
---|
741 | 752 | wmb(); |
---|
| 753 | + |
---|
742 | 754 | mpp_write(mpp, enc->hw_info->enc_start_base, start_val); |
---|
| 755 | + |
---|
| 756 | + mpp_task_run_end(mpp_task, timing_en); |
---|
743 | 757 | |
---|
744 | 758 | mpp_debug_leave(); |
---|
745 | 759 | |
---|
.. | .. |
---|
793 | 807 | if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) |
---|
794 | 808 | mpp_task_dump_hw_reg(mpp, mpp_task); |
---|
795 | 809 | } |
---|
| 810 | + |
---|
796 | 811 | mpp_task_finish(mpp_task->session, mpp_task); |
---|
797 | 812 | |
---|
798 | 813 | mpp_debug_leave(); |
---|
.. | .. |
---|
1031 | 1046 | enc->procfs = NULL; |
---|
1032 | 1047 | return -EIO; |
---|
1033 | 1048 | } |
---|
| 1049 | + |
---|
| 1050 | + /* for common mpp_dev options */ |
---|
| 1051 | + mpp_procfs_create_common(enc->procfs, mpp); |
---|
| 1052 | + |
---|
1034 | 1053 | /* for debug */ |
---|
1035 | 1054 | mpp_procfs_create_u32("aclk", 0644, |
---|
1036 | 1055 | enc->procfs, &enc->aclk_info.debug_rate_hz); |
---|
.. | .. |
---|
1063 | 1082 | struct rkvenc_dev *enc = to_rkvenc_dev(mpp); |
---|
1064 | 1083 | int ret = 0; |
---|
1065 | 1084 | |
---|
1066 | | - mpp->grf_info = &mpp->srv->grf_infos[MPP_DRIVER_RKVENC]; |
---|
| 1085 | + mpp->grf_info = &mpp->srv->grf_infos[MPP_DRIVER_RKVENC2]; |
---|
1067 | 1086 | |
---|
1068 | 1087 | /* Get clock info from dtsi */ |
---|
1069 | 1088 | ret = mpp_get_clk_info(mpp, &enc->aclk_info, "aclk_vcodec"); |
---|
.. | .. |
---|
1097 | 1116 | return 0; |
---|
1098 | 1117 | } |
---|
1099 | 1118 | |
---|
1100 | | -static int rkvenc_reset(struct mpp_dev *mpp) |
---|
| 1119 | +static int rkvenc_soft_reset(struct mpp_dev *mpp) |
---|
1101 | 1120 | { |
---|
1102 | 1121 | struct rkvenc_dev *enc = to_rkvenc_dev(mpp); |
---|
1103 | 1122 | struct rkvenc_hw_info *hw = enc->hw_info; |
---|
1104 | | - |
---|
1105 | | - mpp_debug_enter(); |
---|
| 1123 | + u32 rst_status = 0; |
---|
| 1124 | + int ret = 0; |
---|
1106 | 1125 | |
---|
1107 | 1126 | /* safe reset */ |
---|
1108 | 1127 | mpp_write(mpp, hw->int_mask_base, 0x3FF); |
---|
1109 | 1128 | mpp_write(mpp, hw->enc_clr_base, 0x1); |
---|
1110 | | - udelay(5); |
---|
| 1129 | + ret = readl_relaxed_poll_timeout(mpp->reg_base + hw->int_sta_base, |
---|
| 1130 | + rst_status, |
---|
| 1131 | + rst_status & RKVENC_SCLR_DONE_STA, |
---|
| 1132 | + 0, 5); |
---|
1111 | 1133 | mpp_write(mpp, hw->int_clr_base, 0xffffffff); |
---|
1112 | 1134 | mpp_write(mpp, hw->int_sta_base, 0); |
---|
1113 | 1135 | |
---|
| 1136 | + return ret; |
---|
| 1137 | + |
---|
| 1138 | +} |
---|
| 1139 | + |
---|
| 1140 | +static int rkvenc_reset(struct mpp_dev *mpp) |
---|
| 1141 | +{ |
---|
| 1142 | + struct rkvenc_dev *enc = to_rkvenc_dev(mpp); |
---|
| 1143 | + int ret = 0; |
---|
| 1144 | + |
---|
| 1145 | + mpp_debug_enter(); |
---|
| 1146 | + |
---|
| 1147 | + /* safe reset first*/ |
---|
| 1148 | + ret = rkvenc_soft_reset(mpp); |
---|
| 1149 | + |
---|
1114 | 1150 | /* cru reset */ |
---|
1115 | | - if (enc->rst_a && enc->rst_h && enc->rst_core) { |
---|
1116 | | - rockchip_pmu_idle_request(mpp->dev, true); |
---|
| 1151 | + if (ret && enc->rst_a && enc->rst_h && enc->rst_core) { |
---|
| 1152 | + mpp_err("soft reset timeout, use cru reset\n"); |
---|
| 1153 | + mpp_pmu_idle_request(mpp, true); |
---|
1117 | 1154 | mpp_safe_reset(enc->rst_a); |
---|
1118 | 1155 | mpp_safe_reset(enc->rst_h); |
---|
1119 | 1156 | mpp_safe_reset(enc->rst_core); |
---|
.. | .. |
---|
1121 | 1158 | mpp_safe_unreset(enc->rst_a); |
---|
1122 | 1159 | mpp_safe_unreset(enc->rst_h); |
---|
1123 | 1160 | mpp_safe_unreset(enc->rst_core); |
---|
1124 | | - rockchip_pmu_idle_request(mpp->dev, false); |
---|
| 1161 | + mpp_pmu_idle_request(mpp, false); |
---|
1125 | 1162 | } |
---|
1126 | 1163 | |
---|
1127 | 1164 | mpp_debug_leave(); |
---|
.. | .. |
---|
1338 | 1375 | } |
---|
1339 | 1376 | mpp->session_max_buffers = RKVENC_SESSION_MAX_BUFFERS; |
---|
1340 | 1377 | enc->hw_info = to_rkvenc_info(mpp->var->hw_info); |
---|
| 1378 | + |
---|
1341 | 1379 | rkvenc_procfs_init(mpp); |
---|
1342 | 1380 | mpp_dev_register_srv(mpp, mpp->srv); |
---|
1343 | 1381 | |
---|
.. | .. |
---|
1416 | 1454 | dev_info(dev, "shutdown success\n"); |
---|
1417 | 1455 | } |
---|
1418 | 1456 | |
---|
| 1457 | +static int rkvenc_runtime_suspend(struct device *dev) |
---|
| 1458 | +{ |
---|
| 1459 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 1460 | + struct mpp_grf_info *info = mpp->grf_info; |
---|
| 1461 | + |
---|
| 1462 | + if (cpu_is_rk3528() && info && info->mem_offset) |
---|
| 1463 | + regmap_write(info->grf, |
---|
| 1464 | + info->mem_offset, |
---|
| 1465 | + info->val_mem_off); |
---|
| 1466 | + |
---|
| 1467 | + return 0; |
---|
| 1468 | +} |
---|
| 1469 | + |
---|
| 1470 | +static int rkvenc_runtime_resume(struct device *dev) |
---|
| 1471 | +{ |
---|
| 1472 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 1473 | + struct mpp_grf_info *info = mpp->grf_info; |
---|
| 1474 | + |
---|
| 1475 | + if (cpu_is_rk3528() && info && info->mem_offset) |
---|
| 1476 | + regmap_write(info->grf, |
---|
| 1477 | + info->mem_offset, |
---|
| 1478 | + info->val_mem_on); |
---|
| 1479 | + |
---|
| 1480 | + return 0; |
---|
| 1481 | +} |
---|
| 1482 | + |
---|
| 1483 | +static const struct dev_pm_ops rkvenc_pm_ops = { |
---|
| 1484 | + .runtime_suspend = rkvenc_runtime_suspend, |
---|
| 1485 | + .runtime_resume = rkvenc_runtime_resume, |
---|
| 1486 | +}; |
---|
| 1487 | + |
---|
1419 | 1488 | struct platform_driver rockchip_rkvenc2_driver = { |
---|
1420 | 1489 | .probe = rkvenc_probe, |
---|
1421 | 1490 | .remove = rkvenc_remove, |
---|
1422 | 1491 | .shutdown = rkvenc_shutdown, |
---|
1423 | 1492 | .driver = { |
---|
1424 | 1493 | .name = RKVENC_DRIVER_NAME, |
---|
| 1494 | + .pm = &rkvenc_pm_ops, |
---|
1425 | 1495 | .of_match_table = of_match_ptr(mpp_rkvenc_dt_match), |
---|
1426 | 1496 | }, |
---|
1427 | 1497 | }; |
---|