| .. | .. |
|---|
| 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 | }; |
|---|