mediasync: add mediasync clock driver [3/5]
authorLifeng Cao <lifeng.cao@amlogic.com>
Thu, 18 Jun 2020 09:53:42 +0000 (17:53 +0800)
committerLifeng Cao <lifeng.cao@amlogic.com>
Sat, 3 Oct 2020 06:42:54 +0000 (23:42 -0700)
PD#SWPL-25622

Problem:
AV sync need a driver in media modules

Solution:
add mediasync clock driver

Verify:
SC2

Change-Id: Id0b1190bd1c2bbbce306362ecdb9466296ec0584
Signed-off-by: Lifeng Cao <lifeng.cao@amlogic.com>
drivers/Makefile
drivers/media_sync/Makefile [new file with mode: 0644]
drivers/media_sync/media_sync_core.c [new file with mode: 0644]
drivers/media_sync/media_sync_core.h [new file with mode: 0644]
drivers/media_sync/media_sync_debug.c [new file with mode: 0644]
drivers/media_sync/media_sync_dev.c [new file with mode: 0644]
drivers/media_sync/media_sync_dev.h [new file with mode: 0644]

index 84560e8acf075207103ce0f23879015c086c99ae..3e487db0dea3c1712b2e03e4f829a48c0484b2d0 100644 (file)
@@ -5,4 +5,4 @@ obj-y   +=      stream_input/
 obj-y  +=      amvdec_ports/
 obj-y  +=      fake_video_out/
 obj-y  +=      framerate_adapter/
-
+obj-y  +=      media_sync/
diff --git a/drivers/media_sync/Makefile b/drivers/media_sync/Makefile
new file mode 100644 (file)
index 0000000..7ed5b83
--- /dev/null
@@ -0,0 +1,4 @@
+obj-m  +=       media_sync.o
+
+media_sync-objs        +=      media_sync_dev.o
+media_sync-objs        +=      media_sync_core.o
diff --git a/drivers/media_sync/media_sync_core.c b/drivers/media_sync/media_sync_core.c
new file mode 100644 (file)
index 0000000..59efe85
--- /dev/null
@@ -0,0 +1,402 @@
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/cpu_version.h>
+#include <linux/syscalls.h>
+#include <linux/times.h>
+#include <linux/time.h>
+#include <linux/time64.h>
+#include <media_sync_core.h>
+
+#define MAX_INSTANCE_NUM 10
+mediasync_ins* vMediaSyncInsList[MAX_INSTANCE_NUM] = {0};
+u64 last_system;
+u64 last_pcr;
+extern int demux_get_stc(int demux_device_index, int index,
+                  u64 *stc, unsigned int *base);
+extern int demux_get_pcr(int demux_device_index, int index, u64 *pcr);
+
+static u64 get_llabs(s64 value){
+       u64 llvalue;
+       if (value > 0) {
+               return value;
+       } else {
+               llvalue = (u64)(0-value);
+               return llvalue;
+       }
+}
+
+static u64 get_stc_time_us(s32 sSyncInsId)
+{
+    /*mediasync_ins* pInstance = NULL;
+       u64 stc;
+       unsigned int base;
+      s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       demux_get_stc(pInstance->mDemuxId, 0, &stc, &base);*/
+       mediasync_ins* pInstance = NULL;
+       int ret;
+       u64 stc;
+       u64 timeus;
+       u64 pcr;
+       s64 pcr_diff;
+       s64 time_diff;
+       s32 index = sSyncInsId;
+       struct timespec64 ts_monotonic;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+       pInstance = vMediaSyncInsList[index];
+       ktime_get_ts64(&ts_monotonic);
+       timeus = ts_monotonic.tv_sec * 1000000LL + ts_monotonic.tv_nsec / 1000LL;
+       ret = demux_get_pcr(pInstance->mDemuxId, 0, &pcr);
+       if (ret != 0) {
+               stc = timeus;
+       } else {
+               if (last_pcr == 0) {
+                       stc = timeus;
+                       last_pcr = pcr * 100 / 9;
+                       last_system = timeus;
+               } else {
+                       pcr_diff = pcr * 100 / 9 - last_pcr;
+                       time_diff = timeus - last_system;
+                       if (time_diff && (get_llabs(pcr_diff) / time_diff
+                                           > 100)) {
+                               last_pcr = pcr * 100 / 9;
+                               last_system = timeus;
+                               stc = timeus;
+                       } else {
+                               if (time_diff)
+                                       stc = last_system + pcr_diff;
+                               else
+                                       stc = timeus;
+
+                               last_pcr = pcr * 100 / 9;
+                               last_system = stc;
+                       }
+               }
+       }
+       printk("get_stc_time_us stc:%lld pcr:%lld system_time:%lld\n", stc,  pcr * 100 / 9,  timeus);
+       return stc;
+}
+
+static s64 get_system_time_us(void) {
+       s64 TimeUs;
+       struct timespec64 ts_monotonic;
+       ktime_get_ts64(&ts_monotonic);
+       TimeUs = ts_monotonic.tv_sec * 1000000LL + ts_monotonic.tv_nsec / 1000LL;
+       printk("get_system_time_us %lld\n", TimeUs);
+       return TimeUs;
+}
+
+long mediasync_ins_alloc(s32 sDemuxId,
+                       s32 sPcrPid,
+                       s32 *sSyncInsId,
+                       mediasync_ins **pIns){
+       s32 index = 0;
+       mediasync_ins* pInstance = NULL;
+       pInstance = kzalloc(sizeof(mediasync_ins), GFP_KERNEL);
+       if (pInstance == NULL) {
+               return -1;
+       }
+
+       for (index = 0; index < MAX_INSTANCE_NUM - 1; index++) {
+               if (vMediaSyncInsList[index] == NULL) {
+                       vMediaSyncInsList[index] = pInstance;
+                       pInstance->mSyncInsId = index;
+                       *sSyncInsId = index;
+                       printk("mediasync_ins_alloc index:%d\n", index);
+                       break;
+               }
+       }
+
+       if (index == MAX_INSTANCE_NUM) {
+               kzfree(pInstance);
+               return -1;
+       }
+
+       pInstance->mDemuxId = sDemuxId;
+       pInstance->mPcrPid = sPcrPid;
+       *pIns = pInstance;
+       return 0;
+}
+
+
+long mediasync_ins_delete(s32 sSyncInsId) {
+       mediasync_ins* pInstance = NULL;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+
+       kzfree(pInstance);
+       vMediaSyncInsList[index] = NULL;
+       return 0;
+}
+
+long mediasync_ins_binder(s32 sSyncInsId,
+                       mediasync_ins **pIns) {
+       mediasync_ins* pInstance = NULL;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+
+       pInstance->mRef++;
+       *pIns = pInstance;
+       return 0;
+}
+
+long mediasync_ins_unbinder(s32 sSyncInsId) {
+       mediasync_ins* pInstance = NULL;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+
+       pInstance->mRef--;
+
+       if (pInstance->mRef <= 0)
+               mediasync_ins_delete(sSyncInsId);
+
+       return 0;
+}
+
+long mediasync_ins_update_mediatime(s32 sSyncInsId,
+                               s64 lMediaTime,
+                               s64 lSystemTime) {
+       mediasync_ins* pInstance = NULL;
+       u64 current_stc = 0;
+       s64 current_systemtime = 0;
+       s64 diff_system_time = 0;
+       s64 diff_mediatime = 0;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+
+       current_stc = get_stc_time_us(sSyncInsId);
+       current_systemtime = get_system_time_us();
+       pInstance->mSyncMode = MEDIA_SYNC_PCRMASTER;
+
+       if (pInstance->mSyncMode == MEDIA_SYNC_PCRMASTER) {
+               if (lSystemTime == 0) {
+                       if (current_stc != 0) {
+                               diff_system_time = current_stc - pInstance->mLastStc;
+                               diff_mediatime = lMediaTime - pInstance->mLastMediaTime;
+                       } else {
+                               diff_system_time = current_systemtime - pInstance->mLastRealTime;
+                               diff_mediatime = lMediaTime - pInstance->mLastMediaTime;
+                       }
+                       if (diff_mediatime < 0
+                               || ((diff_mediatime > 0)
+                               && (get_llabs(diff_system_time - diff_mediatime) > MIN_UPDATETIME_THRESHOLD_US ))) {
+                               printk("MEDIA_SYNC_PCRMASTER update time");
+                               pInstance->mLastMediaTime = lMediaTime;
+                               pInstance->mLastRealTime = current_systemtime;
+                               pInstance->mLastStc = current_stc;
+                       }
+               } else {
+                       if (current_stc != 0) {
+                               diff_system_time = lSystemTime - pInstance->mLastRealTime;
+                               diff_mediatime = lMediaTime - pInstance->mLastMediaTime;
+                       } else {
+                               diff_system_time = lSystemTime - pInstance->mLastRealTime;
+                               diff_mediatime = lMediaTime - pInstance->mLastMediaTime;
+                       }
+
+                       if (diff_mediatime < 0
+                               || ((diff_mediatime > 0)
+                               && (get_llabs(diff_system_time - diff_mediatime) > MIN_UPDATETIME_THRESHOLD_US ))) {
+                               pInstance->mLastMediaTime = lMediaTime;
+                               pInstance->mLastRealTime = lSystemTime;
+                               pInstance->mLastStc = current_stc + lSystemTime - current_systemtime;
+                       }
+               }
+       } else {
+               if (lSystemTime == 0) {
+                       pInstance->mLastMediaTime = lMediaTime;
+                       pInstance->mLastRealTime = current_systemtime;
+                       pInstance->mLastStc = current_stc;
+               } else {
+                       pInstance->mLastMediaTime = lMediaTime;
+                       pInstance->mLastRealTime = lSystemTime;
+                       pInstance->mLastStc = current_stc + lSystemTime - current_systemtime;
+               }
+       }
+       return 0;
+}
+
+long mediasync_ins_set_mediatime_speed(s32 sSyncInsId,
+                                       mediasync_speed fSpeed) {
+       mediasync_ins* pInstance = NULL;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+
+       pInstance->mSpeed.mNumerator = fSpeed.mNumerator;
+       pInstance->mSpeed.mDenominator = fSpeed.mDenominator;
+       return 0;
+}
+
+long mediasync_ins_set_paused(s32 sSyncInsId, s32 sPaused) {
+
+       mediasync_ins* pInstance = NULL;
+       u64 current_stc = 0;
+       s64 current_systemtime = 0;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+
+       if ((sPaused != 0 && sPaused != 1)
+               || (sPaused == pInstance->mPaused))
+               return -1;
+
+       current_stc = get_stc_time_us(sSyncInsId);
+       current_systemtime = get_system_time_us();
+
+       pInstance->mPaused = sPaused;
+       pInstance->mLastRealTime = current_systemtime;
+       pInstance->mLastStc = current_stc;
+
+       return 0;
+}
+
+long mediasync_ins_get_paused(s32 sSyncInsId, s32* spPaused) {
+
+       mediasync_ins* pInstance = NULL;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+       *spPaused = pInstance->mPaused ;
+       return 0;
+}
+
+long mediasync_ins_set_syncmode(s32 sSyncInsId, s32 sSyncMode){
+       mediasync_ins* pInstance = NULL;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+
+       pInstance->mSyncMode = sSyncMode;
+       return 0;
+}
+
+long mediasync_ins_get_syncmode(s32 sSyncInsId, s32 *sSyncMode) {
+       mediasync_ins* pInstance = NULL;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+       *sSyncMode = pInstance->mSyncMode;
+       return 0;
+}
+
+long mediasync_ins_get_mediatime_speed(s32 sSyncInsId, mediasync_speed *fpSpeed) {
+       mediasync_ins* pInstance = NULL;
+       s32 index = sSyncInsId;
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+       fpSpeed->mNumerator = pInstance->mSpeed.mNumerator;
+       fpSpeed->mDenominator = pInstance->mSpeed.mDenominator;
+       return 0;
+}
+
+long mediasync_ins_get_anchor_time(s32 sSyncInsId,
+                                                                                               s64* lpMediaTime,
+                                                                                               s64* lpSTCTime,
+                                                                                               s64* lpSystemTime) {
+       mediasync_ins* pInstance = NULL;
+       s32 index = sSyncInsId;
+
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+
+    *lpMediaTime = pInstance->mLastMediaTime;
+       *lpSTCTime = pInstance->mLastStc;
+       *lpSystemTime = pInstance->mLastRealTime;
+       return 0;
+}
+
+long mediasync_ins_get_systemtime(s32 sSyncInsId, s64* lpSTC, s64* lpSystemTime){
+       mediasync_ins* pInstance = NULL;
+       u64 current_stc = 0;
+       s64 current_systemtime = 0;
+       s32 index = sSyncInsId;
+
+       if (index < 0 || index >= MAX_INSTANCE_NUM)
+               return -1;
+
+       pInstance = vMediaSyncInsList[index];
+       if (pInstance == NULL)
+               return -1;
+
+       current_stc = get_stc_time_us(sSyncInsId);
+       current_systemtime = get_system_time_us();
+
+       *lpSTC = current_stc;
+       *lpSystemTime = current_systemtime;
+
+       return 0;
+}
+
+long mediasync_ins_get_nextvsync_systemtime(s32 sSyncInsId, s64* lpSystemTime) {
+
+       return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media_sync/media_sync_core.h b/drivers/media_sync/media_sync_core.h
new file mode 100644 (file)
index 0000000..aa357eb
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef MEDIA_SYNC_HEAD_HH
+#define MEDIA_SYNC_HEAD_HH
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/cpu_version.h>
+
+
+#define MIN_UPDATETIME_THRESHOLD_US 50000
+typedef enum {
+       MEDIA_SYNC_VMASTER = 0,
+       MEDIA_SYNC_AMASTER = 1,
+       MEDIA_SYNC_PCRMASTER = 2,
+       MEDIA_SYNC_MODE_MAX = 255,
+}sync_mode;
+
+typedef struct speed{
+       u32 mNumerator;
+       u32 mDenominator;
+}mediasync_speed;
+
+typedef struct instance{
+    s32 mSyncInsId;
+    s32 mDemuxId;
+    s32 mPcrPid;
+    s32 mPaused;
+       s32 mRef;
+       s32 mSyncMode;
+    s64 mLastStc;
+    s64 mLastRealTime;
+    s64 mLastMediaTime;
+       mediasync_speed mSpeed;
+}mediasync_ins;
+
+long mediasync_ins_alloc(s32 sDemuxId,
+                       s32 sPcrPid,
+                       s32 *sSyncInsId,
+                       mediasync_ins **pIns);
+
+long mediasync_ins_delete(s32 sSyncInsId);
+long mediasync_ins_binder(s32 sSyncInsId,
+                       mediasync_ins **pIns);
+long mediasync_ins_unbinder(s32 sSyncInsId);
+long mediasync_ins_update_mediatime(s32 sSyncInsId,
+                                       s64 lMediaTime,
+                                       s64 lSystemTime);
+long mediasync_ins_set_mediatime_speed(s32 sSyncInsId, mediasync_speed fSpeed);
+long mediasync_ins_set_paused(s32 sSyncInsId, s32 sPaused);
+long mediasync_ins_get_paused(s32 sSyncInsId, s32* spPaused);
+long mediasync_ins_set_syncmode(s32 sSyncInsId, s32 sSyncMode);
+long mediasync_ins_get_syncmode(s32 sSyncInsId, s32 *sSyncMode);
+long mediasync_ins_get_mediatime_speed(s32 sSyncInsId, mediasync_speed *fpSpeed);
+long mediasync_ins_get_anchor_time(s32 sSyncInsId,
+                                                                                               s64* lpMediaTime,
+                                                                                               s64* lpSTCTime,
+                                                                                               s64* lpSystemTime);
+long mediasync_ins_get_systemtime(s32 sSyncInsId,
+                               s64* lpSTC,
+                               s64* lpSystemTime);
+long mediasync_ins_get_nextvsync_systemtime(s32 sSyncInsId, s64* lpSystemTime);
+#endif
+
+
diff --git a/drivers/media_sync/media_sync_debug.c b/drivers/media_sync/media_sync_debug.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/drivers/media_sync/media_sync_dev.c b/drivers/media_sync/media_sync_dev.c
new file mode 100644 (file)
index 0000000..bdd93ab
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * drivers/amlogic/media/frame_sync/tsync_pcr.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/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+#include <linux/platform_device.h>
+#include <linux/amlogic/cpu_version.h>
+#include <linux/amlogic/major.h>
+#include <media_sync_core.h>
+#include <media_sync_dev.h>
+
+#define MEDIASYNC_DEVICE_NAME   "mediasync"
+static struct device *mediasync_dev;
+
+typedef struct alloc_para {
+       s32 mDemuxId;
+       s32 mPcrPid;
+} mediasync_alloc_para;
+
+typedef struct systime_para {
+       s64 mStcUs;
+       s64 mSystemTimeUs;
+}mediasync_systime_para;
+
+typedef struct updatetime_para {
+       int64_t mMediaTimeUs;
+       int64_t mSystemTimeUs;
+}mediasync_updatetime_para;
+
+typedef struct arthortime_para {
+       int64_t mMediaTimeUs;
+       int64_t mSystemTimeUs;
+       int64_t mStcTimeUs;
+}mediasync_arthortime_para;
+
+typedef struct priv_s {
+       s32 mSyncInsId;
+       mediasync_ins *mSyncIns;
+}mediasync_priv_s;
+
+static int mediasync_open(struct inode *inode, struct file *file)
+{
+       mediasync_priv_s *priv = {0};
+       priv = kzalloc(sizeof(mediasync_priv_s), GFP_KERNEL);
+       if (priv == NULL)
+               return -ENOMEM;
+       priv->mSyncInsId = -1;
+       priv->mSyncIns = NULL;
+       file->private_data = priv;
+       return 0;
+}
+
+static int mediasync_release(struct inode *inode, struct file *file)
+{
+       long ret = 0;
+       mediasync_priv_s *priv = (mediasync_priv_s *)file->private_data;
+       if (priv == NULL) {
+               return -ENOMEM;
+       }
+
+       if (priv->mSyncInsId != -1) {
+               ret = mediasync_ins_unbinder(priv->mSyncInsId);
+               priv->mSyncInsId = -1;
+               priv->mSyncIns = NULL;
+       }
+       kfree(priv);
+       return 0;
+}
+
+static long mediasync_ioctl(struct file *file, unsigned int cmd, ulong arg)
+{
+       long ret = 0;
+       mediasync_speed SyncSpeed = {0};
+       s32 SyncInsId = -1;
+       s32 SyncPaused = 0;
+       s32 SyncMode = -1;
+       s64 NextVsyncSystemTime = 0;
+
+       mediasync_priv_s *priv = (mediasync_priv_s *)file->private_data;
+       mediasync_ins *SyncIns = NULL;
+       mediasync_alloc_para parm = {0};
+    mediasync_arthortime_para ArthorTime = {0};
+       mediasync_updatetime_para UpdateTime = {0};
+       mediasync_systime_para SystemTime = {0};
+       switch (cmd) {
+               case MEDIASYNC_IOC_INSTANCE_ALLOC:
+                       if (copy_from_user ((void *)&parm,
+                                               (void *)arg,
+                                               sizeof(parm)))
+                               return -EFAULT;
+                       if (mediasync_ins_alloc(parm.mDemuxId,
+                                               parm.mPcrPid,
+                                               &SyncInsId,
+                                               &SyncIns) < 0) {
+                               return -EFAULT;
+                       }
+                       if (SyncIns == NULL) {
+                               return -EFAULT;
+                       }
+                       if (priv != NULL) {
+                               priv->mSyncInsId = SyncInsId;
+                               priv->mSyncIns = SyncIns;
+                               priv->mSyncIns->mRef++;
+                       }
+
+               break;
+               case MEDIASYNC_IOC_INSTANCE_GET:
+                       if (priv->mSyncIns == NULL) {
+                               return -EFAULT;
+                       }
+
+                       SyncInsId = priv->mSyncInsId;
+                       if (copy_to_user((void *)arg,
+                                       &SyncInsId,
+                                       sizeof(SyncInsId))) {
+                               return -EFAULT;
+                       }
+               break;
+               case MEDIASYNC_IOC_INSTANCE_BINDER:
+                       if (copy_from_user((void *)&SyncInsId,
+                                               (void *)arg,
+                                               sizeof(parm))) {
+                               return -EFAULT;
+                       }
+                       ret = mediasync_ins_binder(SyncInsId, &SyncIns);
+                       if (SyncIns == NULL) {
+                               return -EFAULT;
+                       }
+
+                       priv->mSyncInsId = SyncInsId;
+                       priv->mSyncIns = SyncIns;
+               break;
+
+               case MEDIASYNC_IOC_UPDATE_MEDIATIME:
+                       if (copy_from_user((void *)&UpdateTime,
+                                               (void *)arg,
+                                               sizeof(UpdateTime))) {
+                               return -EFAULT;
+                       }
+                       if (priv->mSyncIns == NULL) {
+                               return -EFAULT;
+                       }
+
+                       ret = mediasync_ins_update_mediatime(priv->mSyncInsId,
+                                                       UpdateTime.mMediaTimeUs,
+                                                       UpdateTime.mSystemTimeUs);
+                       break;
+
+               case MEDIASYNC_IOC_GET_MEDIATIME:
+                       if (priv->mSyncIns == NULL) {
+                               return -EFAULT;
+                       }
+                       ret = mediasync_ins_get_anchor_time(priv->mSyncInsId,
+                                                                                               &(ArthorTime.mMediaTimeUs),
+                                                                                               &(ArthorTime.mStcTimeUs),
+                                                                                               &(ArthorTime.mSystemTimeUs));
+                       if (ret == 0) {
+                               if (copy_to_user((void *)arg,
+                                               &ArthorTime,
+                                               sizeof(ArthorTime))) {
+                                       return -EFAULT;
+                               }
+                       }
+               break;
+
+               case MEDIASYNC_IOC_GET_SYSTEMTIME:
+
+                       if (priv->mSyncIns == NULL) {
+                               return -EFAULT;
+                       }
+
+                       ret = mediasync_ins_get_systemtime(priv->mSyncInsId,
+                                                                                       &(SystemTime.mStcUs),
+                                                                                       &(SystemTime.mSystemTimeUs));
+                       if (ret == 0) {
+                               if (copy_to_user((void *)arg,
+                                               &SystemTime,
+                                               sizeof(SystemTime))) {
+                                       return -EFAULT;
+                               }
+                       }
+               break;
+
+               case MEDIASYNC_IOC_GET_NEXTVSYNC_TIME:
+                       if (priv->mSyncIns == NULL)
+                               return -EFAULT;
+
+                       ret = mediasync_ins_get_nextvsync_systemtime(priv->mSyncInsId,
+                                                               &NextVsyncSystemTime);
+                       if (ret == 0) {
+                               if (copy_to_user((void *)arg,
+                                               &NextVsyncSystemTime,
+                                               sizeof(NextVsyncSystemTime)))
+                                       return -EFAULT;
+                       }
+               break;
+
+               case MEDIASYNC_IOC_SET_SPEED:
+                       if (copy_from_user((void *)&SyncSpeed,
+                                       (void *)arg,
+                                       sizeof(SyncSpeed)))
+                               return -EFAULT;
+
+                       if (priv->mSyncIns == NULL)
+                               return -EFAULT;
+
+                       ret = mediasync_ins_set_mediatime_speed(priv->mSyncInsId,
+                                                               SyncSpeed);
+               break;
+
+               case MEDIASYNC_IOC_GET_SPEED:
+                       if (priv->mSyncIns == NULL)
+                               return -EFAULT;
+
+                       ret = mediasync_ins_get_mediatime_speed(priv->mSyncInsId,
+                                                               &SyncSpeed);
+                       if (ret == 0) {
+                               if (copy_to_user((void *)arg,
+                                               &SyncSpeed,
+                                               sizeof(SyncSpeed)))
+                                       return -EFAULT;
+                       }
+               break;
+
+               case MEDIASYNC_IOC_SET_PAUSE:
+                       if (copy_from_user((void *)&SyncPaused,
+                                               (void *)arg,
+                                               sizeof(SyncPaused)))
+                               return -EFAULT;
+
+                       if (priv->mSyncIns == NULL)
+                               return -EFAULT;
+
+                       ret = mediasync_ins_set_paused(priv->mSyncInsId,
+                                                       SyncPaused);
+               break;
+
+               case MEDIASYNC_IOC_GET_PAUSE:
+                       if (priv->mSyncIns == NULL)
+                               return -EFAULT;
+
+                       ret = mediasync_ins_get_paused(priv->mSyncInsId,
+                                                       &SyncPaused);
+                       if (ret == 0) {
+                               if (copy_to_user((void *)arg,
+                                               &SyncPaused,
+                                               sizeof(SyncPaused)))
+                                       return -EFAULT;
+                       }
+               break;
+
+               case MEDIASYNC_IOC_SET_SYNCMODE:
+                       if (copy_from_user((void *)&SyncMode,
+                                               (void *)arg,
+                                               sizeof(SyncMode)))
+                               return -EFAULT;
+
+                       if (priv->mSyncIns == NULL)
+                               return -EFAULT;
+
+                       ret = mediasync_ins_set_syncmode(priv->mSyncInsId,
+                                                       SyncMode);
+               break;
+
+               case MEDIASYNC_IOC_GET_SYNCMODE:
+                       if (priv->mSyncIns == NULL)
+                               return -EFAULT;
+
+                       ret = mediasync_ins_get_syncmode(priv->mSyncInsId,
+                                                       &SyncMode);
+                       if (ret == 0) {
+                               if (copy_to_user((void *)arg,
+                                               &SyncMode,
+                                               sizeof(SyncMode)))
+                                       return -EFAULT;
+                       }
+               break;
+
+               default:
+                       pr_info("invalid cmd:%d\n", cmd);
+               break;
+       }
+
+       return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static long mediasync_compat_ioctl(struct file *file, unsigned int cmd, ulong arg)
+{
+       long ret = 0;
+       switch (cmd) {
+               case MEDIASYNC_IOC_INSTANCE_ALLOC:
+               case MEDIASYNC_IOC_INSTANCE_GET:
+               case MEDIASYNC_IOC_INSTANCE_BINDER:
+               case MEDIASYNC_IOC_UPDATE_MEDIATIME:
+               case MEDIASYNC_IOC_GET_MEDIATIME:
+               case MEDIASYNC_IOC_GET_SYSTEMTIME:
+               case MEDIASYNC_IOC_GET_NEXTVSYNC_TIME:
+               case MEDIASYNC_IOC_SET_SPEED:
+               case MEDIASYNC_IOC_GET_SPEED:
+               case MEDIASYNC_IOC_SET_PAUSE:
+               case MEDIASYNC_IOC_GET_PAUSE:
+                       return mediasync_ioctl(file, cmd, arg);
+               default:
+                       return -EINVAL;
+       }
+       return ret;
+}
+#endif
+
+static const struct file_operations mediasync_fops = {
+       .owner = THIS_MODULE,
+       .open = mediasync_open,
+       .release = mediasync_release,
+       .unlocked_ioctl = mediasync_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = mediasync_compat_ioctl,
+#endif
+};
+
+static struct class_attribute mediasync_class_attrs[] = {
+    __ATTR_NULL
+};
+
+static struct class mediasync_class = {
+       .name = "mediasync",
+       .class_attrs = mediasync_class_attrs,
+};
+
+static int __init mediasync_module_init(void)
+{
+       int r;
+
+       r = class_register(&mediasync_class);
+
+       if (r) {
+               pr_err("mediasync class create fail.\n");
+               return r;
+       }
+
+       /* create tsync device */
+       r = register_chrdev(MEDIASYNC_MAJOR, "mediasync", &mediasync_fops);
+       if (r < 0) {
+               pr_info("Can't register major for tsync\n");
+               goto err2;
+       }
+
+       mediasync_dev = device_create(&mediasync_class, NULL,
+                               MKDEV(MEDIASYNC_MAJOR, 0), NULL, MEDIASYNC_DEVICE_NAME);
+
+       if (IS_ERR(mediasync_dev)) {
+               pr_err("Can't create mediasync_dev device\n");
+               goto err1;
+       }
+       return 0;
+
+err1:
+       unregister_chrdev(MEDIASYNC_MAJOR, "mediasync");
+err2:
+       class_unregister(&mediasync_class);
+
+       return 0;
+}
+
+static void __exit mediasync_module_exit(void)
+{
+       device_destroy(&mediasync_class, MKDEV(MEDIASYNC_MAJOR, 0));
+       unregister_chrdev(MEDIASYNC_MAJOR, "mediasync");
+       class_unregister(&mediasync_class);
+}
+
+module_init(mediasync_module_init);
+module_exit(mediasync_module_exit);
+
+MODULE_DESCRIPTION("AMLOGIC media sync management driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lifeng Cao <lifeng.cao@amlogic.com>");
+
diff --git a/drivers/media_sync/media_sync_dev.h b/drivers/media_sync/media_sync_dev.h
new file mode 100644 (file)
index 0000000..90ea09a
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef MEDIA_SYNC_DEV_HEAD_HH
+#define MEDIA_SYNC_DEV_HEAD_HH
+
+#define MEDIASYNC_IOC_MAGIC 'M'
+
+#define MEDIASYNC_IOC_INSTANCE_ALLOC _IOW(MEDIASYNC_IOC_MAGIC, 0x01, int)
+#define MEDIASYNC_IOC_INSTANCE_GET   _IOW(MEDIASYNC_IOC_MAGIC, 0x02, int)
+#define MEDIASYNC_IOC_INSTANCE_BINDER _IOW(MEDIASYNC_IOC_MAGIC, 0x03, int)
+#define MEDIASYNC_IOC_UPDATE_MEDIATIME _IOW(MEDIASYNC_IOC_MAGIC, 0x04, int)
+#define MEDIASYNC_IOC_GET_MEDIATIME _IOW(MEDIASYNC_IOC_MAGIC, 0x05, int)
+#define MEDIASYNC_IOC_GET_SYSTEMTIME _IOW(MEDIASYNC_IOC_MAGIC, 0x06, int)
+#define MEDIASYNC_IOC_GET_NEXTVSYNC_TIME _IOW(MEDIASYNC_IOC_MAGIC, 0x07, int)
+#define MEDIASYNC_IOC_SET_SPEED _IOW(MEDIASYNC_IOC_MAGIC, 0x08, int)
+#define MEDIASYNC_IOC_GET_SPEED _IOW(MEDIASYNC_IOC_MAGIC, 0x09, int)
+#define MEDIASYNC_IOC_SET_PAUSE _IOW(MEDIASYNC_IOC_MAGIC, 0x0A, int)
+#define MEDIASYNC_IOC_GET_PAUSE _IOW(MEDIASYNC_IOC_MAGIC, 0x0B, int)
+#define MEDIASYNC_IOC_SET_SYNCMODE _IOW(MEDIASYNC_IOC_MAGIC, 0x0C, int)
+#define MEDIASYNC_IOC_GET_SYNCMODE _IOW(MEDIASYNC_IOC_MAGIC, 0x0D, int)
+
+#endif