hc
2023-11-06 15ade055295d13f95d49e3d99b09f3bbfb4a43e7
kernel/drivers/video/rockchip/mpp/mpp_iep2.c
....@@ -20,6 +20,8 @@
2020 #include <linux/regmap.h>
2121 #include <linux/pm_runtime.h>
2222 #include <linux/proc_fs.h>
23
+#include <linux/mfd/syscon.h>
24
+#include <linux/rockchip/cpu.h>
2325 #include <soc/rockchip/pm_domains.h>
2426
2527 #include "rockchip_iep2_regs.h"
....@@ -389,12 +391,13 @@
389391 | IEP2_REG_DIL_OSD_EN
390392 | IEP2_REG_DIL_PD_EN
391393 | IEP2_REG_DIL_FF_EN
392
- | IEP2_REG_DIL_MD_PRE_EN
393394 | IEP2_REG_DIL_FIELD_ORDER(cfg->dil_field_order)
394395 | IEP2_REG_DIL_OUT_MODE(cfg->dil_out_mode)
395396 | IEP2_REG_DIL_MODE(cfg->dil_mode);
396397 if (cfg->roi_en)
397398 reg |= IEP2_REG_DIL_ROI_EN;
399
+ if (cfg->md_lambda < 8)
400
+ reg |= IEP2_REG_DIL_MD_PRE_EN;
398401 mpp_write_relaxed(mpp, IEP2_REG_DIL_CONFIG0, reg);
399402
400403 if (cfg->dil_mode != ROCKCHIP_IEP2_DIL_MODE_PD) {
....@@ -437,6 +440,9 @@
437440 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTUV, bot->cbcr);
438441 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTV, bot->cr);
439442 }
443
+
444
+ reg = IEP2_REG_TIMEOUT_CFG_EN | 0x3ffffff;
445
+ mpp_write_relaxed(mpp, IEP2_REG_TIMEOUT_CFG, reg);
440446
441447 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_PREY, cfg->src[2].y);
442448 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_PREUV, cfg->src[2].cbcr);
....@@ -580,6 +586,7 @@
580586 struct mpp_task *mpp_task)
581587 {
582588 struct iep_task *task = NULL;
589
+ u32 timing_en = mpp->srv->timing_en;
583590
584591 mpp_debug_enter();
585592
....@@ -598,12 +605,20 @@
598605 mpp_write_relaxed(mpp, IEP2_REG_INT_EN,
599606 IEP2_REG_FRM_DONE_EN
600607 | IEP2_REG_OSD_MAX_EN
601
- | IEP2_REG_BUS_ERROR_EN);
608
+ | IEP2_REG_BUS_ERROR_EN
609
+ | IEP2_REG_TIMEOUT_EN);
610
+
611
+ /* flush tlb before starting hardware */
612
+ mpp_iommu_flush_tlb(mpp->iommu_info);
613
+
614
+ mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY);
602615
603616 /* Last, flush the registers */
604617 wmb();
605618 /* start iep2 */
606619 mpp_write(mpp, IEP2_REG_FRM_START, 1);
620
+
621
+ mpp_task_run_end(mpp_task, timing_en);
607622
608623 mpp_debug_leave();
609624
....@@ -612,6 +627,10 @@
612627
613628 static int iep2_irq(struct mpp_dev *mpp)
614629 {
630
+ u32 work_mode = mpp_read(mpp, IEP2_REG_WORK_MODE);
631
+
632
+ if (work_mode && !(work_mode & IEP2_REG_IEP2_MODE))
633
+ return IRQ_NONE;
615634 mpp->irq_status = mpp_read(mpp, IEP2_REG_INT_STS);
616635 mpp_write(mpp, IEP2_REG_INT_CLR, 0xffffffff);
617636
....@@ -640,7 +659,8 @@
640659 mpp_debug(DEBUG_IRQ_STATUS, "irq_status: %08x\n",
641660 task->irq_status);
642661
643
- if (IEP2_REG_RO_BUS_ERROR_STS(task->irq_status))
662
+ if (IEP2_REG_RO_BUS_ERROR_STS(task->irq_status) ||
663
+ IEP2_REG_RO_TIMEOUT_STS(task->irq_status))
644664 atomic_inc(&mpp->reset_request);
645665
646666 mpp_task_finish(mpp_task->session, mpp_task);
....@@ -769,6 +789,10 @@
769789 iep->procfs = NULL;
770790 return -EIO;
771791 }
792
+
793
+ /* for common mpp_dev options */
794
+ mpp_procfs_create_common(iep->procfs, mpp);
795
+
772796 mpp_procfs_create_u32("aclk", 0644,
773797 iep->procfs, &iep->aclk_info.debug_rate_hz);
774798 mpp_procfs_create_u32("session_buffers", 0644,
....@@ -870,17 +894,29 @@
870894 {
871895 struct iep2_dev *iep = to_iep2_dev(mpp);
872896
873
- if (iep->rst_a && iep->rst_h && iep->rst_s) {
874
- /* Don't skip this or iommu won't work after reset */
875
- rockchip_pmu_idle_request(mpp->dev, true);
876
- mpp_safe_reset(iep->rst_a);
877
- mpp_safe_reset(iep->rst_h);
878
- mpp_safe_reset(iep->rst_s);
879
- udelay(5);
880
- mpp_safe_unreset(iep->rst_a);
881
- mpp_safe_unreset(iep->rst_h);
882
- mpp_safe_unreset(iep->rst_s);
883
- rockchip_pmu_idle_request(mpp->dev, false);
897
+ int ret = 0;
898
+ u32 rst_status = 0;
899
+
900
+ /* soft rest first */
901
+ mpp_write(mpp, IEP2_REG_IEP_CONFIG0, IEP2_REG_ACLK_SRESET_P);
902
+ ret = readl_relaxed_poll_timeout(mpp->reg_base + IEP2_REG_STATUS,
903
+ rst_status,
904
+ rst_status & IEP2_REG_ARST_FINISH_DONE,
905
+ 0, 5);
906
+ if (ret) {
907
+ mpp_err("soft reset timeout, use cru reset\n");
908
+ if (iep->rst_a && iep->rst_h && iep->rst_s) {
909
+ /* Don't skip this or iommu won't work after reset */
910
+ mpp_pmu_idle_request(mpp, true);
911
+ mpp_safe_reset(iep->rst_a);
912
+ mpp_safe_reset(iep->rst_h);
913
+ mpp_safe_reset(iep->rst_s);
914
+ udelay(5);
915
+ mpp_safe_unreset(iep->rst_a);
916
+ mpp_safe_unreset(iep->rst_h);
917
+ mpp_safe_unreset(iep->rst_s);
918
+ mpp_pmu_idle_request(mpp, false);
919
+ }
884920 }
885921
886922 return 0;
....@@ -1008,12 +1044,53 @@
10081044 dev_err(dev, "wait total running time out\n");
10091045 }
10101046
1047
+static int iep2_runtime_suspend(struct device *dev)
1048
+{
1049
+ struct mpp_dev *mpp = dev_get_drvdata(dev);
1050
+ struct mpp_grf_info *info = mpp->grf_info;
1051
+ struct mpp_taskqueue *queue = mpp->queue;
1052
+
1053
+ if (cpu_is_rk3528() && info && info->mem_offset) {
1054
+ mutex_lock(&queue->ref_lock);
1055
+ if (!atomic_dec_if_positive(&queue->runtime_cnt)) {
1056
+ regmap_write(info->grf, info->mem_offset,
1057
+ info->val_mem_off);
1058
+ }
1059
+ mutex_unlock(&queue->ref_lock);
1060
+ }
1061
+
1062
+ return 0;
1063
+}
1064
+
1065
+static int iep2_runtime_resume(struct device *dev)
1066
+{
1067
+ struct mpp_dev *mpp = dev_get_drvdata(dev);
1068
+ struct mpp_grf_info *info = mpp->grf_info;
1069
+ struct mpp_taskqueue *queue = mpp->queue;
1070
+
1071
+ if (cpu_is_rk3528() && info && info->mem_offset) {
1072
+ mutex_lock(&queue->ref_lock);
1073
+ regmap_write(info->grf, info->mem_offset,
1074
+ info->val_mem_on);
1075
+ atomic_inc(&queue->runtime_cnt);
1076
+ mutex_unlock(&queue->ref_lock);
1077
+ }
1078
+
1079
+ return 0;
1080
+}
1081
+
1082
+static const struct dev_pm_ops iep2_pm_ops = {
1083
+ .runtime_suspend = iep2_runtime_suspend,
1084
+ .runtime_resume = iep2_runtime_resume,
1085
+};
1086
+
10111087 struct platform_driver rockchip_iep2_driver = {
10121088 .probe = iep2_probe,
10131089 .remove = iep2_remove,
10141090 .shutdown = iep2_shutdown,
10151091 .driver = {
10161092 .name = IEP2_DRIVER_NAME,
1093
+ .pm = &iep2_pm_ops,
10171094 .of_match_table = of_match_ptr(mpp_iep2_match),
10181095 },
10191096 };