From 0e31e76526c751df58f3705dba72461288e4abbe Mon Sep 17 00:00:00 2001 From: Lifeng Cao Date: Thu, 18 Jun 2020 17:53:42 +0800 Subject: [PATCH] mediasync: add mediasync clock driver [3/5] 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 --- drivers/Makefile | 2 +- drivers/media_sync/Makefile | 4 + drivers/media_sync/media_sync_core.c | 402 ++++++++++++++++++++++++++ drivers/media_sync/media_sync_core.h | 65 +++++ drivers/media_sync/media_sync_debug.c | 0 drivers/media_sync/media_sync_dev.c | 397 +++++++++++++++++++++++++ drivers/media_sync/media_sync_dev.h | 20 ++ 7 files changed, 889 insertions(+), 1 deletion(-) create mode 100644 drivers/media_sync/Makefile create mode 100644 drivers/media_sync/media_sync_core.c create mode 100644 drivers/media_sync/media_sync_core.h create mode 100644 drivers/media_sync/media_sync_debug.c create mode 100644 drivers/media_sync/media_sync_dev.c create mode 100644 drivers/media_sync/media_sync_dev.h diff --git a/drivers/Makefile b/drivers/Makefile index 84560e8..3e487db 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -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 index 0000000..7ed5b83 --- /dev/null +++ b/drivers/media_sync/Makefile @@ -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 index 0000000..59efe85 --- /dev/null +++ b/drivers/media_sync/media_sync_core.c @@ -0,0 +1,402 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..aa357eb --- /dev/null +++ b/drivers/media_sync/media_sync_core.h @@ -0,0 +1,65 @@ +#ifndef MEDIA_SYNC_HEAD_HH +#define MEDIA_SYNC_HEAD_HH + +#include +#include +#include +#include +#include + + +#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 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 index 0000000..bdd93ab --- /dev/null +++ b/drivers/media_sync/media_sync_dev.c @@ -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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 "); + diff --git a/drivers/media_sync/media_sync_dev.h b/drivers/media_sync/media_sync_dev.h new file mode 100644 index 0000000..90ea09a --- /dev/null +++ b/drivers/media_sync/media_sync_dev.h @@ -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 -- 2.20.1