/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * 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 https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/


#ifndef _DRV_STC_H_
#define _DRV_STC_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include "x_typedef.h"
#include "x_timer.h"

/* STC ID */
#define STC_SRC_A1                          0
#define STC_SRC_A2                          1
#if defined(CC_SKYPE_FINE_INSTANCE) || defined(CC_TLV_SUPPORT) || defined(CC_ATSC30_ALP_SUPPORT)
#define STC_SRC_NS                          5
#else
#define STC_SRC_NS                          3
#endif

#define STC_SRC_NTP1    4
#define STC_SRC_NTP0    3

#define STC_SRC_PTP1    4 //PTP reuse NTP HW resource
#define STC_SRC_PTP0    3

#define STC_SRC_PCR    1
#define STC_SRC_AUD    0

/* MT5351 STC ID */
#define STC_SRC_V1                          2
#define STC_SRC_V2                          3

/* AV SYNC Mode */
#define AV_SYNC_MODE_NONE                   0
#define AV_SYNC_MODE_AUDIO_MASTER           1
#define AV_SYNC_MODE_VIDEO_MASTER           2
#define AV_SYNC_MODE_SYSTEM_MASTER          3
#define AV_SYNC_MODE_NS                     4

/* Video SYNC Mode */
#define VID_SYNC_MODE_NONE                  0
#define VID_SYNC_MODE_SLAVE                 1
#define VID_SYNC_MODE_MASTER                2
#define VID_SYNC_MODE_SLAVE_MM              3
#define VID_SYNC_MODE_NS                    4

/* AV Sync Target */
#define AV_SYNC_TARGET_AUD                  0
#define AV_SYNC_TARGET_VDO                  1
#define AV_SYNC_TARGET_NS                   2

/* AV Sync Target */
#define DATA_SRC_NONE    0
#define DATA_SRC_DTV     1
#define DATA_SRC_MM      2
#define DATA_SRC_ENC     3     //TVA
#define DATA_SRC_NS      4


/* MAX Device ID */
#define MAX_DEVICE_ID                       0xFF

/* STC API Return Value */
//return value
#define STC_OK                     (0)
#define STC_FAIL                   (1)
#define STC_INV_ARG                (2)
#define STC_INTERNAL_ERR           (3)
#define STC_NOT_IMPL               (4)

#define STC_SET_OK                 (0)
#define STC_SET_FAIL               (-1)
#define STC_VALID                  (0)
#define STC_INVALID                (-1)

/* STC Time Structure */
typedef struct _STC_CLOCK
{
    UCHAR           ucBaseHi;
    UINT16          u2Ext;
    UINT32          u4Base;
    UINT64          u8Base;
} STC_CLOCK;


typedef struct
{
    UINT32 u4FractionalSecond  :  24;
    UINT32 u4Second 		   :  32;
    UINT32                     :   8;

    //LINT_SUPPRESS_NEXT_EXPRESSION(950)
} __attribute__ ((packed))   TIME_EXT;

typedef union
{
    UINT64 u8Value;
    TIME_EXT rExt;
} TLV_NTP_STC_T;

typedef struct _PTS_COMPENSATE
{
    BOOL    fgCompensate;
    UINT64  u8Compensate;
} PTS_COMPENSATE;

typedef enum
{
    STC_SPEED_TYPE_FORWARD_1X,
    STC_SPEED_TYPE_FORWARD_2X,
    STC_SPEED_TYPE_FORWARD_3X,
    STC_SPEED_TYPE_FORWARD_4X,
    STC_SPEED_TYPE_FORWARD_8X,
    STC_SPEED_TYPE_FORWARD_16X,
    STC_SPEED_TYPE_FORWARD_32X,
    STC_SPEED_TYPE_FORWARD_64X,
    STC_SPEED_TYPE_FORWARD_128X,
    STC_SPEED_TYPE_FORWARD_256X,
    STC_SPEED_TYPE_FORWARD_512X,
    STC_SPEED_TYPE_FORWARD_1024X,
    STC_SPEED_TYPE_FORWARD_1_DIV_2X,
    STC_SPEED_TYPE_FORWARD_1_DIV_3X,
    STC_SPEED_TYPE_FORWARD_1_DIV_4X,
    STC_SPEED_TYPE_FORWARD_1_DIV_8X,
    STC_SPEED_TYPE_FORWARD_1_DIV_16X,
    STC_SPEED_TYPE_FORWARD_1_DIV_32X,
    STC_SPEED_TYPE_FORWARD_0_DOT_6X,    /* Slow Forward 0.6X */
    STC_SPEED_TYPE_FORWARD_0_DOT_7X,    /* Slow Forward 0.7X */
    STC_SPEED_TYPE_FORWARD_0_DOT_8X,    /* Slow Forward 0.8X */
    STC_SPEED_TYPE_FORWARD_0_DOT_9X,    /* Slow Forward 0.9X */
    STC_SPEED_TYPE_FORWARD_1_DOT_1X,    /* Fast Forward 1.1X */
    STC_SPEED_TYPE_FORWARD_1_DOT_2X,    /* Fast Forward 1.2X */
    STC_SPEED_TYPE_FORWARD_1_DOT_3X,    /* Fast Forward 1.3X */
    STC_SPEED_TYPE_FORWARD_1_DOT_4X,    /* Fast Forward 1.4X */
    STC_SPEED_TYPE_FORWARD_1_DOT_5X,    /* Fast Forward 1.5X */
    STC_SPEED_TYPE_REWIND_1X,
    STC_SPEED_TYPE_REWIND_2X,
    STC_SPEED_TYPE_REWIND_3X,
    STC_SPEED_TYPE_REWIND_4X,
    STC_SPEED_TYPE_REWIND_8X,
    STC_SPEED_TYPE_REWIND_16X,
    STC_SPEED_TYPE_REWIND_32X,
    STC_SPEED_TYPE_REWIND_64X,
    STC_SPEED_TYPE_REWIND_128X,
    STC_SPEED_TYPE_REWIND_256X,
    STC_SPEED_TYPE_REWIND_512X,
    STC_SPEED_TYPE_REWIND_1024X,
    STC_SPEED_TYPE_REWIND_1_DIV_2X,       ///<Slow backward 1/2X
    STC_SPEED_TYPE_REWIND_1_DIV_4X,       ///<Slow backward 1/4X
    STC_SPEED_TYPE_REWIND_1_DIV_8X,       ///<Slow backward 1/8X
    STC_SPEED_TYPE_REWIND_1_DIV_16X,       ///<Slow backward 1/16X
    STC_SPEED_TYPE_REWIND_1_DIV_32X,       ///<Slow backward 1/32X
    STC_SPEED_TYPE_NS
}STC_SPEED_TYPE_T;

typedef enum
{
    DMX_STC_STATUS_UNKNOWN,
    DMX_STC_STATUS_INVALID,
    DMX_STC_STATUS_BIG_DRIFT,
    DMX_STC_STATUS_VALID,
    DMX_STC_STATUS_TRACKING,
    DMX_STC_STATUS_DRIFT,
    DMX_STC_STATUS_NS
}STC_STATUS_T;

typedef enum
{
    STC_DATA_NONE,
    STC_DATA_PCR,
    STC_DATA_AUD,
    STC_DATA_ENC,     //for TVA
    STC_DATA_NTP0,
    STC_DATA_NTP1,
    STC_DATA_PTP0,
    STC_DATA_PTP1,
    STC_DATA_NS
}STC_DATA_SRC_T;

typedef struct
{
    //hal part, must be in the first position
    VOID* pvData;
    VOID* hStc;

    BOOL  fgUsed;
    BOOL  fgOpen;
    BOOL  fgPtsCompensate;
    UCHAR ucStcId;
    UCHAR ucPidIdx;

    UINT32 u4PwmAdj;
    UINT32 u4SyncMode;

    UINT32 u4AudTarget;
    UINT32 u4VidTarget;
    UINT32 u4LogMask;

    UINT32 u4DriftCnt;
    HAL_TIME_T t_DriftTime;


    STC_STATUS_T    eStatus;
    PTS_COMPENSATE  tCompensate;
}STC_OBJECT_T;

typedef struct
{
    UINT8 ucPtpId;
    UINT32 u4Msk;
    UINT64 u8Pts;
} ATSC30_PTS_COMPENSATE_T;

// STC Log Mask
typedef enum
{
    STC_LOG_DTV_CONN   = (1U << 0),
    STC_LOG_MMP_CONN   = (1U << 1),
    STC_LOG_SRC_VAL    = (1U << 2),
    STC_LOG_STC_VAL    = (1U << 3),
    STC_LOG_SET_VAL    = (1U << 4),
    STC_LOG_CTL_STACK  = (1U << 5),
    STC_LOG_SET_STACK  = (1U << 6),
    STC_LOG_PCR_LOOP   = (1U << 7),
    STC_LOG_PCR_MON    = (1U << 8),
    STC_LOG_PTS_DIFF   = (1U << 9),
    STC_LOG_FLOW_CHECK = (1U << 10),
    STC_LOG_PTP_CHECK  = (1U << 11),
    STC_LOG_PTP_MON    = (1U << 12),
    STC_LOG_MAX,
}STC_LOG_FILTER_TYPE_T;

/// ATSC3.0 video/audio
#define DMX_MM_ATSC30_VIDEO                 0x00000001
#define DMX_MM_ATSC30_AUDIO                 0x00000002

EXTERN UINT32 STC_Log_GetFilterMaskVal(UCHAR ucStcId);
EXTERN VOID   STC_Log_SetFilterMaskVal(UCHAR ucStcId, BOOL ucEnable, STC_LOG_FILTER_TYPE_T rLogFilterType);

#define STC_LOG_FILTER_TEST_BIT(u4Mask, u4BitVal) (((u4Mask) & (u4BitVal)) != 0)

#define STCLOG(filter, stcId, fmt, ...)                                   \
do {                                                                      \
    if (STC_LOG_FILTER_TEST_BIT(STC_Log_GetFilterMaskVal(stcId), filter)) \
    {                                                                     \
        LOG(2, ("[STC-%d] " fmt), stcId,  ##__VA_ARGS__);                  \
    }                                                                     \
} while (0)

/******************************************************************************
* STC API
******************************************************************************/
extern INT32 DMX_SetStcSrc(UCHAR ucPidIdx, UCHAR ucStcId);
extern INT32 STC_GetStcStatus(UCHAR ucStcId);
extern INT32 STC_GetSrc(UCHAR ucStcId, STC_CLOCK* prStc);
extern INT32 STC_SetSrc(UCHAR ucStcId, STC_CLOCK* prStc);

extern INT32 STC_SetSyncTarget(UCHAR ucType, UCHAR ucStcId, UCHAR ucTargetId);
extern UCHAR STC_GetSyncTarget(UCHAR ucType, UCHAR ucStcId);
extern INT32 STC_SetStartPts(UCHAR ucType, UCHAR ucStcId, UINT32 u4Pts);

extern INT32 STC_SetPtsDrift(UCHAR ucStcId, INT32 i4Drift);
extern INT32 STC_GetPtsDrift(UCHAR ucStcId);

extern INT32 STC_SetPtpDrift(UCHAR ucStcId, INT32 i4Drift);
extern INT32 STC_GetPtpDrift(UCHAR ucStcId);

extern INT32 STC_GetPtsDriftByAudDeviceId(UCHAR ucDevId);
extern INT32 STC_GetPtsDriftByVdoDeviceId(UCHAR ucDevId);

extern void STC_RxEsPkt(UCHAR ucType, UCHAR ucDevId, UINT32 u4Pts);
extern UINT32 STC_GetFastChangeChangeAhead(UCHAR ucStcId);
extern void STC_SetVidStcDiff(UINT8 ucStcId, INT32 i4StcDiff);
extern INT32 STC_GetVidStcDiff(UINT8 ucStcId);


#ifdef CC_53XX_SWDMX_V2
extern void STC_SetStcValue(UCHAR ucStcId, UINT32 u4Stc);
extern void STC_SetStcValueEx(UINT8 ucStcId, UINT64 u8Stc);

extern UINT32 STC_GetStcValue(UCHAR ucStcId);
extern UINT64 STC_GetStcValueEx(UINT8 ucStcId);

extern void STC_StopStc(UCHAR ucStcId);
extern void STC_StartStc(UCHAR ucStcId);
extern BOOL STC_IsStartedStc(UCHAR ucStcId);
extern void STC_SetSTCSyncMode(UINT8 ucStcId,UINT32 u4SyncMode);
extern void STC_SetSyncMode(UINT8 ucStcId, UINT8 ucAdecId, UINT8 ucVdecId, UINT32 u4SyncMode);
extern UINT32 STC_GetSyncMode(UINT8 ucStcId);
#else
extern void STC_SetStcValue(UINT32 u4Stc);
extern UINT32 STC_GetStcValue(void);

extern void STC_StopStc(void);
extern void STC_StartStc(void);
extern BOOL STC_IsStartedStc(void);

extern void STC_SetSyncMode(UINT32 u4SyncMode);
#endif

extern BOOL STC_PtsCompensate(ATSC30_PTS_COMPENSATE_T *ptInfo, UINT64 *u8Pts);

#define STC_SetAudDeviceId(x, y)        ((void)0)
#define STC_SetVdoDeviceId(x, y)        ((void)0)
#define STC_GetVdoDeviceId(x)           STC_GetSyncTarget(AV_SYNC_TARGET_VDO, x)

#ifdef CC_GET_PCR_PTS_INFO
EXTERN void STC_GetPcr(STC_CLOCK* prPcr);
EXTERN void STC_GetPcrStcDelta(INT64* pi8Delta);
EXTERN void STC_GetAudioPts(STC_CLOCK* prAudioPts);
EXTERN void STC_GetAudioPtsStcDelta(INT64* pi8Delta);
EXTERN BOOL STC_GetAudioSync(void);
EXTERN void STC_GetVideoPts(STC_CLOCK* prVideoPts);
EXTERN void STC_GetVideoPtsStcDelta(INT64* pi8Delta);
EXTERN BOOL STC_GetVideoSync(void);
#endif // CC_GET_PCR_PTS_INFO

EXTERN UCHAR STC_AllocStc(UINT32 u4Src);

EXTERN void STC_FreeStc(UCHAR ucStcId);

EXTERN void DmxSetPcrInfo(UCHAR ucStcId, BOOL ucEnable, UINT32 u4Mask);

#ifdef __cplusplus
}
#endif

#endif /* _DRV_STC_H_ */

