media: merged code from c502feca7 on the amlogic-3.14-dev [1/3]
authorNanxin Qin <nanxin.qin@amlogic.com>
Sun, 3 Sep 2017 14:47:21 +0000 (22:47 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Thu, 14 Sep 2017 11:16:12 +0000 (04:16 -0700)
PD#150739: merged code from c502feca7 on the amlogic-3.14-dev
1.codec_mm: fixed tvp first wait long time bug
2.pcrmaster: fix some avsync issue in pcrmaster mode
3.vfm: fix vf provider crash issue

Change-Id: I64202a38a3ed0c50ba665fb477caea26c67ddcb0
Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
20 files changed:
MAINTAINERS
arch/arm64/configs/meson64_defconfig
drivers/amlogic/Kconfig
drivers/amlogic/Makefile
drivers/amlogic/media/common/codec_mm/codec_mm.c
drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c
drivers/amlogic/media/common/vfm/vframe_provider.c
drivers/amlogic/media/frame_sync/timestamp.c
drivers/amlogic/media/frame_sync/tsync_pcr.c
drivers/amlogic/media/video_sink/video.c
drivers/amlogic/media/video_sink/video_keeper.c
drivers/amlogic/media/video_sink/vpp.c
drivers/amlogic/tee/Kconfig [new file with mode: 0644]
drivers/amlogic/tee/Makefile [new file with mode: 0644]
drivers/amlogic/tee/tee.c [new file with mode: 0644]
include/linux/amlogic/media/frame_sync/timestamp.h
include/linux/amlogic/media/utils/amstream.h
include/linux/amlogic/media/video_sink/video.h
include/linux/amlogic/media/video_sink/video_keeper.h
include/linux/amlogic/tee.h [new file with mode: 0644]

index 9632f6c..f4d1a03 100644 (file)
@@ -14079,3 +14079,8 @@ F: arch/arm64/configs/meson64_smarthome_defconfig
 AMLOGIC MESONGXL ADD P241 DTS
 M:     Lianghu Su <lianghu.su@amlogic.com>
 F:     arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts
+
+AMLOGIC tee
+M:  Nanxin Qin <nanxin.qin@amlogic.com>
+F: drivers/amlogic/tee/*
+F: include/linux/amlogic/tee.h
index 34d03b8..54a2c55 100644 (file)
@@ -312,6 +312,7 @@ CONFIG_AMLOGIC_IRBLASTER=y
 CONFIG_AMLOGIC_IIO=y
 CONFIG_AMLOGIC_SARADC=y
 CONFIG_AMLOGIC_DDR_WINDOW_TOOL=m
+CONFIG_AMLOGIC_TEE=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
index eabbb04..2bcd011 100644 (file)
@@ -114,5 +114,6 @@ source "drivers/amlogic/drm/Kconfig"
 
 source "drivers/amlogic/secure_monitor/Kconfig"
 
+source "drivers/amlogic/tee/Kconfig"
 endmenu
 endif
index 46b8f88..53f5104 100644 (file)
@@ -104,3 +104,5 @@ obj-$(CONFIG_AMLOGIC_DDR_WINDOW_TOOL)       += ddr_window/
 obj-$(CONFIG_DRM_MESON)        += drm/
 
 obj-$(CONFIG_AMLOGIC_M8B_SM) += secure_monitor/
+
+obj-$(CONFIG_AMLOGIC_TEE) += tee/
index 0dcda79..d8f4465 100644 (file)
@@ -638,7 +638,7 @@ void codec_mm_release(struct codec_mm_s *mem, const char *owner)
        if (!mem)
                return;
 
-       spin_lock_irqsave(&mem->lock, flags);
+       spin_lock_irqsave(&mgt->lock, flags);
        index = atomic_dec_return(&mem->use_cnt);
        max_owner = mem->owner[index];
        for (i = 0; i < index; i++) {
@@ -651,13 +651,13 @@ void codec_mm_release(struct codec_mm_s *mem, const char *owner)
                        mem->from_flags, index);
        mem->owner[index] = NULL;
        if (index == 0) {
-               spin_unlock_irqrestore(&mem->lock, flags);
-               codec_mm_free_in(mgt, mem);
                list_del(&mem->list);
+               spin_unlock_irqrestore(&mgt->lock, flags);
+               codec_mm_free_in(mgt, mem);
                kfree(mem);
                return;
        }
-       spin_unlock_irqrestore(&mem->lock, flags);
+       spin_unlock_irqrestore(&mgt->lock, flags);
 }
 EXPORT_SYMBOL(codec_mm_release);
 
index 7b3e2c3..fa00ecd 100644 (file)
@@ -127,6 +127,7 @@ struct codec_mm_scatter_s {
        u32 enable_slot_from_sys;
        u32 no_cache_size_M;
        u32 support_from_slot_sys;
+       u32 no_alloc_from_sys;
 };
 
 struct codec_mm_scatter_mgt {
@@ -144,6 +145,7 @@ struct codec_mm_scatter_mgt {
        int alloc_from_cma_first;
        u32 enable_slot_from_sys;
        u32 no_cache_size_M;
+       u32 no_alloc_from_sys;
        u32 support_from_slot_sys;
        int one_page_cnt;
        int scatters_cnt;
@@ -577,8 +579,9 @@ static struct codec_mm_slot *codec_mm_slot_alloc(
                        break;  /*ignore codec_mm */
                if ((try_alloc_size <= 0 ||
                        try_alloc_size > 64 * 1024) &&  /*must > 512K. */
-                       codec_mm_get_free_size() >
-                       smgt->reserved_block_mm_M * SZ_1M) {
+                       (smgt->tvp_mode ||
+                               (codec_mm_get_free_size() >
+                               smgt->reserved_block_mm_M * SZ_1M))) {
                        /*try from codec_mm */
                        if (try_alloc_size <= 0) {
                                try_alloc_size =
@@ -626,9 +629,10 @@ static struct codec_mm_slot *codec_mm_slot_alloc(
                        goto error;     /*don't alloc 1 page with slot. */
                }
        }
-       if (!have_alloced && smgt->tvp_mode) {
+       if (!have_alloced) {
                /*tvp not support alloc from sys.*/
-               goto error;
+               if (smgt->tvp_mode || smgt->no_alloc_from_sys)
+                       goto error;
        }
        while (!have_alloced) {
                /*don't alloc 1 page with slot. */
@@ -857,10 +861,11 @@ static int codec_mm_page_alloc_from_slot(
        int n;
 
        codec_mm_list_lock(smgt);
-       if (list_empty(&smgt->free_list) &&
-               (codec_mm_get_free_size() <     /*no codec mm */
-                       smgt->reserved_block_mm_M * SZ_1M) &&
-                       !smgt->support_from_slot_sys) { /*no sys */
+       if (!smgt->tvp_mode &&
+               list_empty(&smgt->free_list) &&
+               (codec_mm_get_free_size() </*no codec mm*/
+               smgt->reserved_block_mm_M * SZ_1M) &&
+               !smgt->support_from_slot_sys) {/*no sys*/
                codec_mm_list_unlock(smgt);
                return 0;
        }
@@ -1023,7 +1028,7 @@ static int codec_mm_page_alloc_all_locked(
                                num - alloced);
                        if (new_alloc <= 0)
                                can_from_slot = 0;
-               } else if (!smgt->tvp_mode) {
+               } else if (!smgt->no_alloc_from_sys && !smgt->tvp_mode) {
                        new_alloc = codec_mm_page_alloc_from_one_pages(
                                smgt,
                                pages + alloced,
@@ -1049,7 +1054,7 @@ static int codec_mm_pages_free_to_scatter(
        if (src_mms->page_used >= src_mms->page_cnt)
                return -1;      /*no need free. */
        dst_mms = smgt->cache_sc;
-       if (!dst_mms)
+       if (!dst_mms || src_mms  == dst_mms)
                return 0;
        codec_mm_scatter_lock(dst_mms);
        moved = min(src_mms->page_cnt - src_mms->page_used,
@@ -1142,37 +1147,74 @@ static int codec_mm_scatter_free_pages_in_locked(
        }
        codec_mm_list_lock(smgt);
        smgt->alloced_page_num -= freeNum;
+       if (smgt->cache_sc == mms)
+               smgt->cached_pages = mms->page_cnt;
        codec_mm_list_unlock(smgt);
        return 0;
 }
 
 /*
-*free pages from id(include id);
-*/
+ *fast_mode:
+ *1: set page_used: call by owner
+ *2: free to scatter: call by owner
+ *3: free to slot or others: call by owner
+ *
+ *free_mode:
+ *0: free from id pages.
+ *1: free not used pages;call by moniter.
+ *2: less pages.: call by moniter for cache
+ *   id is negative.
+ */
 static int codec_mm_scatter_free_tail_pages_in(
        struct codec_mm_scatter *mms,
-       int start_free_id,
-       int fast)
+       int id,
+       int fast_mode,
+       int free_mode)
 {
-       int id = start_free_id;
        struct codec_mm_scatter_mgt *smgt;
-       if (!mms || id < 0 || id >= mms->page_cnt || mms->page_tail < 0) {
-               if (mms)
-                       ERR_LOG("free mm scatters error id %d,page_cnt=%d\n",
-                               id, mms->page_cnt);
+       int start_free_id = id;
+
+       if (!mms)
+               return -1;
+       codec_mm_scatter_lock(mms);
+       if (free_mode == 1)
+               start_free_id = mms->page_used;
+       if (free_mode == 2) {
+               if (id > 0) {
+                       if (id >= mms->page_cnt)
+                               start_free_id = 0;
+                       else
+                               start_free_id = mms->page_cnt - id;
+               } else
+                       start_free_id = -1;
+       }
+       if ((start_free_id < 0) ||
+               (start_free_id >= mms->page_cnt) ||
+               (mms->page_tail < 0)) {
+               if (mms &&
+                       start_free_id != mms->page_cnt) {
+                       ERR_LOG(
+                               "mms[%p],free error id %d(%d),cnt=%d ,=m:%d,%d\n",
+                               mms,
+                               id,
+                               start_free_id,
+                               mms->page_cnt,
+                               fast_mode,
+                               free_mode);
+               }
+               codec_mm_scatter_unlock(mms);
                return -1;
        }
        smgt = (struct codec_mm_scatter_mgt *)mms->manager;
-       codec_mm_scatter_lock(mms);
        mms->page_used = start_free_id;
 
-       if (fast == 1) {
+       if (fast_mode == 1) {
                codec_mm_scatter_unlock(mms);
                return 0;
        }
-       if (fast == 2 || fast == 3) {
+       if (fast_mode == 2 || fast_mode == 3) {
                codec_mm_pages_free_to_scatter(smgt, mms);
-               if (fast == 2 || mms->page_used == mms->page_cnt) {
+               if (fast_mode == 2 || mms->page_used == mms->page_cnt) {
                        codec_mm_scatter_unlock(mms);
                        return 0;
                }
@@ -1184,14 +1226,12 @@ static int codec_mm_scatter_free_tail_pages_in(
 
 int codec_mm_scatter_free_tail_pages(
                struct codec_mm_scatter *mms,
-               int start_free_id)
+               int start_id)
 {
        int ret = 0;
-
-       if (start_free_id < mms->page_cnt)
-               ret = codec_mm_scatter_free_tail_pages_in(
+       ret = codec_mm_scatter_free_tail_pages_in(
                        mms,
-                       start_free_id, 0);
+                       start_id, 0, 0);
        return ret;
 }
 EXPORT_SYMBOL(codec_mm_scatter_free_tail_pages);
@@ -1206,7 +1246,7 @@ int codec_mm_scatter_free_tail_pages_fast(
        if (start_free_id < mms->page_cnt)
                ret = codec_mm_scatter_free_tail_pages_in(
                                mms,
-                               start_free_id, 2);
+                               start_free_id, 2, 0);
        codec_mm_schedule_delay_work(
                (struct codec_mm_scatter_mgt *)mms->manager,
                100, 0);
@@ -1217,14 +1257,23 @@ EXPORT_SYMBOL(codec_mm_scatter_free_tail_pages_fast);
 int codec_mm_scatter_free_unused_pages(struct codec_mm_scatter *mms)
 {
        int ret = 0;
-
-       if (mms->page_used < mms->page_cnt)
-               ret = codec_mm_scatter_free_tail_pages_in(mms,
-                       mms->page_used, 3);
+       ret = codec_mm_scatter_free_tail_pages_in(mms,
+                       0, 0, 1);
        return ret;
 }
 EXPORT_SYMBOL(codec_mm_scatter_free_unused_pages);
 
+int codec_mm_scatter_less_pages(struct codec_mm_scatter *mms,
+       int nums)
+{
+       int ret = 0;
+
+       ret = codec_mm_scatter_free_tail_pages_in(mms,
+                       nums, 0, 2);
+       return ret;
+}
+EXPORT_SYMBOL(codec_mm_scatter_less_pages);
+
 /*free all pages only
 *don't free scatter
 */
@@ -1315,7 +1364,7 @@ static int codec_mm_scatter_free_on_nouser_ext(
        codec_mm_list_unlock(smgt);
        codec_mm_scatter_unlock(mms);
        if (mms->page_cnt > 0)
-               ret = codec_mm_scatter_free_tail_pages_in(mms, 0, 0);
+               ret = codec_mm_scatter_free_tail_pages_in(mms, 0, 0, 0);
        if (free >= 256 &&
                (smgt->try_alloc_in_sys_page_cnt <
                        smgt->try_alloc_in_sys_page_cnt_max) &&
@@ -1364,7 +1413,6 @@ static int codec_mm_scatter_inc_user_in1(
        codec_mm_list_unlock(smgt);
        return ret <= 0 ? ret : 0;      /*must add before user cnt >= 0 */
 }
-
 static int codec_mm_scatter_inc_user_in(
        struct codec_mm_scatter *mms,
        int cnt)
@@ -1394,6 +1442,7 @@ static int codec_mm_scatter_dec_user_in1(
                int delay_free_ms, int cnt)
 {
        int after_users = 1;
+
        codec_mm_list_lock(smgt);
        if (!codec_mm_scatter_valid_locked(smgt, mms)) {
                codec_mm_list_unlock(smgt);
@@ -1424,6 +1473,7 @@ static int codec_mm_scatter_dec_user_in(
 {
        struct codec_mm_scatter_mgt *smgt;
        int ret;
+
        if (!mms)
                return -1;
        smgt = codec_mm_get_scatter_mgt(0);
@@ -1440,6 +1490,7 @@ static int codec_mm_scatter_dec_user_in(
        }
        return ret;
 }
+
 /*
 *maybe a render/sink.video/osd/
 */
@@ -2084,6 +2135,7 @@ int codec_mm_scatter_update_config(struct codec_mm_scatter_mgt *smgt)
        smgt->enable_slot_from_sys = g_scatter.enable_slot_from_sys;
        smgt->support_from_slot_sys = g_scatter.support_from_slot_sys;
        smgt->no_cache_size_M = g_scatter.no_cache_size_M;
+       smgt->no_alloc_from_sys = g_scatter.no_alloc_from_sys;
        return 0;
 }
 
@@ -2207,13 +2259,9 @@ static void codec_mm_scatter_cache_manage(
                        smgt->delay_free_timeout_jiffies64)) {
                        /*wait time out can free.*/
                        mms = smgt->cache_sc;
-                       if (mms) {      /*only free some 1M cache */
-                               int free_start = smgt->cached_pages - 256;
-
-                               if (free_start < smgt->keep_size_PAGE)
-                                       free_start = smgt->keep_size_PAGE;
-                               codec_mm_scatter_free_tail_pages(mms,
-                                       free_start);
+                       if (mms) {/*only free some 1M cache*/
+                               codec_mm_scatter_less_pages(mms,
+                                       256);
                        }
                        codec_mm_free_all_free_slots_in(smgt);
                        /*free some slots.*/
@@ -2481,6 +2529,7 @@ static struct mconfig codec_mm_sc_configs[] = {
        MC_PU32("enable_slot_from_sys",
                &g_scatter.enable_slot_from_sys),
        MC_PU32("no_cache_size_M", &g_scatter.no_cache_size_M),
+       MC_PU32("no_alloc_from_sys", &g_scatter.no_alloc_from_sys),
 };
 
 static struct mconfig_node codec_mm_sc;
@@ -2504,7 +2553,7 @@ int codec_mm_scatter_mgt_init(void)
        g_scatter.enable_slot_from_sys = smgt->enable_slot_from_sys;
        g_scatter.support_from_slot_sys = smgt->support_from_slot_sys;
        g_scatter.no_cache_size_M = smgt->no_cache_size_M;
-
+       g_scatter.no_alloc_from_sys = smgt->no_cache_size_M;
        INIT_REG_NODE_CONFIGS("media.codec_mm",
                &codec_mm_sc, "scatter",
                codec_mm_sc_configs,
index 54ead51..af83ff2 100644 (file)
 #include "vftrace.h"
 
 #define MAX_PROVIDER_NUM    32
-struct vframe_provider_s *provider_table[MAX_PROVIDER_NUM];
+static struct vframe_provider_s *provider_table[MAX_PROVIDER_NUM];
+static atomic_t provider_used = ATOMIC_INIT(0);
+
+#define providers_lock() atomic_inc(&provider_used)
+#define providers_unlock()     atomic_dec(&provider_used)
+#define providers_used()       atomic_read(&provider_used)
+
+static DEFINE_MUTEX(provider_table_mutex);
+#define TABLE_LOCK() mutex_lock(&provider_table_mutex)
+#define TABLE_UNLOCK() mutex_unlock(&provider_table_mutex)
+
+#define VFPROVIER_DEBUG
+#ifdef VFPROVIER_DEBUG
+static DEFINE_SPINLOCK(provider_lock);
+static const char *last_receiver;
+static const char *last_provider;
+void provider_update_caller(const char *receiver, const char *provider)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&provider_lock, flags);
+       last_receiver = receiver;
+       last_provider = provider;
+       spin_unlock_irqrestore(&provider_lock, flags);
+}
+
+void provider_print_last_info(void)
+{
+       unsigned long flags;
+       struct vframe_provider_s *p;
+       int i;
+
+       spin_lock_irqsave(&provider_lock, flags);
+       pr_info("last receiver: %s\n",
+               last_receiver ? last_receiver : "null");
+       pr_info("last provider: %s\n",
+               last_provider ? last_provider : "null");
+       pr_info("register provider:\n");
+       for (i = 0; i < MAX_PROVIDER_NUM; i++) {
+               p = provider_table[i];
+               if (p)
+                       pr_info("%s: user_cnt:%d\n", p->name,
+                       atomic_read(&p->use_cnt));
+       }
+       spin_unlock_irqrestore(&provider_lock, flags);
+}
+#else
+void provider_update_caller(
+       const char *receiver,
+       const char *provider) {return }
+void provider_print_last_info(void) {return}
+
+#endif
 
 int provider_list(char *buf)
 {
@@ -135,6 +187,7 @@ static int vf_provider_close(struct vframe_provider_s *prov)
        if (ret > CLOSED_CNT) {
                pr_err("**ERR***,release, provider %s not finised,%d, wait=%d\n",
                        prov->name, ret, wait_max);
+               provider_print_last_info();
        }
        return 0;
 }
@@ -208,11 +261,14 @@ int vf_reg_provider(struct vframe_provider_s *prov)
        prov->traceget = NULL;
        prov->traceput = NULL;
        atomic_set(&prov->use_cnt, 0);/*set it ready for use.*/
+       TABLE_LOCK();
        for (i = 0; i < MAX_PROVIDER_NUM; i++) {
                p = provider_table[i];
                if (p) {
-                       if (!strcmp(p->name, prov->name))
+                       if (!strcmp(p->name, prov->name)) {
+                               TABLE_UNLOCK();
                                return -1;
+                       }
                }
        }
        for (i = 0; i < MAX_PROVIDER_NUM; i++) {
@@ -221,6 +277,7 @@ int vf_reg_provider(struct vframe_provider_s *prov)
                        break;
                }
        }
+       TABLE_UNLOCK();
        if (i < MAX_PROVIDER_NUM) {
                vf_update_active_map();
                receiver = vf_get_receiver(prov->name);
@@ -253,18 +310,20 @@ void vf_unreg_provider(struct vframe_provider_s *prov)
        int i;
 
        for (i = 0; i < MAX_PROVIDER_NUM; i++) {
+               TABLE_LOCK();
                p = provider_table[i];
                if (p && !strcmp(p->name, prov->name)) {
+                       provider_table[i] = NULL;
+                       TABLE_UNLOCK();
                        if (p->traceget) {
-                               vftrace_free_trace(p->traceget);
+                               vftrace_free_trace(prov->traceget);
                                p->traceget = NULL;
                        }
                        if (p->traceput) {
-                               vftrace_free_trace(p->traceput);
+                               vftrace_free_trace(prov->traceput);
                                p->traceput = NULL;
                        }
                        vf_provider_close(prov);
-                       provider_table[i] = NULL;
                        if (vfm_debug_flag & 1)
                                pr_err("%s:%s\n", __func__, prov->name);
                        receiver = vf_get_receiver(prov->name);
@@ -281,6 +340,27 @@ void vf_unreg_provider(struct vframe_provider_s *prov)
                        vf_update_active_map();
                        break;
                }
+               TABLE_UNLOCK();
+       }
+       {
+       /*
+        * wait no one used provider,
+        * if some one have on used.
+        * the provider memory may free,
+        * become unreachable.
+        */
+               int cnt = 0;
+
+               while (providers_used()) {
+                       schedule();
+                       cnt++;
+                       if (cnt > 10000) {
+                               pr_err("unreg provider locked %s,%d!\n",
+                                       prov->name, cnt);
+                               provider_print_last_info();
+                               break;
+                       }
+               }
        }
 }
 EXPORT_SYMBOL(vf_unreg_provider);
@@ -316,9 +396,11 @@ void vf_ext_light_unreg_provider(struct vframe_provider_s *prov)
        int i;
 
        for (i = 0; i < MAX_PROVIDER_NUM; i++) {
+               TABLE_LOCK();
                p = provider_table[i];
                if (p && !strcmp(p->name, prov->name)) {
                        provider_table[i] = NULL;
+                       TABLE_UNLOCK();
                        if (vfm_debug_flag & 1)
                                pr_err("%s:%s\n", __func__, prov->name);
 
@@ -332,6 +414,7 @@ void vf_ext_light_unreg_provider(struct vframe_provider_s *prov)
                        vf_update_active_map();
                        break;
                }
+               TABLE_UNLOCK();
        }
 }
 EXPORT_SYMBOL(vf_ext_light_unreg_provider);
@@ -340,12 +423,14 @@ struct vframe_s *vf_peek(const char *receiver)
 {
        struct vframe_provider_s *vfp;
        struct vframe_s *vf = NULL;
+       providers_lock();
        vfp = vf_get_provider(receiver);
        if (use_provider(vfp)) {
                if (vfp->ops && vfp->ops->peek)
                        vf = vfp->ops->peek(vfp->op_arg);
                unuse_provider(vfp);
        }
+       providers_unlock();
        return vf;
 }
 EXPORT_SYMBOL(vf_peek);
@@ -355,14 +440,20 @@ struct vframe_s *vf_get(const char *receiver)
 
        struct vframe_provider_s *vfp;
        struct vframe_s *vf = NULL;
+       providers_lock();
        vfp = vf_get_provider(receiver);
+
        if (use_provider(vfp)) {
+               provider_update_caller(receiver, vfp->name);
                if (vfp->ops && vfp->ops->get)
                        vf = vfp->ops->get(vfp->op_arg);
                if (vf)
                        vftrace_info_in(vfp->traceget, vf);
                unuse_provider(vfp);
-       }
+       } else
+               provider_update_caller(receiver, NULL);
+
+       providers_unlock();
        return vf;
 }
 EXPORT_SYMBOL(vf_get);
@@ -370,15 +461,19 @@ EXPORT_SYMBOL(vf_get);
 void vf_put(struct vframe_s *vf, const char *receiver)
 {
        struct vframe_provider_s *vfp;
-
+       providers_lock();
        vfp = vf_get_provider(receiver);
        if (use_provider(vfp)) {
+               provider_update_caller(receiver, vfp->name);
                if (vfp->ops && vfp->ops->put)
                        vfp->ops->put(vf, vfp->op_arg);
                if (vf)
                        vftrace_info_in(vfp->traceput, vf);
                unuse_provider(vfp);
+       } else {
+               provider_update_caller(receiver, NULL);
        }
+       providers_unlock();
 }
 EXPORT_SYMBOL(vf_put);
 
@@ -386,12 +481,14 @@ int vf_get_states(struct vframe_provider_s *vfp,
        struct vframe_states *states)
 {
        int ret = -1;
-
+       providers_lock();
        if (use_provider(vfp)) {
+               provider_update_caller(NULL, vfp->name);
                if (vfp->ops && vfp->ops->vf_states)
                        ret = vfp->ops->vf_states(states, vfp->op_arg);
                unuse_provider(vfp);
        }
+       providers_unlock();
        return ret;
 }
 EXPORT_SYMBOL(vf_get_states);
index a6b6812..2bfda61 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/amlogic/media/frame_sync/tsync.h>
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include <linux/amlogic/media/registers/register.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
 
 
 u32 acc_apts_inc;
@@ -200,6 +201,19 @@ void timestamp_pcrscr_set_adj(s32 inc)
 }
 EXPORT_SYMBOL(timestamp_pcrscr_set_adj);
 
+void timestamp_pcrscr_set_adj_pcr(s32 inc)
+{
+       const struct vinfo_s *info = get_current_vinfo();
+
+       if (inc != 0) {
+               system_time_inc_adj =
+                       900 * info->sync_duration_den /
+                       (info->sync_duration_num*inc);
+       } else
+               system_time_inc_adj = 0;
+}
+EXPORT_SYMBOL(timestamp_pcrscr_set_adj_pcr);
+
 void timestamp_pcrscr_enable(u32 enable)
 {
        system_time_up = enable;
index 4868932..950df03 100644 (file)
@@ -330,7 +330,7 @@ u32 tsync_pcr_get_min_checkinpts(void)
        u32 last_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO);
        u32 last_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO);
 
-       if (last_checkin_apts > 0 && last_checkin_apts > 0)
+       if (last_checkin_vpts > 0 && last_checkin_apts > 0)
                return min(last_checkin_vpts, last_checkin_apts);
        else if (last_checkin_apts > 0)
                return last_checkin_apts;
@@ -407,7 +407,9 @@ void tsync_pcr_pcrscr_set(void)
        if (cur_pcr && !(tsync_pcr_inited_flag & complete_init_flag)
                && (min_checkinpts != 0)) {
                tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_PCR;
-               ref_pcr = cur_pcr - tsync_pcr_adj_value * 15;
+               if (cur_pcr > tsync_pcr_adj_value * 15)
+                       ref_pcr = cur_pcr - tsync_pcr_adj_value * 15;
+
                timestamp_pcrscr_set(ref_pcr);
                tsync_pcr_usepcr = 1;
 
@@ -431,12 +433,14 @@ void tsync_pcr_pcrscr_set(void)
                ref_pcr = first_apts;
 
                /* add it for dolby av sync */
-               if (cur_pcr > 0)
+               if (cur_pcr > tsync_apts_adj_value)
                        ref_pcr = cur_pcr - tsync_apts_adj_value;
 
                timestamp_pcrscr_set(ref_pcr);
                if (cur_pcr > 0)
                        tsync_pcr_usepcr = 1;
+               else
+                       tsync_pcr_usepcr = 0;
 
                timestamp_pcrscr_enable(1);
                pr_info
@@ -456,10 +460,14 @@ void tsync_pcr_pcrscr_set(void)
        if (first_vpts && !(tsync_pcr_inited_flag & complete_init_flag)
                && (min_checkinpts != 0)) {
                tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_VPTS;
-               ref_pcr = first_vpts - tsync_pcr_ref_latency * 15;
+               if (first_vpts > tsync_pcr_ref_latency * 15)
+                       ref_pcr = first_vpts - tsync_pcr_ref_latency * 15;
+
                timestamp_pcrscr_set(ref_pcr);
                if (cur_pcr > 0)
                        tsync_pcr_usepcr = 1;
+               else
+                       tsync_pcr_usepcr = 0;
 
                timestamp_pcrscr_enable(1);
                pr_info
@@ -1181,19 +1189,16 @@ static unsigned long tsync_pcr_check(void)
        }
 
        if (need_recovery && !tsync_pcr_vpause_flag) {
-               if (play_mode == PLAY_MODE_SLOW) {
-                       timestamp_pcrscr_set(timestamp_pcrscr_get() -
-                                       tsync_pcr_recovery_span);
-               } else if (play_mode == PLAY_MODE_FORCE_SLOW) {
-                       timestamp_pcrscr_set(timestamp_pcrscr_get() -
-                                       FORCE_RECOVERY_SPAN);
-               } else if (play_mode == PLAY_MODE_SPEED) {
-                       timestamp_pcrscr_set(timestamp_pcrscr_get() +
-                                       tsync_pcr_recovery_span);
-               } else if (play_mode == PLAY_MODE_FORCE_SPEED) {
-                       timestamp_pcrscr_set(timestamp_pcrscr_get() +
-                                       FORCE_RECOVERY_SPAN);
-               }
+               if (play_mode == PLAY_MODE_SLOW)
+                       timestamp_pcrscr_set_adj_pcr(-1);
+               else if (play_mode == PLAY_MODE_FORCE_SLOW)
+                       timestamp_pcrscr_set_adj_pcr(-2);
+               else if (play_mode == PLAY_MODE_SPEED)
+                       timestamp_pcrscr_set_adj_pcr(1);
+               else if (play_mode == PLAY_MODE_FORCE_SPEED)
+                       timestamp_pcrscr_set_adj_pcr(2);
+               else if (play_mode == PLAY_MODE_NORMAL)
+                       timestamp_pcrscr_set_adj_pcr(0);
        }
        /* } */
 
@@ -1294,6 +1299,7 @@ void tsync_pcr_stop(void)
                del_timer_sync(&tsync_pcr_check_timer);
                pr_info("[tsync_pcr_stop]PCRMASTER stop success.\n");
        }
+       timestamp_pcrscr_set(0);
        tsync_pcr_freerun_mode = 0;
        tsync_pcr_started = 0;
 }
index fa285c3..6f0e8ac 100644 (file)
@@ -95,6 +95,8 @@ int video_vsync = -ENXIO;
 #define DEBUG_TMP 0
 
 static int video_global_output = 1;
+/*  video_pause_global: 0 is play, 1 is pause, 2 is invalid */
+static int video_pause_global = 1;
 
 #ifdef CONFIG_GE2D_KEEP_FRAME
 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
@@ -764,7 +766,7 @@ int get_video0_frame_info(struct vframe_s *vf)
 }
 EXPORT_SYMBOL(get_video0_frame_info);
 
-static struct vframe_s vf_local;
+static struct vframe_s vf_local, vf_local2;
 static u32 vsync_pts_inc;
 static u32 vsync_pts_inc_scale;
 static u32 vsync_pts_inc_scale_base = 1;
@@ -808,6 +810,7 @@ u32 trickmode_fffb;
 atomic_t trickmode_framedone = ATOMIC_INIT(0);
 atomic_t video_sizechange = ATOMIC_INIT(0);
 atomic_t video_unreg_flag = ATOMIC_INIT(0);
+atomic_t video_inirq_flag = ATOMIC_INIT(0);
 atomic_t video_pause_flag = ATOMIC_INIT(0);
 int trickmode_duration;
 int trickmode_duration_count;
@@ -1503,7 +1506,6 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls,
                                *rs = *ls + (height >> 1);
                                *re = *le + (height >> 1);
                        }
-               }
                if ((process_3d_type & MODE_3D_TO_2D_MASK)
                    || (process_3d_type & MODE_3D_OUT_LR)) {
                        /* same width,half height */
@@ -1511,6 +1513,7 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls,
                        *le = zoom_end_y_lines;
                        *rs = zoom_start_y_lines + (height >> 1);
                        *re = zoom_end_y_lines + (height >> 1);
+                       }
                }
                break;
        case VPP_3D_MODE_LR:
@@ -1562,7 +1565,7 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls,
 #endif
 static void zoom_display_horz(int hscale)
 {
-       u32 ls, le, rs, re;
+       u32 ls = 0, le = 0, rs = 0, re = 0;
 #ifdef TV_REVERSE
        int content_w, content_l, content_r;
 #endif
@@ -1622,7 +1625,8 @@ static void zoom_display_horz(int hscale)
 
                if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
                        VSYNC_WR_MPEG_REG(AFBC_SIZE_OUT,
-                               (VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT) & 0xffff) |
+                               (VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT)
+                               & 0xffff) |
                                (((r_aligned - l_aligned) / h_skip) << 16));
                }
 #ifdef TV_REVERSE
@@ -1681,25 +1685,28 @@ static void vd2_zoom_display_horz(int hscale)
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
                int l_aligned;
                int r_aligned;
+               int h_skip = cur_frame_par->hscale_skip_count + 1;
 
                if ((zoom2_start_x_lines > 0) ||
                (zoom2_end_x_lines < ori2_end_x_lines)) {
                        l_aligned = round_down(ori2_start_x_lines, 32);
                        r_aligned = round_up(ori2_end_x_lines + 1, 32);
                } else {
-                       l_aligned = round_down(ori2_start_x_lines, 32);
-                       r_aligned = round_up(ori2_end_x_lines + 1, 32);
+                       l_aligned = round_down(zoom2_start_x_lines, 32);
+                       r_aligned = round_up(zoom2_end_x_lines + 1, 32);
                }
                VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_W,
-                         ((r_aligned - l_aligned) << 16) |
-                         (r_aligned / 2 - l_aligned / 2));
+                         (((r_aligned - l_aligned) / h_skip) << 16) |
+                         ((r_aligned / 2 - l_aligned / 2) / h_skip));
+
                VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_HOR_SCOPE,
                          ((l_aligned / 32) << 16) |
                          ((r_aligned / 32) - 1));
                if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
                        VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_OUT,
-                               (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT) &
-                               0xffff) | ((r_aligned - l_aligned) << 16));
+                               (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT)
+                               & 0xffff) |
+                               (((r_aligned - l_aligned) / h_skip) << 16));
                }
 #ifdef TV_REVERSE
                if (reverse) {
@@ -1909,13 +1916,18 @@ static void vd2_zoom_display_vert(void)
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
                int t_aligned;
                int b_aligned;
-
+               int ori_t_aligned;
+               int ori_b_aligned;
+               int v_skip = cur_frame_par->vscale_skip_count + 1;
                t_aligned = round_down(zoom2_start_y_lines, 4);
                b_aligned = round_up(zoom2_end_y_lines + 1, 4);
 
+               ori_t_aligned = round_down(ori2_start_y_lines, 4);
+               ori_b_aligned = round_up(ori2_end_y_lines + 1, 4);
+
                /* TODO: afbc setting only support 420 for now */
                VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_H,
-                   (b_aligned - t_aligned) / 2);
+                  (b_aligned - t_aligned) / 2 / v_skip);
 
                VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_VER_SCOPE,
                    ((t_aligned / 4) << 16) |
@@ -1926,12 +1938,14 @@ static void vd2_zoom_display_vert(void)
                    (zoom2_end_y_lines - t_aligned));
 
                VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_IN,
-                       (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_IN) & 0xffff0000) |
-                       (b_aligned - t_aligned));
+                       (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_IN)
+                       & 0xffff0000) |
+                       (ori_b_aligned - ori_t_aligned));
                if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
                        VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_OUT,
-                       (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT) & 0xffff0000)
-                       | (b_aligned - t_aligned));
+                       (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT)
+                       & 0xffff0000) |
+                       ((b_aligned - t_aligned) / v_skip));
                }
        }
 }
@@ -2593,6 +2607,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
        u32 type = vf->type, bit_mode = 0;
        bool vf_with_el = false;
 
+       pr_debug("set dcu for vd1 %p, type:0x%x\n", vf, type);
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
                if (frame_par->nocomp)
                        type &= ~VIDTYPE_COMPRESS;
@@ -2642,10 +2657,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
                                                VFORMATTER_EN);
                                else
                                        VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL,
-                                       (is_dolby_vision_on() ?
-                                       HFORMATTER_REPEAT |
-                                       (0xc << VFORMATTER_INIPHASE_BIT)  :
-                                               HFORMATTER_RRT_PIXEL0) |
+                                               HFORMATTER_REPEAT |
+                                       (0xc << VFORMATTER_INIPHASE_BIT) |
                                                HFORMATTER_YC_RATIO_2_1 |
                                                HFORMATTER_EN |
                                                VFORMATTER_RPTLINE0_EN |
@@ -2668,15 +2681,13 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
                                                VFORMATTER_EN);
                                else
                                        VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL,
-                                       (is_dolby_vision_on() ?
-                                       HFORMATTER_REPEAT |
-                                       (0xc << VFORMATTER_INIPHASE_BIT)  :
-                                       HFORMATTER_RRT_PIXEL0) |
-                                       HFORMATTER_YC_RATIO_2_1 |
-                                       HFORMATTER_EN |
-                                       VFORMATTER_RPTLINE0_EN |
-                                       (0x8 << VFORMATTER_PHASE_BIT) |
-                                       VFORMATTER_EN);
+                                               HFORMATTER_REPEAT |
+                                       (0xc << VFORMATTER_INIPHASE_BIT) |
+                                               HFORMATTER_YC_RATIO_2_1 |
+                                               HFORMATTER_EN |
+                                               VFORMATTER_RPTLINE0_EN |
+                                               (0x8 << VFORMATTER_PHASE_BIT) |
+                                               VFORMATTER_EN);
                        }
                        if ((VSYNC_RD_MPEG_REG(DI_POST_CTRL) & 0x100) == 0)
                                VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0 +
@@ -2684,6 +2695,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
 
                        VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0 +
                                        cur_dev->viu_off, 1, 20, 1);
+                       VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG +
+                                        cur_dev->viu_off, 0);
                        return;
 
                } else {
@@ -2702,6 +2715,10 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
                        }
                        VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG3,
                                (bit_mode&0x3), 8, 2);
+                       if ((vf->type & VIDTYPE_MVC) && (!vf_with_el))
+                               VSYNC_WR_MPEG_REG_BITS(
+                                       VD2_IF0_GEN_REG3,
+                                       (bit_mode & 0x3), 8, 2);
                        VSYNC_WR_MPEG_REG_BITS(DI_IF1_GEN_REG3,
                                (bit_mode&0x3), 8, 2);
                        if (is_meson_txl_cpu() || is_meson_txlx_cpu())
@@ -2836,7 +2853,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
                                ((type & VIDTYPE_VIU_422) ?
                                0 :
                                VFORMATTER_EN));
-                       pr_info("\tvd1 set fmt(dovi tv)\n");
+                       pr_debug("\tvd1 set fmt(dovi tv)\n");
                } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() ||
                        is_meson_txlx_cpu()) {
                        if ((vf->width >= 3840) &&
@@ -3128,9 +3145,8 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
        static const u32 vpat[] = { 0, 0x8, 0x9, 0xa, 0xb, 0xc };
        u32 u, v;
        u32 type = vf->type, bit_mode = 0;
-       u32 skip_count = 0;
 
-       pr_info("set dcu for vd2 %p, type:0x%x\n", vf, type);
+       pr_debug("set dcu for vd2 %p, type:0x%x\n", vf, type);
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
                if (type & VIDTYPE_COMPRESS) {
                        r = (3 << 24) |
@@ -3138,9 +3154,9 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
                            (1 << 14) | /*burst1 1*/
                            (vf->bitdepth & BITDEPTH_MASK);
 
-                       if (skip_count)
+                       if (frame_par->hscale_skip_count)
                                r |= 0x33;
-                       if (skip_count)
+                       if (frame_par->vscale_skip_count)
                                r |= 0xcc;
 
 #ifdef TV_REVERSE
@@ -3219,6 +3235,8 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
 #endif
                        VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL1 +
                                        cur_dev->viu_off, 1, 1, 1);
+                       VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG +
+                                        cur_dev->viu_off, 0);
                        return;
                } else {
                        if ((vf->bitdepth & BITDEPTH_Y10) &&
@@ -3268,7 +3286,7 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
                }
        }
 
-       if (skip_count)
+       if (frame_par->hscale_skip_count)
                r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG;
 
        VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, r);
@@ -3307,7 +3325,7 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
                                (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
                                << VFORMATTER_PHASE_BIT) |
                                VFORMATTER_EN);
-                       pr_info("\tvd2 set fmt(dovi tv)\n");
+                       pr_debug("\tvd2 set fmt(dovi tv)\n");
                } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() ||
                is_meson_txlx_cpu()) {
                        if ((vf->width >= 3840) &&
@@ -3394,13 +3412,13 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
                }
        }
        /* LOOP/SKIP pattern */
-       pat = vpat[skip_count];
+       pat = vpat[frame_par->vscale_skip_count];
 
        if (type & VIDTYPE_VIU_FIELD) {
                loop = 0;
 
        if (type & VIDTYPE_INTERLACE)
-               pat = vpat[skip_count >> 1];
+               pat = vpat[frame_par->vscale_skip_count >> 1];
        } else if (type & VIDTYPE_MVC) {
                loop = 0x11;
                pat = 0x80;
@@ -3652,10 +3670,12 @@ static inline bool vpts_expire(struct vframe_s *cur_vf,
                                tsync_avevent_locked(VIDEO_TSTAMP_DISCONTINUITY,
                                                     pts);
 
-                       pr_info("discontinue, systime=0x%x vpts=0x%x next_vf->pts = 0x%x\n",
-                               systime,
-                               pts,
-                               next_vf->pts);
+                       /* pr_info("discontinue,
+                        *   systime=0x%x vpts=0x%x next_vf->pts = 0x%x\n",
+                        *      systime,
+                        *      pts,
+                        *      next_vf->pts);
+                        */
 
                        /* pts==0 is a keep frame maybe. */
                        if (systime > next_vf->pts || next_vf->pts == 0)
@@ -4128,10 +4148,113 @@ static void dmc_adjust_for_mali_vpu(unsigned int width, unsigned int height)
        }
 }
 
+void correct_vd1_mif_size_for_DV(struct vpp_frame_par_s *par)
+{
+       u32 aligned_mask = 0xfffffffe;
+       u32 old_len;
+
+       if ((is_dolby_vision_on() == true) &&
+               (par->VPP_line_in_length_ > 0)) {
+               if (cur_dispbuf2) {
+                       /*
+                        *if (cur_dispbuf2->type
+                        *      & VIDTYPE_COMPRESS)
+                        *      aligned_mask = 0xffffffc0;
+                        *else
+                        */
+                       aligned_mask = 0xfffffffc;
+               }
+#if 0 /* def TV_REVERSE */
+               if (reverse) {
+                       par->VPP_line_in_length_
+                               &= 0xfffffffe;
+                       par->VPP_hd_end_lines_
+                               &= 0xfffffffe;
+                       par->VPP_hd_start_lines_ =
+                               par->VPP_hd_end_lines_ + 1
+                               - par->VPP_line_in_length_;
+               } else
+#endif
+               {
+               par->VPP_line_in_length_
+                       &= aligned_mask;
+               par->VPP_hd_start_lines_
+                       &= aligned_mask;
+               par->VPP_hd_end_lines_ =
+                       par->VPP_hd_start_lines_ +
+                       par->VPP_line_in_length_ - 1;
+               /* if have el layer, need 2 pixel align by height */
+               if (cur_dispbuf2) {
+                       old_len =
+                               par->VPP_vd_end_lines_ -
+                               par->VPP_vd_start_lines_ + 1;
+                       if (old_len & 1)
+                               par->VPP_vd_end_lines_--;
+                       if (par->VPP_vd_start_lines_ & 1) {
+                               par->VPP_vd_start_lines_--;
+                               par->VPP_vd_end_lines_--;
+                       }
+                       old_len =
+                               par->VPP_vd_end_lines_ -
+                               par->VPP_vd_start_lines_ + 1;
+                       old_len = old_len >> par->vscale_skip_count;
+                       if (par->VPP_pic_in_height_ < old_len)
+                               par->VPP_pic_in_height_ = old_len;
+               }
+               }
+       }
+}
+
+#if DEBUG_TMP
+void correct_vd2_mif_size_for_DV(
+       struct vpp_frame_par_s *par,
+       struct vframe_s *bl_vf)
+{
+       int width_bl, width_el, line_in_length;
+       int shift;
+
+       if ((is_dolby_vision_on() == true) &&
+               (par->VPP_line_in_length_ > 0)) {
+               width_el = (cur_dispbuf2->type
+                       & VIDTYPE_COMPRESS) ?
+                       cur_dispbuf2->compWidth :
+                       cur_dispbuf2->width;
+               width_bl = (bl_vf->type
+                       & VIDTYPE_COMPRESS) ?
+                       bl_vf->compWidth :
+                       bl_vf->width;
+               if (width_el >= width_bl)
+                       shift = 0;
+               else
+                       shift = 1;
+               zoom2_start_x_lines =
+                       par->VPP_hd_start_lines_ >> shift;
+               line_in_length =
+                       par->VPP_line_in_length_ >> shift;
+               zoom2_end_x_lines
+                       &= 0xfffffffe;
+               line_in_length
+                       &= 0xfffffffe;
+               if (line_in_length > 1)
+                       zoom2_end_x_lines =
+                               zoom2_start_x_lines +
+                               line_in_length - 1;
+               else
+                       zoom2_end_x_lines = zoom2_start_x_lines;
+
+               zoom2_start_y_lines =
+                       par->VPP_vd_start_lines_ >> shift;
+               if (zoom2_start_y_lines >= zoom2_end_y_lines)
+                       zoom2_end_y_lines = zoom2_start_y_lines;
+               /* TODO: if el len is 0, need disable bl */
+       }
+}
+#endif
+
 #ifdef FIQ_VSYNC
-void vsync_fisr(void)
+void vsync_fisr_in(void)
 #else
-static irqreturn_t vsync_isr(int irq, void *dev_id)
+static irqreturn_t vsync_isr_in(int irq, void *dev_id)
 #endif
 {
        int hold_line;
@@ -4152,10 +4275,11 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
 #endif
 #if DEBUG_TMP
        struct vframe_s *toggle_vf = NULL;
-       int ret;
 #endif
+       struct vframe_s *toggle_frame = NULL;
        int video1_off_req = 0;
        struct vframe_s *cur_dispbuf_back = cur_dispbuf;
+       static  struct vframe_s *pause_vf;
 
        if (debug_flag & DEBUG_FLAG_VSYNC_DONONE)
                return IRQ_HANDLED;
@@ -4263,9 +4387,6 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
        /* check video frame before VECM process */
        if (is_dolby_vision_enable() && vf)
                dolby_vision_check_hdr10(vf);
-#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
-       amvecm_on_vs(vf);
-#endif
 #endif
 
 #ifdef CONFIG_TVIN_VDIN
@@ -4340,7 +4461,9 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
 
        if (atomic_read(&video_unreg_flag))
                goto exit;
-       if (atomic_read(&video_pause_flag))
+       if (atomic_read(&video_pause_flag)
+               && (!((video_global_output == 1)
+               && (video_enabled != video_status_saved))))
                goto exit;
 #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
        if (is_vsync_rdma_enable())
@@ -4484,6 +4607,11 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
 
 #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
                        refresh_on_vs(vf);
+                       if (amvecm_on_vs(
+                               (cur_dispbuf != &vf_local)
+                               ? cur_dispbuf : NULL,
+                               vf, CSC_FLAG_CHECK_OUTPUT) == 1)
+                               break;
 #endif
 
                        if (is_dolby_vision_enable()
@@ -4498,12 +4626,12 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
                         */
                        if (vf && hdmiin_frame_check &&
                                (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) &&
-                               (video_vf_disp_mode_get(vf) !=
-                               VFRAME_DISP_MODE_OK) &&
+                               (video_vf_disp_mode_get(vf) ==
+                               VFRAME_DISP_MODE_UNKNOWN) &&
                                (hdmiin_frame_check_cnt++ < 10))
                                break;
-
-                       hdmiin_frame_check_cnt = 0;
+                       else
+                               hdmiin_frame_check_cnt = 0;
 
                        vf = video_vf_get();
                        if (!vf)
@@ -4528,13 +4656,15 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
                                }
                        }
                        vsync_toggle_frame(vf);
-#if DEBUG_TMP
-                       if (is_dolby_vision_enable())
-                               toggle_vf = dolby_vision_toggle_frame(vf);
-                       else
-#endif
+                       toggle_frame = vf;
+                       if (0/*is_dolby_vision_enable()*/) { /*DEBUG_TMP*/
+                               //toggle_vf = dolby_vision_toggle_frame(vf);
+                               video_pause_global = 0;
+                       } else {
                                cur_dispbuf2 = NULL;
-
+                               video_pause_global = 2;
+                               pause_vf = NULL;
+                       }
                        if (trickmode_fffb == 1) {
                                trickmode_vpts = vf->pts;
 #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
@@ -4594,11 +4724,20 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
                                        if (is_dolby_vision_enable()
                                        && dolby_vision_need_wait())
                                                break;
+#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
+                                       refresh_on_vs(vf);
+                                       if (amvecm_on_vs(
+                                               (cur_dispbuf != &vf_local)
+                                               ? cur_dispbuf : NULL,
+                                               vf, CSC_FLAG_CHECK_OUTPUT) == 1)
+                                               break;
+#endif
 #endif
                                        vf = video_vf_get();
                                        if (!vf)
                                                break;
                                        vsync_toggle_frame(vf);
+                                       toggle_frame = vf;
 #if DEBUG_TMP
                                        if (is_dolby_vision_enable())
                                                toggle_vf =
@@ -4633,8 +4772,23 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
                                                                cur_dispbuf);
                                } else
                                        vsync_toggle_frame(cur_dispbuf);
+                               /*DEBUG_TMP*/
+                               if (0/*is_dolby_vision_enable()*/) {
+                                       pause_vf = cur_dispbuf;
+                                       video_pause_global = 1;
+                               } else {
+                                       pause_vf = NULL;
+                                       video_pause_global = 2;
+                               }
                        }
-
+#if DEBUG_TMP
+                       if (pause_vf && (video_pause_global == 1)
+                           && is_dolby_vision_enable()) {
+                               toggle_vf = pause_vf;
+                               dolby_vision_parse_metadata(cur_dispbuf, true);
+                               dolby_vision_set_toggle_flag(1);
+                       }
+#endif
                        break;
                }
 
@@ -4657,22 +4811,50 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
 
 SET_FILTER:
 #if DEBUG_TMP
-       if (is_dolby_vision_enable()) {
-               u32 skip_mode = 0;
-
-               if (cur_frame_par)
-                       skip_mode =
-                       (cur_frame_par->hscale_skip_count << 16)
-                       | cur_frame_par->vscale_skip_count;
-               dolby_vision_process(toggle_vf, skip_mode);
-               dolby_vision_update_setting();
-       }
+#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
+       amvecm_on_vs(
+               (cur_dispbuf != &vf_local) ? cur_dispbuf : NULL,
+               toggle_frame,
+               toggle_frame ? CSC_FLAG_TOGGLE_FRAME : 0);
+#endif
 #endif
        /* filter setting management */
        if ((frame_par_ready_to_set) || (frame_par_force_to_set)) {
                cur_frame_par = next_frame_par;
                frame_par_di_set = 1;
        }
+
+#if DEBUG_TMP
+       if (is_dolby_vision_enable()) {
+               u32 frame_size = 0, h_size, v_size;
+
+               if (cur_frame_par) {
+                       if (cur_frame_par->VPP_hd_start_lines_
+                               >=  cur_frame_par->VPP_hd_end_lines_)
+                               h_size = 0;
+                       else
+                               h_size = cur_frame_par->VPP_hd_end_lines_
+                               - cur_frame_par->VPP_hd_start_lines_ + 1;
+                       h_size /= (cur_frame_par->hscale_skip_count + 1);
+                       if (cur_frame_par->VPP_vd_start_lines_
+                               >=  cur_frame_par->VPP_vd_end_lines_)
+                               v_size = 0;
+                       else
+                               v_size = cur_frame_par->VPP_vd_end_lines_
+                               - cur_frame_par->VPP_vd_start_lines_ + 1;
+                       v_size /= (cur_frame_par->vscale_skip_count + 1);
+                       frame_size = (h_size << 16) | v_size;
+               } else if (toggle_vf) {
+                       h_size = (toggle_vf->type & VIDTYPE_COMPRESS) ?
+                               toggle_vf->compWidth : toggle_vf->width;
+                       v_size = (toggle_vf->type & VIDTYPE_COMPRESS) ?
+                               toggle_vf->compHeight : toggle_vf->height;
+                       frame_size = (h_size << 16) | v_size;
+               }
+               dolby_vision_process(toggle_vf, frame_size);
+               dolby_vision_update_setting();
+       }
+#endif
        if ((platform_type == 1) || (platform_type == 0)) {
                if (mode_3d_changed) {
                        mode_3d_changed = 0;
@@ -4880,7 +5062,7 @@ SET_FILTER:
 
                if (cur_dispbuf) {
                        u32 zoom_start_y, zoom_end_y;
-
+                       correct_vd1_mif_size_for_DV(cur_frame_par);
                        if (cur_dispbuf->type & VIDTYPE_INTERLACE) {
                                if (cur_dispbuf->type & VIDTYPE_VIU_FIELD) {
                                        zoom_start_y =
@@ -4929,9 +5111,11 @@ SET_FILTER:
                        if (is_dolby_vision_enable() && cur_dispbuf2) {
                                zoom2_start_x_lines = ori2_start_x_lines;
                                zoom2_end_x_lines = ori2_end_x_lines;
-                               vd2_zoom_display_horz(0);
                                zoom2_start_y_lines = ori2_start_y_lines;
                                zoom2_end_y_lines = ori2_end_y_lines;
+                               correct_vd2_mif_size_for_DV(
+                                       cur_frame_par, cur_dispbuf);
+                               vd2_zoom_display_horz(0);
                                vd2_zoom_display_vert();
                        }
 #endif
@@ -5108,6 +5292,13 @@ SET_FILTER:
                                cur_frame_par->supsc0_vert_ratio) & 0x1fff));
                }
 #endif
+               /* work around to cut the last green line*/
+                       /*when two layer dv display and do vskip */
+               if (is_dolby_vision_on() &&
+                       (cur_frame_par->vscale_skip_count > 0)
+                       && cur_dispbuf2
+                       && (cur_frame_par->VPP_pic_in_height_ > 0))
+                       cur_frame_par->VPP_pic_in_height_--;
                VSYNC_WR_MPEG_REG(VPP_PIC_IN_HEIGHT + cur_dev->vpp_off,
                                  cur_frame_par->VPP_pic_in_height_);
 
@@ -5397,6 +5588,9 @@ SET_FILTER:
                if (debug_flag & DEBUG_FLAG_BLACKOUT)
                        pr_info("AFBC off now.\n");
                VSYNC_WR_MPEG_REG(AFBC_ENABLE, 0);
+               VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0);
+               VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG, 0);
+               VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0);
        }
 
 #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
@@ -5461,6 +5655,24 @@ SET_FILTER:
 }
 
 
+#ifdef FIQ_VSYNC
+void vsync_fisr(void)
+{
+       atomic_set(&video_inirq_flag, 1);
+       vsync_fisr_in();
+       atomic_set(&video_inirq_flag, 0);
+}
+#else
+static irqreturn_t vsync_isr(int irq, void *dev_id)
+{
+       irqreturn_t ret;
+
+       atomic_set(&video_inirq_flag, 1);
+       ret = vsync_isr_in(irq, dev_id);
+       atomic_set(&video_inirq_flag, 0);
+       return ret;
+}
+#endif
 
 
 /*********************************************************
@@ -5554,11 +5766,14 @@ EXPORT_SYMBOL(query_video_status);
 static void video_vf_unreg_provider(void)
 {
        ulong flags;
+       struct vframe_s *el_vf = NULL;
 
        new_frame_count = 0;
        first_frame_toggled = 0;
 
        atomic_set(&video_unreg_flag, 1);
+       while (atomic_read(&video_inirq_flag) > 0)
+               schedule();
        spin_lock_irqsave(&lock, flags);
 
 #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
@@ -5574,10 +5789,15 @@ static void video_vf_unreg_provider(void)
                cur_dispbuf = &vf_local;
                cur_dispbuf->video_angle = 0;
        }
-#if DEBUG_TMP
-       if (is_dolby_vision_enable())
+       if (0/*is_dolby_vision_enable()*/) {/*DEBUG_TMP*/
+               if (cur_dispbuf2 == &vf_local2)
+                       cur_dispbuf2 = NULL;
+               else if (cur_dispbuf2 != NULL) {
+                       vf_local2 = *cur_dispbuf2;
+                       el_vf = &vf_local2;
+               }
                cur_dispbuf2 = NULL;
-#endif
+       }
        if (trickmode_fffb) {
                atomic_set(&trickmode_framedone, 0);
                to_notify_trick_wait = false;
@@ -5599,7 +5819,7 @@ static void video_vf_unreg_provider(void)
        if (cur_dispbuf) {
                /* TODO: mod gate */
                /* switch_mod_gate_by_name("ge2d", 1); */
-               vf_keep_current(cur_dispbuf);
+               vf_keep_current(cur_dispbuf, el_vf);
                /* TODO: mod gate */
                /* switch_mod_gate_by_name("ge2d", 0); */
        }
@@ -5608,7 +5828,7 @@ static void video_vf_unreg_provider(void)
 #else
        /* if (!trickmode_fffb) */
        if (cur_dispbuf)
-               vf_keep_current(cur_dispbuf);
+               vf_keep_current(cur_dispbuf, el_vf);
        if (hdmi_in_onvideo == 0)
                tsync_avevent(VIDEO_STOP, 0);
 #endif
index a4ae093..78e3f13 100644 (file)
@@ -66,6 +66,8 @@ static unsigned long keep_y_addr, keep_u_addr, keep_v_addr;
 static int keep_video_on;
 static int keep_id;
 static int keep_head_id;
+static int keep_el_id;
+static int keep_el_head_id;
 
 #define Y_BUFFER_SIZE   0x400000       /* for 1920*1088 */
 #define U_BUFFER_SIZE   0x100000       /* compatible with NV21 */
@@ -602,8 +604,9 @@ static int canvas_dup(ulong dst, ulong src_paddr, ulong size)
 #ifdef RESERVE_CLR_FRAME
 static int free_alloced_keep_buffer(void)
 {
-       pr_info("free_alloced_keep_buffer %p.%p.%p\n",
+       /*pr_info("free_alloced_keep_buffer %p.%p.%p\n",
                (void *)keep_y_addr, (void *)keep_u_addr, (void *)keep_v_addr);
+               */
        if (keep_y_addr) {
                codec_mm_free_for_dma(MEM_NAME, keep_y_addr);
                keep_y_addr = 0;
@@ -690,9 +693,8 @@ void try_free_keep_video(int flags)
        int free_scatter_keeper = flags & 0x1;
 
        if (keep_video_on || free_scatter_keeper) {
-               pr_info("disbled keep video before free keep buffer.\n");
+               /*pr_info("disbled keep video before free keep buffer.\n");*/
                keep_video_on = 0;
-               update_cur_dispbuf(NULL);
                if (!get_video_enabled()) {
                        /*if not disable video,changed to 2 for */
                        pr_info("disbled video for next before free keep buffer!\n");
@@ -701,46 +703,101 @@ void try_free_keep_video(int flags)
                        safe_disble_videolayer();
                }
        }
-       if (free_scatter_keeper && keep_id > 0) {
-               pr_info("try_free_keep_video keepid\n");
-               codec_mm_keeper_unmask_keeper(keep_id, 0);
-               keep_id = -1;
-       }
-       if (free_scatter_keeper && keep_head_id > 0) {
-               pr_info("try_free_keep_video keep_head_id\n");
-               codec_mm_keeper_unmask_keeper(keep_head_id, 0);
-               keep_head_id = -1;
-       }
        mutex_lock(&video_keeper_mutex);
+       video_keeper_new_frame_notify();
        free_alloced_keep_buffer();
        mutex_unlock(&video_keeper_mutex);
-
 }
 EXPORT_SYMBOL(try_free_keep_video);
 
 #endif
 
+static void video_keeper_update_keeper_mem(
+       void *mem_handle, int type,
+       int *id)
+{
+       int ret;
+       int old_id = *id;
+
+       if (!mem_handle)
+               return;
+       ret = codec_mm_keeper_mask_keep_mem(mem_handle,
+               type);
+       if (ret > 0) {
+               if (old_id > 0 && ret != old_id) {
+                       /*wait 80 ms for vsync post.*/
+                       codec_mm_keeper_unmask_keeper(old_id, 120);
+               }
+               *id = ret;
+       }
+}
+static void video_keeper_frame_keep_locked(
+       struct vframe_s *cur_dispbuf,
+       struct vframe_s *cur_dispbuf_el)
+{
+       int type = MEM_TYPE_CODEC_MM;
+
+       if (cur_dispbuf->type & VIDTYPE_SCATTER)
+               type = MEM_TYPE_CODEC_MM_SCATTER;
+       video_keeper_update_keeper_mem(
+               cur_dispbuf->mem_handle,
+               type,
+               &keep_id);
+       video_keeper_update_keeper_mem(
+               cur_dispbuf->mem_head_handle,
+               MEM_TYPE_CODEC_MM,
+               &keep_head_id);
+       if (cur_dispbuf_el) {
+               if (cur_dispbuf->type & VIDTYPE_SCATTER)
+                       type = MEM_TYPE_CODEC_MM_SCATTER;
+               else
+                       type = MEM_TYPE_CODEC_MM;
+               video_keeper_update_keeper_mem(
+                       cur_dispbuf_el->mem_handle,
+                       type,
+                       &keep_el_id);
+               video_keeper_update_keeper_mem(
+                       cur_dispbuf_el->mem_head_handle,
+                       MEM_TYPE_CODEC_MM,
+                       &keep_el_head_id);
+       }
+}
+
+/*
+ * call in irq.
+ *don't used mutex
+ */
 void video_keeper_new_frame_notify(void)
 {
        if (keep_video_on) {
-               pr_info("new toggle keep_id\n");
+               pr_info("new frame show, free keeper\n");
                keep_video_on = 0;
        }
        if (keep_id > 0) {
                /*wait 80 ms for vsync post.*/
-               pr_info("new frame show, free keeper\n");
                codec_mm_keeper_unmask_keeper(keep_id, 120);
                keep_id = -1;
        }
        if (keep_head_id > 0) {
                /*wait 80 ms for vsync post.*/
-               pr_info("new frame show, free keeper head\n");
                codec_mm_keeper_unmask_keeper(keep_head_id, 120);
                keep_head_id = -1;
        }
+       if (keep_el_id > 0) {
+               /*wait 80 ms for vsync post.*/
+               codec_mm_keeper_unmask_keeper(keep_el_id, 120);
+               keep_el_id = -1;
+       }
+       if (keep_el_head_id > 0) {
+               /*wait 80 ms for vsync post.*/
+               codec_mm_keeper_unmask_keeper(keep_el_head_id, 120);
+               keep_el_head_id = -1;
+       }
        return;
 }
-static unsigned int vf_keep_current_locked(struct vframe_s *cur_dispbuf)
+static unsigned int vf_keep_current_locked(
+       struct vframe_s *cur_dispbuf,
+       struct vframe_s *cur_dispbuf_el)
 {
        u32 cur_index;
        u32 y_index, u_index, v_index;
@@ -777,36 +834,8 @@ static unsigned int vf_keep_current_locked(struct vframe_s *cur_dispbuf)
                pr_info("keep exit is skip VPP_VD1_POSTBLEND\n");
                return 0;
        }
-       if (1) {
-               int ret;
-               int old_keep = keep_id;
-               int old_head_keep = keep_head_id;
-               int type = MEM_TYPE_CODEC_MM;
-
-               if (cur_dispbuf->type & VIDTYPE_SCATTER)
-                       type = MEM_TYPE_CODEC_MM_SCATTER;
-               ret = codec_mm_keeper_mask_keep_mem(cur_dispbuf->mem_handle,
-                       type);
-               if (ret > 0) {
-                       keep_id = ret;
-                       if (old_keep > 0 && keep_id != old_keep) {
-                               /*wait 80 ms for vsync post.*/
-                               codec_mm_keeper_unmask_keeper(old_keep, 120);
-                       }
-               }
-               ret = codec_mm_keeper_mask_keep_mem(
-                       cur_dispbuf->mem_head_handle,
-                       MEM_TYPE_CODEC_MM);
-               if (ret > 0) {
-                       keep_head_id = ret;
-                       if (old_head_keep > 0 &&
-                                        keep_head_id != old_head_keep) {
-                               /*wait 80 ms for vsync post.*/
-                               codec_mm_keeper_unmask_keeper(old_head_keep,
-                                        120);
-                       }
-               }
-       }
+       video_keeper_frame_keep_locked(cur_dispbuf,
+               cur_dispbuf_el);
 
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
        if (codec_mm_video_tvp_enabled()) {
@@ -999,12 +1028,15 @@ static unsigned int vf_keep_current_locked(struct vframe_s *cur_dispbuf)
        return 0;
 
 }
-unsigned int vf_keep_current(struct vframe_s *cur_dispbuf)
+unsigned int vf_keep_current(
+       struct vframe_s *cur_dispbuf,
+       struct vframe_s *cur_dispbuf2)
 {
        unsigned int ret;
 
        mutex_lock(&video_keeper_mutex);
-       ret = vf_keep_current_locked(cur_dispbuf);
+       ret = vf_keep_current_locked(cur_dispbuf,
+                       cur_dispbuf2);
        mutex_unlock(&video_keeper_mutex);
        return ret;
 }
index 0cf1dc3..40b045f 100644 (file)
@@ -1803,6 +1803,11 @@ static void vpp_set_scaler(u32 process_3d_type, u32 src_width,
                        next_frame_par->supsc1_hori_ratio = 0;
                else
                        next_frame_par->supsc1_hori_ratio = 1;
+               /* disble sp1 for this case */
+               if ((vpp_wide_mode == VIDEO_WIDEOPTION_NONLINEAR)
+                       && (next_frame_par->supscl_path
+                       == sup0_pp_sp1_scpath))
+                       next_frame_par->supsc1_hori_ratio = 0;
                next_frame_par->supsc0_enable =
                        (next_frame_par->supsc0_hori_ratio ||
                        next_frame_par->supsc0_enable) ? 1 : 0;
@@ -1965,6 +1970,21 @@ static void vpp_set_scaler(u32 process_3d_type, u32 src_width,
                        next_frame_par->supsc1_vert_ratio;
        }
 
+       if ((vpp_wide_mode == VIDEO_WIDEOPTION_NONLINEAR) &&
+               (next_frame_par->VPP_hsc_endp >
+               next_frame_par->VPP_hsc_startp)) {
+               s32 start, end;
+               struct vppfilter_mode_s *filter =
+                       &next_frame_par->vpp_filter;
+               start = next_frame_par->VPP_hsc_startp;
+               end = next_frame_par->VPP_hsc_endp;
+               calculate_non_linear_ratio(
+                       (filter->vpp_hsc_start_phase_step >> 6),
+                       end - start,
+                       next_frame_par);
+               next_frame_par->VPP_hsc_linear_startp =
+               next_frame_par->VPP_hsc_linear_endp = (start + end) / 2;
+       }
        if (h_crop_enable) {
                next_frame_par->VPP_hd_start_lines_ += video_source_crop_left;
                next_frame_par->VPP_hd_end_lines_ += video_source_crop_left;
diff --git a/drivers/amlogic/tee/Kconfig b/drivers/amlogic/tee/Kconfig
new file mode 100644 (file)
index 0000000..b11afb2
--- /dev/null
@@ -0,0 +1,8 @@
+config AMLOGIC_TEE
+       tristate "TEE Support for Amlogic"
+       default n
+       help
+         Amlogic TEE driver
+
+         Provide TEE APIs and Debug interface in sysfs, depends on the
+         tee os.
diff --git a/drivers/amlogic/tee/Makefile b/drivers/amlogic/tee/Makefile
new file mode 100644 (file)
index 0000000..d99520b
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_AMLOGIC_TEE) += tee.o
diff --git a/drivers/amlogic/tee/tee.c b/drivers/amlogic/tee/tee.c
new file mode 100644 (file)
index 0000000..eb846d2
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * drivers/amlogic/tee/tee.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/arm-smccc.h>
+#include <linux/platform_device.h>
+
+#include <linux/amlogic/tee.h>
+
+#define DRIVER_NAME "tee_info"
+#define DRIVER_DESC "Amlogic tee driver"
+
+#define TEE_MSG_UID_0         0x384fb3e0
+#define TEE_MSG_UID_1         0xe7f811e3
+#define TEE_MSG_UID_2         0xaf630002
+#define TEE_MSG_UID_3         0xa5d5c51b
+
+#define TEE_SMC_FUNCID_CALLS_REVISION 0xFF03
+#define TEE_SMC_CALLS_REVISION \
+       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+                       ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+                       TEE_SMC_FUNCID_CALLS_REVISION)
+
+#define TEE_SMC_FUNCID_CALLS_UID 0xFF01
+#define TEE_SMC_CALLS_UID \
+       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+                          ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+                          TEE_SMC_FUNCID_CALLS_UID)
+
+
+#define TEE_SMC_FAST_CALL_VAL(func_num) \
+       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+                       ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
+
+#define TEE_SMC_FUNCID_GET_OS_REVISION 0x0001
+#define TEE_SMC_CALL_GET_OS_REVISION \
+       TEE_SMC_FAST_CALL_VAL(TEE_SMC_FUNCID_GET_OS_REVISION)
+
+#define TEE_SMC_FUNCID_LOAD_VIDEO_FW 15
+#define TEE_SMC_LOAD_VIDEO_FW \
+       TEE_SMC_FAST_CALL_VAL(TEE_SMC_FUNCID_LOAD_VIDEO_FW)
+
+static struct class *tee_sys_class;
+
+struct tee_smc_calls_revision_result {
+       unsigned long major;
+       unsigned long minor;
+       unsigned long reserved0;
+       unsigned long reserved1;
+};
+
+static int tee_msg_os_revision(uint32_t *major, uint32_t *minor)
+{
+       union {
+               struct arm_smccc_res smccc;
+               struct tee_smc_calls_revision_result result;
+       } res;
+
+       arm_smccc_smc(TEE_SMC_CALL_GET_OS_REVISION,
+                       0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+       *major = res.result.major;
+       *minor = res.result.minor;
+
+       return 0;
+}
+
+static int tee_msg_api_revision(uint32_t *major, uint32_t *minor)
+{
+       union {
+               struct arm_smccc_res smccc;
+               struct tee_smc_calls_revision_result result;
+       } res;
+
+       arm_smccc_smc(TEE_SMC_CALLS_REVISION,
+                       0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+       *major = res.result.major;
+       *minor = res.result.minor;
+
+       return 0;
+}
+
+static ssize_t tee_os_version_show(struct class *class,
+               struct class_attribute *attr, char *buf)
+{
+       int ret;
+       uint32_t major, minor;
+
+       ret = tee_msg_os_revision(&major, &minor);
+       if (ret)
+               return 0;
+
+       ret = sprintf(buf, "os version: V%d.%d\n", major, minor);
+
+       return ret;
+}
+
+static ssize_t tee_api_version_show(struct class *class,
+               struct class_attribute *attr, char *buf)
+{
+       int ret;
+       uint32_t major, minor;
+
+       ret = tee_msg_api_revision(&major, &minor);
+       if (ret)
+               return 0;
+
+       ret = sprintf(buf, "api version: V%d.%d\n", major, minor);
+
+       return ret;
+}
+
+static CLASS_ATTR(os_version, 0644, tee_os_version_show,
+               NULL);
+static CLASS_ATTR(api_version, 0644, tee_api_version_show,
+               NULL);
+
+int tee_load_video_fw(uint32_t index)
+{
+       struct arm_smccc_res res;
+
+       arm_smccc_smc(TEE_SMC_LOAD_VIDEO_FW,
+                       index, 0, 0, 0, 0, 0, 0, &res);
+
+       return res.a0;
+}
+EXPORT_SYMBOL(tee_load_video_fw);
+
+bool tee_enabled(void)
+{
+       struct arm_smccc_res res;
+
+       arm_smccc_smc(TEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+       if (res.a0 == TEE_MSG_UID_0 && res.a1 == TEE_MSG_UID_1 &&
+           res.a2 == TEE_MSG_UID_2 && res.a3 == TEE_MSG_UID_3)
+               return true;
+       return false;
+}
+EXPORT_SYMBOL(tee_enabled);
+
+int tee_create_sysfs(void)
+{
+       int ret;
+
+       tee_sys_class = class_create(THIS_MODULE, DRIVER_NAME);
+       ret = class_create_file(tee_sys_class, &class_attr_os_version);
+       if (ret != 0) {
+               pr_err("create class file os_version fail\n");
+               return ret;
+       }
+       ret = class_create_file(tee_sys_class, &class_attr_api_version);
+       if (ret != 0) {
+               pr_err("create class file os_version fail\n");
+               return ret;
+       }
+
+       return ret;
+}
+
+static int __init aml_tee_modinit(void)
+{
+       return tee_create_sysfs();
+}
+
+arch_initcall(aml_tee_modinit);
+
+static void __exit aml_tee_modexit(void)
+{
+       class_destroy(tee_sys_class);
+}
+
+module_exit(aml_tee_modexit);
+
+MODULE_AUTHOR("pengguang.zhu<pengguang.zhu@amlogic.com>");
+MODULE_DESCRIPTION(DRIVER_TEE);
+MODULE_LICENSE("GPL");
index b333947..e653bfa 100644 (file)
@@ -48,6 +48,8 @@ extern u32 timestamp_pcrscr_enable_state(void);
 
 extern void timestamp_pcrscr_set_adj(s32 inc);
 
+extern void timestamp_pcrscr_set_adj_pcr(s32 inc);
+
 extern void timestamp_apts_enable(u32 enable);
 
 extern void timestamp_apts_start(u32 enable);
index fcef9f8..7aa5f9f 100644 (file)
@@ -451,6 +451,7 @@ struct userdata_poc_info_t {
 #define AMSTREAM_SET_FRAME_BASE_PATH 0x174
 #define AMSTREAM_SET_EOS 0x175
 #define AMSTREAM_SET_RECEIVE_ID 0x176
+#define AMSTREAM_SET_IS_RESET 0x177
 
 /*  video set ex cmd */
 #define AMSTREAM_SET_EX_VIDEO_AXIS 0x260
index d6aca57..1011c90 100644 (file)
@@ -252,6 +252,8 @@ extern int power_key_pressed;
 #ifdef CONFIG_AM_VIDEO2
 extern void set_clone_frame_rate(unsigned int frame_rate, unsigned int delay);
 #endif
+extern struct vframe_provider_s *vf_get_provider_by_name(
+       const char *provider_name);
 
 extern void prot_get_parameter(u32 wide_mode, struct vframe_s *vf,
                               struct vpp_frame_par_s *next_frame_par,
index 2bfb806..1594690 100644 (file)
@@ -25,6 +25,8 @@ void try_free_keep_video(int flags);
 
 int __init video_keeper_init(void);
 void __exit video_keeper_exit(void);
-unsigned int vf_keep_current(struct vframe_s *cur_dispbuf);
+unsigned int vf_keep_current(
+       struct vframe_s *cur_dispbuf,
+       struct vframe_s *cur_dispbuf2);
 
 #endif
diff --git a/include/linux/amlogic/tee.h b/include/linux/amlogic/tee.h
new file mode 100644 (file)
index 0000000..45e80e4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * include/linux/amlogic/tee.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __TEE_H__
+#define __TEE_H__
+
+extern bool tee_enabled(void);
+extern int is_secload_get(void);
+extern int tee_load_video_fw(uint32_t index);
+#endif /* __TEE_H__ */
+