linuxdriver: add Watermark flush mechanism [2/2]
authorLiqiang Jin <liqiang.jin@amlogic.com>
Mon, 9 Nov 2020 08:12:51 +0000 (16:12 +0800)
committerLiqiang Jin <liqiang.jin@amlogic.com>
Mon, 16 Nov 2020 09:53:17 +0000 (17:53 +0800)
PD#SWPL-36395

Problem:
1) if Verimatrix Watermark enable, OSD flicker when the TV station changes
2) if screen resolution changes, NexGuard Watermark display is abnormal

Solution:
add Watermark flush mechanism

Verify:
Android Q + AH212(SC2)

Change-Id: I096ecf01eca522cb3b6c2f943cd57ab813eb92ed
Signed-off-by: Liqiang Jin <liqiang.jin@amlogic.com>
optee/Makefile
optee/core.c
optee/optee_private.h
optee/optee_smc.h
optee/watermark.c [new file with mode: 0644]

index 8865e152989f280188ef451449a2692c6c64bac4..c563dfafa05d6697b687bc81c7163df8afb5efd8 100644 (file)
@@ -14,3 +14,4 @@ else
 optee_armtz-objs += smccc-call.o
 endif
 optee_armtz-objs += log.o
+optee_armtz-objs += watermark.o
index 45028a1008fec14c5204143a05d0f4d940a8d48b..8cbfc3d591402161f38a2af8469ab6c6514cfce4 100644 (file)
@@ -514,6 +514,8 @@ static int optee_probe(struct platform_device *pdev)
 
        optee_timer_init(&optee->timer);
 
+       optee_wm_irq_register();
+
        mutex_init(&optee->call_queue.mutex);
        INIT_LIST_HEAD(&optee->call_queue.waiters);
        optee_wait_queue_init(&optee->wait_queue);
@@ -549,6 +551,8 @@ static int optee_remove(struct platform_device *pdev)
 {
        struct optee *optee = platform_get_drvdata(pdev);
 
+       optee_wm_irq_free();
+
        optee_timer_destroy(&optee->timer);
 
        optee_log_exit(optee->teedev);
index 2bdf40ebde48d773ecf14979f61edeb33d82ebb8..7c5f8f5c22e554f19e71216636ef330401cd79ea 100644 (file)
@@ -192,4 +192,7 @@ void optee_timer_init(struct optee_timer *timer);
 void optee_timer_destroy(struct optee_timer *timer);
 void optee_timer_missed_destroy(struct tee_context *ctx, u32 session);
 
+int optee_wm_irq_register(void);
+void optee_wm_irq_free(void);
+
 #endif /*OPTEE_PRIVATE_H*/
index bcf4ce2b4d1010a9a34d8f0952c044b549c61795..a06819961e1841a29190dd5f9289b1e0fa9a19a5 100644 (file)
@@ -426,6 +426,21 @@ struct optee_smc_disable_shm_cache_result {
 #define OPTEE_SMC_RETURN_RPC_CMD \
        OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD)
 
+/*
+ * flush watermark
+ *
+ * Call register usage:
+ * a0      SMC Function ID, OPTEE_SMC_FLUSH_WM
+ * a1-7    Not used
+ *
+ * Normal return register usage:
+ * a0      result
+ * a1-7    Preserved
+ */
+#define OPTEE_SMC_FUNCID_FLUSH_WM      0xE000
+#define OPTEE_SMC_FLUSH_WM \
+       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_FLUSH_WM)
+
 /*
  * set logger
  *
@@ -444,6 +459,21 @@ struct optee_smc_disable_shm_cache_result {
 #define OPTEE_SMC_SET_LOGGER \
     OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_SET_LOGGER)
 
+/*
+ * check watermark status
+ *
+ * Call register usage:
+ * a0      SMC Function ID, OPTEE_SMC_CHECK_WM_STATUS
+ * a1-7    Not used
+ *
+ * Normal return register usage:
+ * a0      result
+ * a1-7    Preserved
+ */
+#define OPTEE_SMC_FUNCID_CHECK_WM_STATUS      0xE003
+#define OPTEE_SMC_CHECK_WM_STATUS \
+       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_CHECK_WM_STATUS)
+
 /* Returned in a0 */
 #define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF
 
diff --git a/optee/watermark.c b/optee/watermark.c
new file mode 100644 (file)
index 0000000..36577dc
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2017, Amlogic, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/irqreturn.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include "optee_smc.h"
+#include "optee_private.h"
+
+#define OPTEE_WM_DEBUG      0
+
+#define SRC_IRQ_NAME        "viu-vsync"
+#define DST_IRQ_NAME        "wm-vsync"
+
+static int g_irq_id = 0;
+
+static uint32_t check_wm_status(void)
+{
+       struct arm_smccc_res res;
+
+       arm_smccc_smc(OPTEE_SMC_CHECK_WM_STATUS, 0, 0, 0, 0, 0, 0, 0, &res);
+
+       return res.a0;
+}
+
+static uint32_t flush_wm(void)
+{
+       struct arm_smccc_res res;
+
+       arm_smccc_smc(OPTEE_SMC_FLUSH_WM, 0, 0, 0, 0, 0, 0, 0, &res);
+
+       return res.a0;
+}
+
+static irqreturn_t vsync_isr(int irq, void *dev_id)
+{
+       flush_wm();
+
+       return IRQ_HANDLED;
+}
+
+static int get_wm_irq_id(void)
+{
+       int irq_id = 0;
+       struct device_node *root_node = of_find_node_by_path("/");
+       struct property *root_prop = NULL;
+       char *soc = NULL;
+       char compatible_val[32] = {"amlogic, meson-"};
+       struct device_node *compatible_node = NULL;
+
+       for (root_prop = root_node->properties; root_prop; root_prop = root_prop->next) {
+               if (of_prop_cmp(root_prop->name, "compatible") == 0) {
+                       soc = ((char *)root_prop->value) + strlen("amlogic, ");
+                       strcat(compatible_val, soc);
+                       compatible_node = of_find_compatible_node(NULL, NULL, compatible_val);
+                       if (compatible_node)
+                               irq_id = of_irq_get_byname(compatible_node, SRC_IRQ_NAME);
+                       goto exit;
+               }
+       }
+
+exit:
+       if (irq_id <= 0) {
+               pr_err("SOC: %s; node: %p; node compatible value: %s; interrupt name: %s; interrupt id: %d;\n",
+                               soc, compatible_node, compatible_val,
+                               SRC_IRQ_NAME, irq_id);
+               pr_err("not found %s interrupt\n", SRC_IRQ_NAME);
+       }
+
+       return irq_id;
+}
+
+int optee_wm_irq_register(void)
+{
+       uint32_t wm_sts = 0;
+       int err_num = 0;
+
+       wm_sts = check_wm_status();
+       if (wm_sts) {
+#ifdef OPTEE_WM_DEBUG
+               pr_info("checking watermark status return 0x%08X\n", wm_sts);
+#endif
+               return -1;
+       }
+
+       g_irq_id = get_wm_irq_id();
+#ifdef OPTEE_WM_DEBUG
+       pr_info("%s interrupt id: %d\n", DST_IRQ_NAME, g_irq_id);
+#endif
+
+       err_num = request_irq(g_irq_id, &vsync_isr, IRQF_SHARED, DST_IRQ_NAME, (void *)&g_irq_id);
+       if (err_num)
+               pr_err("can't request %s interrupt for vsync, err_num = %d\n", DST_IRQ_NAME, -err_num);
+
+       return -1;
+}
+
+void optee_wm_irq_free(void)
+{
+       if (g_irq_id > 0)
+               free_irq(g_irq_id, (void *)&g_irq_id);
+}