obj-y += amvdec_ports/
obj-y += fake_video_out/
obj-y += framerate_adapter/
-
+obj-y += media_sync/
--- /dev/null
+obj-m += media_sync.o
+
+media_sync-objs += media_sync_dev.o
+media_sync-objs += media_sync_core.o
--- /dev/null
+#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;
+}
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+#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
+
+
--- /dev/null
+/*
+ * 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>");
+
--- /dev/null
+#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