/**
 * @file Hv_Mw_Channel_Manager.c
 * @brief middlware channel manager cpp file.
 * @details This file provides the following functions: \n
 *          (1) Initialization and de-initialization functions \n
 *          (2) Start and stop functions \n
 *          (3) Feed functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-23
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                        <th>Date         <th>Change Description
 * <tr><td>HiView SoC Software Team      <td>2022-08-23   <td>init
 * </table>
*/

#include <string.h>
#include "hv_comm_Utilities.h"
#include "hv_comm_Assert.h"
#include "hv_comm_LinkedList.h"
#include "hv_comm_DataBase.h"
#include "hv_mw_Channel_Manager.h"
#include "hv_mw_StateMachine.h"
#include "hv_mw_Channel_SearchSource.h"
#include "hv_mw_OsdDraw.h"
#include "hv_mw_Video.h"
#include "hv_mw_PQ.h"
#include "hv_mw_Audio.h"
#include "hv_mw_Video_Interrupt.h"
#include "hv_mw_AudioInterrupt.h"
#include "hv_mw_PowerManager.h"
#include "hv_mw_Video_TimingCheck.h"
#include "hv_mw_Hdmi.h"
#include "hv_mw_SystemManager.h"
#include "hv_mw_PanelManager.h"
#include "hv_mw_DisplayPort.h"
#ifdef CONFIG_USER_TYPE_C_ON
#include "hv_mw_TypecTask.h"
#endif
#ifdef CONFIG_USER_USB_OTA_ON
#include "hv_mw_UsbTask.h"
#endif
#include "PanelConfig.h"

#include "hv_drv_DpuCommon.h"
#include "hv_drv_DpuMainScaler.h"

#include "hv_drv_DpuMainMute.h"
#include "hv_cal_DpuMainScaler.h"
#include "hv_cal_Osd.h"
#include "hv_cal_DpuCprConfig.h"
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
#include "hv_drv_DpuSubMute.h"
#include "hv_drv_DpuSubScaler.h"
#include "hv_cal_DpuSubScaler.h"
#endif
#include "hv_drv_HdmiRx.h"
#include "hv_edid_UpdateEdid.h"
#include "hv_drv_Ktx.h"
#include "hv_drv_PLL.h"
#include "hv_drv_Gpio.h"
#include "hv_drv_PQ.h"
#include "hv_drv_Od.h"
#include "hv_chip_Driver.h"
#include "hv_cal_Audio.h"
#include "hv_app_PQ.h"
#include "hv_app_Ddcci.h"
#include "HvPlatform.h"
#include "hv_mw_Led.h"

#define MAX_CHANNEL_CHECK_AV_STABLE_TIMES       (35)
#define HV_DPU_MUTE_STATUS_NORMAL               (0x21)

#define RX_TIMING_STABLE_TIMER_LENGTH           600
#define UNMUTE_VIDEO_TIMER_LENGTH               (RX_TIMING_STABLE_TIMER_LENGTH +200)
#define UNMUTE_AUDIO_TIMER_LENGTH               (RX_TIMING_STABLE_TIMER_LENGTH +600)
#define BURN_IN_PERIOD_CHECK_TIMER_LENGTH       (2000)
#define AV_WATCHDOG_TIMER_LENGTH                (10000)
#define AUDIO_FS_CHECK_TIMER_LENGTH             (200)

static ChannelManager s_stChannelManager;
/****************************inner function declare begin*************************************************/
static Status RunChannelStateMachine(ChannelEvent* pstChannelEvent, ChannelData* pstChannelData, BOOL* pbNeedInsertConvertEvent);
static BOOL PullOneMsgFromChannelInnerMsgQueue(ChannelInnerMsgQueue* pstChInnerMsgQueue, ChannelEvent* pstEvent);
static Status Hv_Mw_Channel_Start(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_Init(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_Search(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_EnterNoSignal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_EnterBurnIn(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_Config(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_ConfigCheck(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_Active(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_SignalLoss(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_ConfigAbnormalProc(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_PeriodSearch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_SearchAbnormal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_TimingChange(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_ColorChange(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_PxpEnable(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_PxpDisable(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_ManifyDisable(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_MagnifyEnable(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_Reconfig(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_NoSignalPeriodCheck(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_NoSignalToSearch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_HdrChanged(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_HdrSwitch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_ProEsportSwitch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_VideoMute_CheckTimeout(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_MuteStateNormal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_AudioMuteCheckTimeout(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_AudioMuteStateNormal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_AudioFsChangeHandle(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_VideoSrcReselect(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_MainSubSourceSwap(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_AspectRatioConfig(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_BurnInPeriodCheck(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_AvWatchDogTimeout(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_FreeSyncSwitch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_MuteStateAbnormal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);
static Status Hv_Mw_Channel_VRRChanged(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData);

/****************************inner function declare end*************************************************/

static const ChannelStateMachine s_astChannelStateMachine[] = 
{
    /*IDLE流程*/
    {CHANNEL_STATE_IDLE,     CHANNEL_EVENT_ID_START,                       Hv_Mw_Channel_Start,                    CHANNEL_STATE_INITIAL,   CHANNEL_STATE_INITIAL},

    /*Initial流程事件*/
    {CHANNEL_STATE_INITIAL,  CHANNEL_EVENT_ID_ON_FIRST_ENTER_STATE,        Hv_Mw_Channel_Init,                     CHANNEL_STATE_SEARCH,    CHANNEL_STATE_INITIAL},

    /*Search流程事件*/
    {CHANNEL_STATE_SEARCH,   CHANNEL_EVENT_ID_ON_FIRST_ENTER_STATE,        Hv_Mw_Channel_Search,                   CHANNEL_STATE_CONFIG,    CHANNEL_STATE_SEARCH}, 
    {CHANNEL_STATE_SEARCH,   CHANNEL_EVENT_ID_PERIOD_SEARCH_TIME_OUT,      Hv_Mw_Channel_PeriodSearch,             CHANNEL_STATE_CONFIG,    CHANNEL_STATE_NO_SIGNAL},  

    /*config流程事件*/
    {CHANNEL_STATE_CONFIG ,  CHANNEL_EVENT_ID_ON_FIRST_ENTER_STATE,        Hv_Mw_Channel_Config,                   CHANNEL_STATE_ACTIVE,    CHANNEL_STATE_SEARCH},
    {CHANNEL_STATE_CONFIG,   CHANNEL_EVENT_ID_CONFIG_CHECK_AV_STABLE,      Hv_Mw_Channel_ConfigCheck,              CHANNEL_STATE_ACTIVE,    CHANNEL_STATE_SEARCH},   
    {CHANNEL_STATE_ANY_STATE \
     ^ CHANNEL_STATE_CONFIG, CHANNEL_EVENT_ID_CONFIG_CHECK_AV_STABLE,      Hv_Mw_Channel_ConfigAbnormalProc,       CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE},   
    {CHANNEL_STATE_ANY_STATE  \
      ^ CHANNEL_STATE_SEARCH \
      ^ CHANNEL_STATE_NO_SIGNAL, CHANNEL_EVENT_ID_PERIOD_SEARCH_TIME_OUT,  Hv_Mw_Channel_SearchAbnormal,           CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE}, 

    /*NoSignal流程事件*/
    {CHANNEL_STATE_NO_SIGNAL, CHANNEL_EVENT_ID_ON_FIRST_ENTER_STATE,       Hv_Mw_Channel_EnterNoSignal,            CHANNEL_STATE_NO_SIGNAL, CHANNEL_STATE_BURN_IN},
    {CHANNEL_STATE_NO_SIGNAL, CHANNEL_EVENT_ID_NO_SIGNAL_CHECK_TIMER,      Hv_Mw_Channel_NoSignalPeriodCheck,      CHANNEL_STATE_NO_SIGNAL, CHANNEL_STATE_SEARCH},
    {CHANNEL_STATE_NO_SIGNAL, CHANNEL_EVENT_ID_NO_SIGNAL_TO_SEARCH,        Hv_Mw_Channel_NoSignalToSearch,         CHANNEL_STATE_SEARCH,    CHANNEL_STATE_NO_SIGNAL},

    /*老化流程事件*/
    {CHANNEL_STATE_BURN_IN,   CHANNEL_EVENT_ID_ON_FIRST_ENTER_STATE,       Hv_Mw_Channel_EnterBurnIn,              CHANNEL_STATE_BURN_IN,   CHANNEL_STATE_BURN_IN},
    {CHANNEL_STATE_BURN_IN,   CHANNEL_EVENT_ID_BURN_IN_PERIOD_CHECK_TIMER, Hv_Mw_Channel_BurnInPeriodCheck,        CHANNEL_STATE_BURN_IN,   CHANNEL_STATE_SEARCH},

    /*Acitve状态涉及流程事件*/
    {CHANNEL_STATE_ACTIVE,   CHANNEL_EVENT_ID_ON_FIRST_ENTER_STATE,        Hv_Mw_Channel_Active,                   CHANNEL_STATE_ACTIVE,    CHANNEL_STATE_SEARCH},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_SIGNAL_LOSS,                Hv_Mw_Channel_SignalLoss,               CHANNEL_STATE_SEARCH,    CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_PLUG_OUT,                   Hv_Mw_Channel_SignalLoss,               CHANNEL_STATE_SEARCH,    CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_CONFIG \
     | CHANNEL_STATE_ACTIVE, CHANNEL_EVENT_ID_TIMING_CHANGE,               Hv_Mw_Channel_TimingChange,             CHANNEL_STATE_SEARCH,    CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_CONFIG \
     | CHANNEL_STATE_ACTIVE, CHANNEL_EVENT_ID_COLOR_CHANGE,                Hv_Mw_Channel_ColorChange,              CHANNEL_STATE_SEARCH,    CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ACTIVE, CHANNEL_EVENT_ID_AUDIO_FS_CHANGE,               Hv_Mw_Channel_AudioFsChangeHandle,      CHANNEL_STATE_ACTIVE,    CHANNEL_STATE_SEARCH},    
    {CHANNEL_STATE_ACTIVE,    CHANNEL_EVENT_ID_MUTE_STATE_NORMAL,          Hv_Mw_Channel_MuteStateNormal,          CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ACTIVE,    CHANNEL_EVENT_ID_MUTE_STATE_ABNORMAL,        Hv_Mw_Channel_MuteStateAbnormal,        CHANNEL_STATE_SEARCH,    CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_MUTE_CHECK_TIMER_OUT,       Hv_Mw_Channel_VideoMute_CheckTimeout,   CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ACTIVE,    CHANNEL_EVENT_ID_AUDIO_MUTE_STATE_CHANGE,    Hv_Mw_Channel_AudioMuteStateNormal,     CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE},    
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_AUDIO_MUTE_CHECK_TIMER_OUT, Hv_Mw_Channel_AudioMuteCheckTimeout,    CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE},
    
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_AV_WATCHDOG,                Hv_Mw_Channel_AvWatchDogTimeout,        CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE},

    /*OSD菜单事件任意状态均需要处理相关事件流程*/
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_PXP_ENABLE,                 Hv_Mw_Channel_PxpEnable,                CHANNEL_STATE_SEARCH,    CHANNEL_STATE_SEARCH},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_PXP_DISABLE,                Hv_Mw_Channel_PxpDisable,               CHANNEL_STATE_SEARCH,    CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_SUB_PXP_DISABLE,            Hv_Mw_Channel_PxpDisable,               CHANNEL_STATE_IDLE,      CHANNEL_STATE_IDLE},
#endif
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY)
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_MAGNIFY_DISABLE,            Hv_Mw_Channel_ManifyDisable,            CHANNEL_STATE_SEARCH,    CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_MAGNIFY_ENABLE,             Hv_Mw_Channel_MagnifyEnable,            CHANNEL_STATE_SEARCH,    CHANNEL_STATE_ACTIVE},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_SUB_MAGNIFY_DISABLE,        Hv_Mw_Channel_ManifyDisable,            CHANNEL_STATE_IDLE,      CHANNEL_STATE_IDLE},
#endif
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_SET_ASPECT_RATIO,           Hv_Mw_Channel_AspectRatioConfig,        CHANNEL_STATE_SEARCH,    CHANNEL_STATE_SEARCH},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_DATA_PATH_RECONFIG,         Hv_Mw_Channel_Reconfig,                 CHANNEL_STATE_SEARCH,    CHANNEL_STATE_SEARCH},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_RESELECT_VIDEO_SRC,         Hv_Mw_Channel_VideoSrcReselect,         CHANNEL_STATE_SEARCH,    CHANNEL_STATE_SEARCH},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_MAIN_SUB_SOURCE_SWAP,       Hv_Mw_Channel_MainSubSourceSwap,        CHANNEL_STATE_SEARCH,    CHANNEL_STATE_SEARCH},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_HDR_CHANGED,                Hv_Mw_Channel_HdrChanged,               CHANNEL_STATE_SEARCH,    CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_HDR_SWITCH,                 Hv_Mw_Channel_HdrSwitch,                CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_PRO_ESPORT_SWITCH,          Hv_Mw_Channel_ProEsportSwitch,          CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_FREE_SYNC_SWITCH,           Hv_Mw_Channel_FreeSyncSwitch,           CHANNEL_STATE_ANY_STATE, CHANNEL_STATE_ANY_STATE},
    {CHANNEL_STATE_ANY_STATE, CHANNEL_EVENT_ID_RCV_VRR_INFO,               Hv_Mw_Channel_VRRChanged,               CHANNEL_STATE_ANY_STATE,  CHANNEL_STATE_ANY_STATE},
};

/* FIFO是否为空 */
static BOOL QueueIsEmpty(ChannelInnerMsgQueue *pstQueue)
{
    return (pstQueue->usWriteAddr == pstQueue->usReadAddr);
}

/* FIFO是否为满 */
static BOOL QueueIsFull(ChannelInnerMsgQueue *pstQueue)
{
    return ((pstQueue->usWriteAddr + 1) % MAX_CHANNEL_QUEUE_SIZE == pstQueue->usReadAddr);
}

/* FIFO复位 */
static VOID QueueReset(ChannelInnerMsgQueue *pstQueue)
{
    pstQueue->usWriteAddr = 0;
    pstQueue->usReadAddr = 0;
    for(USHORT16 usIndex = 0; usIndex < MAX_CHANNEL_QUEUE_SIZE; usIndex++)
    {
        HV_MEMSET(&pstQueue->astFifo[usIndex], 0 , sizeof(pstQueue->astFifo[usIndex]));
    }
    return;
}

/* FIFO写入数据 */
static QueueStatus QueueWrite(ChannelInnerMsgQueue *pstQueue, const ChannelEvent *pstData)
{
    if (QueueIsFull(pstQueue))
    {
        HV_LOG_ERROR(CHANNEL,"Write failed(%d), queue is full");
        return QUEUE_FULL;
    }
    HV_MEMCPY(&pstQueue->astFifo[pstQueue->usWriteAddr], pstData, sizeof(ChannelEvent));
    pstQueue->usWriteAddr = (pstQueue->usWriteAddr + 1) % MAX_CHANNEL_QUEUE_SIZE;
    return QUEUE_OK;
}

/* FIFO读出数据 */
static QueueStatus QueueRead(ChannelInnerMsgQueue *pstQueue, ChannelEvent *pstdata)
{
    if (QueueIsEmpty(pstQueue))
    {
        return QUEUE_EMPTY;
    }
    HV_MEMCPY(pstdata, &pstQueue->astFifo[pstQueue->usReadAddr], sizeof(ChannelEvent));
    pstQueue->usReadAddr = (pstQueue->usReadAddr + 1) % MAX_CHANNEL_QUEUE_SIZE;

    return QUEUE_OK;
}

/* FIFO内数据的个数 */
static USHORT16 QueueCount(ChannelInnerMsgQueue *pstQueue)
{
    if (pstQueue->usReadAddr <= pstQueue->usWriteAddr)
    {
        return (pstQueue->usWriteAddr - pstQueue->usReadAddr);
    }
    return (MAX_CHANNEL_QUEUE_SIZE + pstQueue->usWriteAddr - pstQueue->usReadAddr);
}

static Status SendSignalStateToOsd(const ChannelData* pstChannelData, USHORT16 usEventId)
{
#ifdef CONFIG_USER_USB_OTA_ON
    if(USB_STATE_OTA_IN_PROCESSING == Hv_Mw_USB_GetUsbState())
    {
        return HV_SUCCESS;
    }
#endif
    HV_VOS_QUEUE_S *pOsdQueue = Hv_Mw_System_GetOsdQueue();
    HV_ASSERT_VALID_PTR(pOsdQueue);
    OsdEvent stOsdEvent = {0};
    switch (usEventId)
    {
        case OSD_EVENT_SIGNAL_STATE_CHANGE:
        case OSD_EVENT_SIGNAL_PARAM_CHANGE:
        case OSD_EVENT_TIMER_LOGO_HIDE:
        case OSD_EVENT_SIGNAL_READY:
        case OSD_EVENT_SIGNAL_PLUG_OUT:
        {
            stOsdEvent.usEventId = usEventId;
            stOsdEvent.usValue |= pstChannelData->enChannelType & 0x00FF;
            stOsdEvent.usValue |= (pstChannelData->enChannelSrcLinkPortIndex << 8) & 0xFF00;
            break;
        }
        case OSD_EVENT_FACTORY_AGING_REFRESH:
        case OSD_EVENT_FACTORY_AGING_EXIT:
        case OSD_EVENT_HIDE_ALL:
        {
            stOsdEvent.usEventId = usEventId;
            stOsdEvent.usValue = 0;
            break;
        }
        case OSD_EVENT_SIGNAL_TIMING_NOT_SUPPORT:               /*给OSD发NOT_SUPPORT消息分为NOT_SUPPORT和OUT_OF_RANGE两种，通过value区分，OUT_OF_RANGE在search中发送*/
        {
            stOsdEvent.usEventId = usEventId;
            stOsdEvent.usValue |= ERROR_RX_TIMING_UNSUPPORT & 0x00FF;
            stOsdEvent.usValue |= (pstChannelData->enChannelType << 8) & 0x0F00;
            stOsdEvent.usValue |= (pstChannelData->enChannelSrcLinkPortIndex << 12) & 0xF000;
            break;
        }
        default:
        {
            break;
        }
    }
    HV_ASSERT_PEEK_TRUE(Hv_Vos_QueueSend(pOsdQueue, &stOsdEvent));
    HV_LOG_DEBUG(CHANNEL, "send signal to OsdTask usEventId=0x%x!!!, value:%u, channel:%u", usEventId, stOsdEvent.usValue, pstChannelData->enChannelType);
    return HV_SUCCESS;
}

static Status SendBacklightOffToPanel(VOID)
{
    Hv_Mw_Panel_SetTimingChangeFlag(HV_TRUE);
    PanelEvent stPanelEvent = {0};
    stPanelEvent.usEventId = PANEL_EVENT_ID_BLK_OFF;
    HV_ASSERT_SUCCESS(Hv_Mw_Panel_SendInnerMsg(&stPanelEvent));
    return HV_SUCCESS;
}

#ifdef CONFIG_USER_TYPE_C_ON
static Status SendSignalLossToTypec(LinkPortIndex enPortIndex)
{
    if(LINK_PORT_INDEX_DP_RX0 == enPortIndex)
    {
        Hv_Mw_Typec_DpSignalLoss();
    }
    return HV_SUCCESS;
}
#endif

static BOOL IsPxpSwitchEvent(const ChannelEvent* pstChannelEvent)
{
    return (CHANNEL_EVENT_ID_PXP_ENABLE == pstChannelEvent->usEventId) ||
           (CHANNEL_EVENT_ID_PXP_DISABLE == pstChannelEvent->usEventId) ||
           (CHANNEL_EVENT_ID_SUB_PXP_DISABLE == pstChannelEvent->usEventId) ||
           (CHANNEL_EVENT_ID_MAGNIFY_DISABLE == pstChannelEvent->usEventId) ||
           (CHANNEL_EVENT_ID_MAGNIFY_ENABLE == pstChannelEvent->usEventId) ||
           (CHANNEL_EVENT_ID_SUB_MAGNIFY_DISABLE == pstChannelEvent->usEventId);
}

Status Hv_Mw_Channel_SendInnerMsg(const ChannelEvent* pstChannelEvent)
{
    HV_ASSERT_VALID_PTR(pstChannelEvent);
    if (CHANNEL_TYPE_MAIN == pstChannelEvent->enChannelType)
    {
        HV_ASSERT_TRUE(QUEUE_OK == QueueWrite(&s_stChannelManager.stChInnerMsgQueue, pstChannelEvent));
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else if (CHANNEL_TYPE_SUB == pstChannelEvent->enChannelType)
    {
        /*此处增加保护，PIP/PBP打开的场景下才可以给辅助通道发送消息
        当PIP/PBP配置处于关闭，辅助通道仅支持开关消息，防止一些OSD或者Port消息误传消息激活了辅通道状态机，
        状态机在Anysate未作保护会切换到search态*/
        UCHAR8 ucPxpMode = (HV_COMMON_DATABASE_GET(UserData, ucPxPMode) || HV_COMMON_DATABASE_GET(UserData, bMagnifyGlassSw));
        if ((ucPxpMode  > 0) 
            || ((ucPxpMode == 0) && IsPxpSwitchEvent(pstChannelEvent)))
        {
            HV_ASSERT_TRUE(QUEUE_OK == QueueWrite(&s_stChannelManager.stChInnerMsgQueue, pstChannelEvent));
        }
    }
#endif
    else
    {
        HV_LOG_ERROR(CHANNEL, "invalid channelType=%u",pstChannelEvent->enChannelType);
        return HV_FAILURE;
    }
    return HV_SUCCESS;
}

static BOOL PullOneMsgFromChannelInnerMsgQueue(ChannelInnerMsgQueue* pstChInnerMsgQueue, ChannelEvent* pstEvent)
{
    if (QUEUE_OK == QueueRead(&s_stChannelManager.stChInnerMsgQueue, pstEvent))
    {
        return HV_TRUE;
    }
    return HV_FALSE;
}

BOOL Hv_Mw_Channel_HasInnerMsgs( VOID )
{
    return !(QueueIsEmpty(&s_stChannelManager.stChInnerMsgQueue));
}

Status Hv_Mw_Channel_ProcInnerMsgs()
{
    ChannelEvent stChannelEvent = {0};
    BOOL bHasMsg = HV_FALSE;
    do   
    {
        BOOL bNeedInsertConvertEvent = HV_FALSE;
        bHasMsg = PullOneMsgFromChannelInnerMsgQueue(&s_stChannelManager.stChInnerMsgQueue, &stChannelEvent);
        if (HV_TRUE == bHasMsg)
        {
            if (CHANNEL_TYPE_MAIN == stChannelEvent.enChannelType)
            {
                RunChannelStateMachine(&stChannelEvent, &s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN], &bNeedInsertConvertEvent); 
            }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
            else if (CHANNEL_TYPE_SUB == stChannelEvent.enChannelType)
            {
                RunChannelStateMachine(&stChannelEvent, &s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB], &bNeedInsertConvertEvent); 
            }
#endif
            else
            {
                HV_LOG_ERROR(CHANNEL, "unknow ChannelEvent usEventId = %u,enChannelType = %u", stChannelEvent.usEventId,stChannelEvent.enChannelType);
            }

            if (bNeedInsertConvertEvent)
            {
                ChannelEvent stConvertEvent = {0};
                stConvertEvent.usEventId = CHANNEL_EVENT_ID_ON_FIRST_ENTER_STATE;
                stConvertEvent.usValue = stChannelEvent.usValue;
                stConvertEvent.enChannelType = stChannelEvent.enChannelType;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stConvertEvent));
            }
        }
    } while ( bHasMsg );

    return HV_SUCCESS;
}

/****************************inner  function end*************************************************/
static Status Hv_Mw_Channel_Start(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_Start enChannelType=%u", pstChannelData->enChannelType);
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if (CHANNEL_TYPE_SUB == pstChannelEvent->enChannelType)
    {
        Hv_Drv_DpuScaler_SetSubChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_IDLE);
    }
#endif
    if (CHANNEL_TYPE_MAIN == pstChannelEvent->enChannelType)
    {
        Hv_Drv_DpuScaler_SetMainChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_IDLE);
    }
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_Init(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_Init enChannelType=%u", pstChannelData->enChannelType);
    pstChannelData->uiEnterNoSignalCount = 0;
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if (PBP_SIZE_SMALL == HV_COMMON_DATABASE_GET(UserData, ucPbpSize))
    {
        HV_COMMON_DATABASE_SET(UserData, usPbpWindowHSize, HV_COMMON_DATABASE_GET(UserData, usPbpSmallWindowHSize));
    }
    else if (PBP_SIZE_MIDDLE == HV_COMMON_DATABASE_GET(UserData, ucPbpSize))
    {
        HV_COMMON_DATABASE_SET(UserData, usPbpWindowHSize, HV_COMMON_DATABASE_GET(UserData, usPbpMiddleWindowHSize));
    }
    else
    {
        HV_COMMON_DATABASE_SET(UserData, usPbpWindowHSize, HV_COMMON_DATABASE_GET(UserData, usPbpBigWindowHSize));
    }
    if (CHANNEL_TYPE_SUB == pstChannelEvent->enChannelType)
    {
        Hv_Drv_DpuScaler_SetSubChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_INITIAL);
        Hv_Drv_DpuScaler_SetSubPathClkEn(1);
    }
#endif
    if (CHANNEL_TYPE_MAIN == pstChannelEvent->enChannelType)
    {
        Hv_Drv_DpuScaler_SetMainChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_INITIAL);
    }
    /*不区分主通道还是辅通道*/
    if ((POWER_ON_REASON_TYPE_POWER_ON != Hv_Mw_Power_GetPowerOnReasonType())
        || (HV_FALSE == HV_COMMON_DATABASE_GET(SystemData, bShowLogoFlag)))
    {
        /*非AC ON赋值为HV_TRUE代表流程不需要在等待OSD显示logo*/
        Hv_Mw_OsdSetLogoBypass();
    }
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_Search(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Enter Hv_Mw_Channel_Search");
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if(CHANNEL_TYPE_SUB == pstChannelData->enChannelType)
    {
        Hv_Drv_DpuScaler_SetSubChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_SEARCH);
        Hv_Drv_DpuScaler_SubChannelClose();
        if (Hv_Mw_Channel_GetChannelOnDisplay() == 0)
        {
            Hv_Drv_DpuScaler_LdgSubBorderEn(HV_FALSE);
        }
    }
    if (HV_TRUE == s_stChannelManager.stChannelFlashConfig.bFlashSubFakeVideoSw)
    {
        Hv_Drv_DpuScaler_SubLdgTopSubBlendEn(HV_FALSE);
    }
#endif
    /*mute for abnormal display*/
    Hv_Mw_Channel_MuteOn(pstChannelData->enChannelType);
    /*close other port audio*/
    Hw_Mw_AudioPath_Mux(pstChannelData,pstChannelData->enChannelType);
    /*close mute/audio/vsync interrupt,*/
    Hv_Mw_Mute_Interrupt_Disable(pstChannelData->enChannelType);
    Hv_Mw_Audio_Interrupt_Disable();
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_FULL_LOCALDIMMING)
    if ((0 == Hv_Mw_Channel_GetChannelOnDisplay()) && (HV_FALSE == Hv_Mw_OsdCheckIsShowing()))
    {
        Hv_Drv_DpuScaler_Disable_Vsync_Interrupt();   //PXP+LDC时需要vsync用来发背光数据，Main sub osd都没有显示时关闭
    }
#else
    Hv_Drv_DpuScaler_Disable_Vsync_Interrupt();
#endif
    /*stop timer*/
    Hv_Vos_Timer_Rstop(pstChannelData->pstNoSignalTimer);
    Hv_Vos_Timer_Rstop(pstChannelData->pstAudioMuteTimer);
    Hv_Vos_Timer_Rstop(pstChannelData->pstVideoMuteTimer);
    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        Hv_Drv_DpuScaler_SetMainChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_SEARCH);
        Hv_Vos_Timer_Rstop(pstChannelData->pstAvWatchdogTimer);
    }
    /*send signal to osd*/
    if ((ChanelSignalState_SearchState != pstChannelData->enChanelSignalState) &&(pstChannelData->uiEnterNoSignalCount == 0))
    {
        pstChannelData->enChanelSignalState = ChanelSignalState_SearchState;
        HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_SIGNAL_STATE_CHANGE));
        HV_LOG_DEBUG(CHANNEL, "Enter Search State Channel %u,Notify OSD success!", pstChannelData->enChannelType);
    }
    /*search table init*/
    Hw_Mw_SearchTable_Init(pstChannelData);
    /*第一次进入search态将错误码初始化为无信号，后续配置正确错误码更新为SUCCESS，或者具体发生的错误.*/
    pstChannelData->usTotalSearchTimes = 0;
    pstChannelData->uiErrorCode = ERROR_RX_NO_SIGNAL;

    /*start period search timer*/
    Hv_Vos_Timer_Rstart(pstChannelData->pstPeriodSearchTimer,0);
    return HV_CONTINUE;
}

static Status Hv_Mw_Channel_PeriodSearch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    Status uiSearchResult = HV_CONTINUE;
    HV_LOG_DEBUG(CHANNEL, "Channel Period Search... enChannelType=%u", pstChannelData->enChannelType);
    const PanelManager* pstPanelManager = Hv_Mw_Panel_GetManagerPtr();
#if (HV_PROJECT_CONFIG_TCON_POWER_CONTROL == HV_CONFIG_ON)
    /*关闭背光即要关屏，在channel config时关屏，config check时开屏，如果在config时发生timing lost不能关屏，否则跳到search时会在卡在panel上，无信号时没有开屏*/
    if ((PANEL_STATE_OFF == pstPanelManager->enCurrentPanelState)
    &&(HV_FALSE == Hv_Mw_Power_GetPowerManagerFakeStandyFlag()))
    {
        HV_LOG_DEBUG(CHANNEL, "channel StartPanelPowerOnTimer");
        Hv_Mw_Panel_StartPanelPowerOnTimer();
    }
#endif
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if(CHANNEL_TYPE_SUB == pstChannelData->enChannelType)
    {
        if (Hv_Mw_Channel_GetChannelOnDisplay() == 0)
        {
            Hv_Drv_DpuScaler_LdgSubBorderEn(HV_FALSE);
        }
    }
#endif
    if((CHANNEL_TYPE_MAIN == pstChannelData->enChannelType) && (Hv_Mw_OsdGetLogoState() == OSD_LOGO_DONE))
    {
        Hv_Drv_DpuScaler_MainChannelEncDecDisenable();
        if ((0 == Hv_Mw_Channel_GetChannelOnDisplay()) && (HV_FALSE == Hv_Mw_OsdCheckIsShowing()))  /*OSD 没有显示*/
        {
#ifdef CONFIG_USER_USB_OTA_ON
            if(USB_STATE_OTA_IN_PROCESSING != Hv_Mw_USB_GetUsbState())
            {
                #if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
                Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_DISABLE);
                #endif
            }
#else
            #if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
            Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_DISABLE);
            #endif
#endif
        }
    }
    if((pstPanelManager->enCurrentPanelState != PANEL_STATE_BLK_ON) && (pstPanelManager->bTimingChangeFlag == HV_FALSE))
    {
        HV_LOG_INFO(CHANNEL, "Wait for panel init end ......");
        Hv_Vos_Timer_Rstart(pstChannelData->pstPeriodSearchTimer,0);
        return HV_CONTINUE;
    }
    if ((ERROR_RX_TIMING_UNSUPPORT == pstChannelData->uiErrorCode)
     || (ERROR_RX_TIMING_FREQ_OUT_OF_RANGE == pstChannelData->uiErrorCode)
     || (ERROR_RX_TIMING_COLOR_DEPTH_NOT_SUPPORT == pstChannelData->uiErrorCode)) /*遇到不支持的timing，进入无信号状态*/
    {
        return HV_FAILURE;
    }
    uiSearchResult = Hw_Mw_Channel_SearchSuitableSource(pstChannelData);
    if (HV_CONTINUE == uiSearchResult)
    {
        Hv_Vos_Timer_Rstart(pstChannelData->pstPeriodSearchTimer,0);
        /*返回continue 状态机一直保持search态,启动PeriodSearchTimer，超时触发下一次PeriodSearch流程*/
        return HV_CONTINUE;
    }
    else if (HV_SUCCESS == uiSearchResult)
    {
        /*有开机logo，等待开机logo显示完成.*/
        if (Hv_Mw_OsdGetLogoState() != OSD_LOGO_DONE)
        {
            HV_LOG_DEBUG(CHANNEL, "Wait for display logo to end......");
            Hv_Vos_Timer_Rstart(pstChannelData->pstPeriodSearchTimer,0);
            return HV_CONTINUE;
        }
        else
        {
            if (0 == Hv_Mw_Channel_GetChannelOnDisplay() && (CHANNEL_TYPE_MAIN == pstChannelEvent->enChannelType)
            && (pstPanelManager->bTimingChangeFlag == HV_FALSE))
            {
                Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_DISABLE);
            }
            Hv_Mw_Panel_SetTimingChangeFlag(HV_TRUE);    /*logo显示完成，允许关tcon电源*/
            Hv_Vos_Timer_Rstop(pstChannelData->pstPeriodSearchTimer);
            /*找到了可用的端口，返回成功则状态机进入CONFIG态*/
            return HV_SUCCESS;
        }
    }
    else
    {
        if(Hv_Mw_OsdGetLogoState() != OSD_LOGO_DONE)
        {
            HV_LOG_INFO(CHANNEL, "Search timing abnormal,continue search");
            Hv_Vos_Timer_Rstart(pstChannelData->pstPeriodSearchTimer,0);
            return HV_CONTINUE;
        }
        else
        {
            return HV_FAILURE;/*enter no signal state*/
        }
    }
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_SearchAbnormal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_SearchAbnormal");
    Hv_Vos_Timer_Rstop(pstChannelData->pstPeriodSearchTimer);
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_EnterNoSignal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_EnterNoSignal");
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if (CHANNEL_TYPE_SUB == pstChannelEvent->enChannelType)
    {
        Hv_Drv_DpuScaler_SetSubChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_NO_SIGNAL);
    }
#endif
    if (CHANNEL_TYPE_MAIN == pstChannelEvent->enChannelType)
    {
        Hv_Drv_DpuScaler_SetMainChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_NO_SIGNAL);
    }
    /*第一次进入Nosignal态清空 checktime统计和 长时间无信号标志*/
    pstChannelData->bAVStable            = HV_FALSE;
    pstChannelData->usNoSignalCheckTimes = 0;
    pstChannelData->bNoSignalLongTimes   = HV_FALSE;
    pstChannelData->bStandByFlag         = HV_FALSE;
    pstChannelData->enChanelSignalState  = ChanelSignalState_NoSignal;
    Hv_Drv_DpuScaler_SetPortMux(pstChannelData->enChannelType, LINK_PORT_INDEX_INVALID);
    s_stChannelManager.bSignalInterruption = HV_FALSE;

    if(LINK_PORT_INDEX_INVALID != pstChannelData->enChannelSrcLinkPortIndex)
    {
        pstChannelData->enLastChannelSrcLinkPortIndex = pstChannelData->enChannelSrcLinkPortIndex;
        //pstChannelData->enChannelSrcLinkPortIndex = LINK_PORT_INDEX_INVALID;
    }

    if ((1 == HV_COMMON_DATABASE_GET(SystemData, bFactoryMode)) 
     && (1 == HV_COMMON_DATABASE_GET(SystemData, bBurnInEnable))
     && (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
     && (0 == Hv_Mw_Channel_GetChannelOnDisplay()
     && (ERROR_RX_TIMING_UNSUPPORT != pstChannelData->uiErrorCode))
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
     &&(PXP_MODE_CLOSE == Hv_Mw_Channel_GetPxpMode())
#endif
     )
    {
        HV_LOG_INFO(CHANNEL, "Enter Burnin state directly in factory mode!");
        return HV_FAILURE; /*enter burn in state directly*/
    }
    else
    {
        if (pstChannelData->uiEnterNoSignalCount == 0)/*send no signal to osd only once*/
        {
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
            if (0 == Hv_Mw_Channel_GetChannelOnDisplay())
            {
                Hv_Drv_DpuScaler_LdgSubBorderEn(HV_FALSE);
            }
            if ((PXP_MODE_CLOSE != s_stChannelManager.stChannelFlashConfig.enFlashPxPMode) && (HV_FALSE == s_stChannelManager.stChannelFlashConfig.bFlashSubFakeVideoSw))
            {
                /*重新发送一次sub的消息给OSD，显示sub timing 信息*/
                if ((ERROR_RX_TIMING_UNSUPPORT == pstChannelData->uiErrorCode)
                || (ERROR_RX_TIMING_FREQ_OUT_OF_RANGE == pstChannelData->uiErrorCode)
                || (ERROR_RX_TIMING_COLOR_DEPTH_NOT_SUPPORT == pstChannelData->uiErrorCode))
                {
                    HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(&(s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB]), OSD_EVENT_SIGNAL_TIMING_NOT_SUPPORT));
                }
                else if (pstChannelData->stRxVideoTiming.bIsNoSignal)
                {
                    HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(&(s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB]), OSD_EVENT_SIGNAL_STATE_CHANGE));
                }
                else
                {
                    HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(&(s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB]), OSD_EVENT_SIGNAL_TIMING_NOT_SUPPORT));
                }
            }
    #if (HV_PROJECT_CONFIG_TCON_POWER_CONTROL == HV_CONFIG_ON)
            if ((CHANNEL_STATE_ACTIVE == s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enCurrentCHState)
            && (HV_FALSE == s_stChannelManager.stChannelFlashConfig.bFlashSubFakeVideoSw))
            {
                Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_ENABLE);
            }
    #endif
#endif
            if ((ERROR_RX_TIMING_UNSUPPORT == pstChannelData->uiErrorCode)
            || (ERROR_RX_TIMING_FREQ_OUT_OF_RANGE == pstChannelData->uiErrorCode)
            || (ERROR_RX_TIMING_COLOR_DEPTH_NOT_SUPPORT == pstChannelData->uiErrorCode))
            {
                HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_SIGNAL_TIMING_NOT_SUPPORT));
            }
            else if (pstChannelData->stRxVideoTiming.bIsNoSignal)
            {
                HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_SIGNAL_STATE_CHANGE));
            }
            else
            {
                HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_SIGNAL_TIMING_NOT_SUPPORT));
            }
            HV_LOG_INFO(CHANNEL, "Enter NoSignal count %u,IsNoSignal %u, Channel %u, Notify OSD success! ", pstChannelData->uiEnterNoSignalCount, pstChannelData->stRxVideoTiming.bIsNoSignal, pstChannelData->enChannelType);
            const PanelManager* pstPanelManager = Hv_Mw_Panel_GetManagerPtr();
            if(pstPanelManager->enCurrentPanelState == PANEL_STATE_BLK_ON)
            {
                Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_ENABLE);
            }
        }
        pstChannelData->uiEnterNoSignalCount++;
        if (CHANNEL_TYPE_MAIN == pstChannelEvent->enChannelType)
        {
            /*先关掉DDR的读，防止解除插黑时从DDR读出异常数据导致绿屏*/
            Hv_Drv_DpuScaler_DpuDataPath_Reset(0);
        }
        Hv_Vos_Timer_Rstart(pstChannelData->pstNoSignalTimer,0);
        return HV_SUCCESS;
    }
}

BOOL AllChannelNoSignalLongTimes(VOID)
{
    BOOL bMainNoSignalLongTimes = s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].bNoSignalLongTimes;
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    BOOL bSubNoSignalLongTimes = s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].bNoSignalLongTimes;
    if (PXP_MODE_CLOSE == Hv_Mw_Channel_GetPxpMode())
    {
        return bMainNoSignalLongTimes;
    }
    else
    {
        return bMainNoSignalLongTimes && bSubNoSignalLongTimes;
    }
#else
    return bMainNoSignalLongTimes;
#endif
}

static Status Hv_Mw_Channel_NoSignalPeriodCheck(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_NoSignalPeriodCheck pstChannelData->usNoSignalCheckTimes=%u", pstChannelData->usNoSignalCheckTimes);
#if (HV_PROJECT_CONFIG_TCON_POWER_CONTROL == HV_CONFIG_ON)
    const PanelManager* pstPanelManager = Hv_Mw_Panel_GetManagerPtr();
    HV_LOG_DEBUG(CHANNEL, "*** sub:%u, pxp:%u, sub status:%u", Hv_Mw_Panel_GetTimingChangeFlag(), Hv_Mw_Channel_GetPxpMode(), s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enCurrentCHState);
    if((CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    && (HV_TRUE == Hv_Mw_Panel_GetTimingChangeFlag())
    && (PXP_MODE_CLOSE != Hv_Mw_Channel_GetPxpMode())
    && (CHANNEL_STATE_ACTIVE == s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enCurrentCHState))
    {
        if (PANEL_STATE_OFF == pstPanelManager->enCurrentPanelState)
        {
            HV_LOG_INFO(CHANNEL, "channel, sub active start panel power");
            Hv_Mw_Panel_StartPanelPowerOnTimer();
            HV_ASSERT_TRUE(Hv_Vos_Timer_Start(pstChannelData->pstNoSignalTimer));
            return HV_CONTINUE;
        }
        else if(PANEL_STATE_BLK_ON != pstPanelManager->enCurrentPanelState)
        {
            HV_LOG_DEBUG(CHANNEL, "panel is not ready, channel still waite");
            HV_ASSERT_TRUE(Hv_Vos_Timer_Start(pstChannelData->pstNoSignalTimer));
            return HV_CONTINUE;
        }
    }
#endif

    if(HV_TRUE == Hv_Mw_Channel_GetOSDActive())//如果当前有按键操作
    {
        pstChannelData->usNoSignalCheckTimes = 0;
        Hv_Mw_Channel_SetOSDActive(HV_FALSE);
        Hv_Mw_Channel_MuteOff(CHANNEL_TYPE_MAIN);   //显示osd不需要解插黑，只开背光
    }
    else
    {
        if(HV_FALSE == Hv_Mw_OsdCheckIsShowing() && (Hv_Mw_Channel_GetChannelOnDisplay() == 0))//如果当前无OSD显示且sub和Main都无显示
        {
            Hv_Mw_Channel_MuteOn(pstChannelData->enChannelType);
        }
        pstChannelData->usNoSignalCheckTimes++;
        if (pstChannelData->usNoSignalCheckTimes >= HV_PROJECT_CONFIG_NO_SIGNAL_CHECK_TIMES)
        {
            pstChannelData->bNoSignalLongTimes = HV_TRUE;
        }
    }
    /*仅在主通道 判决进入待机和老化模式*/
    if ((HV_TRUE == AllChannelNoSignalLongTimes()) && (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType))
    {
        const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
        pstInputPortManager->pfGetVideoPara(pstChannelData->enChannelSrcLinkPortIndex, pstChannelData);     /*更新当前通道的bIsNoSignal信息*/
        if ((HV_FALSE == pstChannelData->bStandByFlag) 
        && (0 == Hv_Mw_Channel_GetChannelOnDisplay())
        && (ERROR_RX_NO_SIGNAL == pstChannelData->uiErrorCode)
        && (1 == pstChannelData->stRxVideoTiming.bIsNoSignal))
        {
            Hv_Mw_Channel_MuteOn(CHANNEL_TYPE_MAIN);
            BOOL bIsAutoPowerOff = HV_FALSE;
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_AUTO_POWER_OFF)
            bIsAutoPowerOff = HV_COMMON_DATABASE_GET(UserData, ucAutoPowerOff)
#endif
            if (bIsAutoPowerOff)
            {   /*进关机*/
                Hv_Mw_Power_SendPoweroffToPowerManager();
            }
            else
            {
                /*Send standby message to PowerState machine*/
                HV_ASSERT_SUCCESS(Hw_Mw_Channel_SendNoSignalMsgToPowerManager(HV_TRUE));
            }
        }
    }
    if ((HV_SUCCESS == Hw_Mw_Channel_NoSignal_SearchPort(pstChannelData))
    && (ERROR_RX_TIMING_UNSUPPORT != pstChannelData->uiErrorCode)) 
    {
        /*在无信号期间搜索到了信号责返回failure退出无信号状态,同时通知power状态机退出无信号待机状态*/
        if (HV_TRUE == pstChannelData->bStandByFlag)
        {
            HV_ASSERT_SUCCESS(Hw_Mw_Channel_SendNoSignalMsgToPowerManager(HV_FALSE));
        }
        return HV_FAILURE; //进入search状态
    }
    else
    {
        Hv_Vos_Timer_Rstart(pstChannelData->pstNoSignalTimer,0);
    }
    /*返回HV_CONTINUE 继续处于Nosignal态*/
    return HV_CONTINUE;
}

static Status Hv_Mw_Channel_NoSignalToSearch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    /*在无信号期间搜索到了信号责返回failure退出无信号状态,同时通知power状态机退出无信号待机状态*/
    pstChannelData->uiEnterNoSignalCount = 0;
    if (HV_TRUE == pstChannelData->bStandByFlag)
    {
        HV_ASSERT_SUCCESS(Hw_Mw_Channel_SendNoSignalMsgToPowerManager(HV_FALSE));
    }
    /*解决无信号立刻走待机流程，此时dp又识别的问题*/
    Hv_Vos_Timer_Rstop(pstChannelData->pstNoSignalTimer);
    s_stChannelManager.bSignalInterruption = HV_TRUE;
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_EnterBurnIn(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_EnterBurnIn");
    Hv_Drv_DpuScaler_SetMainChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_BURN_IN);

    VideoTimingParam    stVideoTiming = {0};
    const PanelManager* pstPanelManager = Hv_Mw_Panel_GetManagerPtr();
    PanelParam stPanelParam = pstPanelManager->stPanelParam;
    /*default settting display control using for burnin*/
    Hv_Mw_Video_GetFakeVideoConfigParams(&stVideoTiming, &(pstChannelData->stVideoConfigParams));
    Hv_Drv_DpuScaler_MainWindowConfig(&(pstChannelData->stVideoConfigParams));

    /*设置默认rxd clock*/
    UINT32 uiDClkCfg = 0;
    UINT64 uiDClockDst = (UINT64) stPanelParam.usPanelHtotalType * stPanelParam.usPanelVtotalType * stPanelParam.usPanelFrameRateType / 1000; 
    Hv_Drv_PLL_SetRxdpllPixelClock(CHANNEL_TYPE_MAIN,&uiDClkCfg, uiDClockDst);
    pstChannelData->stVideoConfigParams.uiRxDpllFreq = uiDClkCfg;
    
    if(NULL != pstPanelManager->stPanelControl.pfCalMNTuSize)
    {
        pstPanelManager->stPanelControl.pfCalMNTuSize(&pstChannelData->stVideoConfigParams, &(pstPanelManager->stPanelParam), (UINT32)uiDClockDst);
    }
    /*reconfig dpu*/
    HV_ASSERT_SUCCESS(Hv_Drv_DpuScaler_DpuClockConfig(&uiDClkCfg,uiDClockDst,&pstChannelData->stVideoConfigParams));    
    pstChannelData->stVideoConfigParams.uiDisplayPllFreq = uiDClkCfg;
    pstChannelData->stVideoConfigParams.uiDestDisplayPllFreq = uiDClockDst;
    /* 再次初始化mute，防止RX修改mute timing */
    pstChannelData->pfSetMuteTiming(&stVideoTiming,pstChannelData->stVideoConfigParams.uiRxDpllFreq, HV_TRUE);
    Hv_Drv_DpuScaler_InitFrcModeMain(HV_TRUE);

    HV_ASSERT_SUCCESS(pstChannelData->pfDpuScalerConfig(&pstChannelData->stVideoConfigParams));
    
    Hv_Drv_DpuScaler_BurnInConfig();
    /*start test pattern*/
    Hv_Mw_Channel_MuteOff(pstChannelData->enChannelType);
    pstChannelData->ucBurnInPattern = 0;
    Hv_Mw_PQ_SetInpPatt(HV_TRUE, 0);

#if (HV_PROJECT_CONFIG_FULL_LOCALDIMMING == HV_CONFIG_ON)
    Hv_Drv_DpuScaler_Enable_Vsync_Interrupt();
#endif

    Hv_Mw_Led_SetLedMode(LED_BURN_IN);
    /*send burnin signal to osd*/
    HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_FACTORY_AGING_REFRESH));

    Hv_Vos_Timer_Rstart(pstChannelData->pstBurnInPeriodCheckTimer,0);
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_BurnInPeriodCheck(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_BurnInPeriodCheck");
#if (HV_PROJECT_CONFIG_TCON_POWER_CONTROL == HV_CONFIG_ON)
    const PanelManager* pstPanelManager = Hv_Mw_Panel_GetManagerPtr();
    if((CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    && (HV_TRUE == Hv_Mw_Panel_GetTimingChangeFlag()))
    {
        if (PANEL_STATE_OFF == pstPanelManager->enCurrentPanelState)
        {
            HV_LOG_DEBUG(CHANNEL, "channel burnin StartPanelPowerOnTimer");
            Hv_Mw_Panel_StartPanelPowerOnTimer();
            HV_ASSERT_TRUE(Hv_Vos_Timer_Start(pstChannelData->pstBurnInPeriodCheckTimer));
            return HV_CONTINUE;
        }
        else if(PANEL_STATE_BLK_ON != pstPanelManager->enCurrentPanelState)
        {
            HV_LOG_DEBUG(CHANNEL, "panel is not ready, channel still waite");
            HV_ASSERT_TRUE(Hv_Vos_Timer_Start(pstChannelData->pstBurnInPeriodCheckTimer));
            return HV_CONTINUE;
        }
        Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_ENABLE);
    }
#endif
    /*端口状态*/
    if ((0 != Hv_Mw_Channel_GetChannelOnDisplay()) || (HV_SUCCESS == Hw_Mw_Channel_NoSignal_SearchPort(pstChannelData)))
    {
        /*sub通道在显示或者检测到非sub在用的信号，老化结束返回search状态*/
        Hv_Mw_PQ_SetInpPatt(HV_FALSE, (pstChannelData->ucBurnInPattern % 8));
        HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_FACTORY_AGING_EXIT));
        Hv_Mw_Led_SetLedMode(LED_BURN_OUT);
        return HV_FAILURE;
    }
    else
    {
        /*继续老化切换pattern*/
        Hv_Drv_DpuScaler_VideoUnmute(CHANNEL_TYPE_MAIN);
        pstChannelData->ucBurnInPattern++;
        if (1 == HV_COMMON_DATABASE_GET(SystemData, bBurnInEnable))
        {
            Hv_Mw_PQ_SetInpPatt(HV_TRUE, (pstChannelData->ucBurnInPattern % 8));
            HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_FACTORY_AGING_REFRESH));
        }
        else
        {
            /*关闭老化OSD界面*/
            HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_HIDE_ALL));
        }
    }
    Hv_Vos_Timer_Rstart(pstChannelData->pstBurnInPeriodCheckTimer,0);
    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        Hv_Vos_Timer_Rstart(pstChannelData->pstAvWatchdogTimer,0);
    }

    /*继续处于老化状态，不改变状态机状态*/
    return HV_CONTINUE;
}

static Status Hv_Mw_Channel_AvWatchDogTimeout(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    if(CHANNEL_STATE_ACTIVE == pstChannelData->enCurrentCHState)
    {
        if (Hv_Drv_Ktx_GetTxPhyAfifoFlag() == 1)
        {            
            Hv_Drv_Ktx_PifRst(0);
            Hv_Drv_Ktx_TxMacRst(0);
            Hv_Vos_Delayus(20);
            Hv_Drv_Ktx_PifRst(1);
            Hv_Drv_Ktx_TxMacRst(1);
            Hv_Vos_Delayus(20);
            Hv_Drv_Ktx_PifStart(0);
            Hv_Vos_Delayus(20);
            Hv_Drv_Ktx_PifStart(1);
            Hv_Drv_Ktx_TxPhyAfifoFlagClear();
            Hv_Vos_Delayus(20000);
            if (Hv_Drv_Ktx_GetTxPhyAfifoFlag() == 1)
            {
                HV_LOG_ERROR(CHANNEL, "Av Watchdog detetc txphy afifo abnormal,reboot!");
                hv_chip_Reset();
            }
        }

        if (0 == Hv_Drv_PLL_CheckRxDpllLock(0))
        {
            HV_LOG_ERROR(CHANNEL, "Av Watchdog detetc RxDpll0 abnormal,reboot!");
            hv_chip_Reset();
        }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        if (PXP_MODE_CLOSE != Hv_Mw_Channel_GetPxpMode())
        {
            if (0 == Hv_Drv_PLL_CheckRxDpllLock(1))
            {
                HV_LOG_ERROR(CHANNEL, "Av Watchdog detetc RxDpll1 abnormal,reboot!");
                hv_chip_Reset();
            }
        }
#endif
        if (0 == Hv_Drv_PLL_CheckPtcdPllLock())
        {
            HV_LOG_ERROR(CHANNEL, "Av Watchdog detetc PtcdPll abnormal,reboot!");
            hv_chip_Reset();
        }
        if (0 == Hv_Drv_PLL_CheckSysPllLock())
        {
            HV_LOG_ERROR(CHANNEL, "Av Watchdog detetc SysPll abnormal,reboot!");
            hv_chip_Reset();
        }
        if (0 == Hv_Drv_PLL_CheckTxdPllLock())
        {
            Hv_Drv_PLL_ResetTxdPll();
            Hv_Vos_Delayus(20000);
            if (0 == Hv_Drv_PLL_CheckTxdPllLock())
            {
                HV_LOG_ERROR(CHANNEL, "Av Watchdog detetc TxDpll abnormal,reboot!");
                hv_chip_Reset();
            }
        }
        if (0 == Hv_Drv_PLL_CheckFNPllLock())
        {
            HV_LOG_ERROR(CHANNEL, "Av Watchdog detetc FnPll abnormal,reboot!");
            hv_chip_Reset();
        }
    }
    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        Hv_Vos_Timer_Rstart(pstChannelData->pstAvWatchdogTimer,0);
    }
    return HV_CONTINUE;
}

#ifdef HV_SCALER_DEBUG_VERSION
const char* sColorFormatType[] =
{
    "ColorFormatType_RGB",
    "ColorFormatType_YCbCr422",
    "ColorFormatType_YCbCr444",
    "ColorFormatType_YCbCr420",
};

const char* sColorDepthType[] =
{
    "null",
    "null",
    "null",
    "ColorDepthType_6Bit",
    "ColorDepthType_8Bit",
    "ColorDepthType_10Bit",
    "ColorDepthType_12Bit",
    "ColorDepthType_16Bit",
};

VOID PrintVdeTimingParam(const VideoTimingParam* pstVideoTiming, const VideoColorParam* pstColor)
{
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usHTotal=%u", pstVideoTiming->usHTotal);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usHFProch=%u", pstVideoTiming->usHFProch);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usHSyncW=%u", pstVideoTiming->usHSyncW);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usHBProch=%u", pstVideoTiming->usHBProch);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usHActive=%u", pstVideoTiming->usHActive);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usHPol=%u", pstVideoTiming->usHPol);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usVTotal=%u", pstVideoTiming->usVTotal);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usVFProch=%u", pstVideoTiming->usVFProch);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usVSyncW=%u", pstVideoTiming->usVSyncW);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usVBProch=%u", pstVideoTiming->usVBProch);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usVActive=%u", pstVideoTiming->usVActive);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usVPol=%u", pstVideoTiming->usVPol);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.usFrameRate=%u", pstVideoTiming->usFrameRate);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.uwFreqKHz=%u", pstVideoTiming->uiFreqKHz);
    HV_LOG_DEBUG(CHANNEL, "VideoTimingParam.uwRxDpllSetFreqKHz=%u",pstVideoTiming->uiRxDpllSetFreqKHz);

    if (pstColor->eClrFormat < ARRAY_SIZE(sColorFormatType))
    {
        HV_LOG_DEBUG(CHANNEL, "VideoColorParam.eClrFormat=%s", sColorFormatType[pstColor->eClrFormat]);
    }

    if (pstColor->eClrDepth < ARRAY_SIZE(sColorDepthType))
    {
        HV_LOG_DEBUG(CHANNEL, "VideoColorParam.eClrFormat=%s", sColorDepthType[pstColor->eClrDepth]);
    }
    return;
}
#endif

static VOID ClearLastChannelConfig(ChannelData* pstChannelData)
{
    /*每次第一次进入config态清空历史保存的timng,和preConfig配置*/
    HV_MEMSET(&pstChannelData->stRxVideoTiming, 0, sizeof(pstChannelData->stRxVideoTiming));
    HV_MEMSET(&pstChannelData->stVideoConfigParams, 0, sizeof(pstChannelData->stVideoConfigParams));

    pstChannelData->usAVStableCheckTimes = 0;
    pstChannelData->bNoSignalLongTimes = HV_FALSE;
    return;
}

BOOL Hv_Mw_Channel_IsAudioOnThisChannel(ChannelType enChannelType)
{
    if (CHANNEL_TYPE_MAIN == enChannelType)
    {
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        if (PXP_MODE_CLOSE == Hv_Mw_Channel_GetPxpMode())
        {
            return HV_TRUE;
        }
        else
#endif
        {
            if (CHANNEL_TYPE_MAIN == HV_COMMON_DATABASE_GET(UserData, ucAudioSource))
            {
                return HV_TRUE;
            }
            else
            {
                return HV_FALSE;
            }
        }
    }
    else
    {

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        if (PXP_MODE_CLOSE == Hv_Mw_Channel_GetPxpMode())
        {
            return HV_FALSE;
        }
        else
#endif
        {
            if (CHANNEL_TYPE_SUB == HV_COMMON_DATABASE_GET(UserData, ucAudioSource))
            {
                return HV_TRUE;
            }
            else
            {
                return HV_FALSE;
            }
        }
    }
    return HV_FALSE;
}

LinkPortIndex Hv_Mw_Channel_GetAudioSelInputPortIndex()
{
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_PXP) 
    if(Hv_Mw_Channel_IsAudioOnThisChannel(CHANNEL_TYPE_SUB))
    {
        return (s_stChannelManager.astChannelData)[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex;
    }
    else
#endif
    {
        return (s_stChannelManager.astChannelData)[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex;
    }
}

static VOID AudioSourceConfig(const ChannelData* pstChannelData)
{
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if (PXP_MODE_CLOSE == Hv_Mw_Channel_GetPxpMode())
    {
        Hw_Mw_AudioPath_Mux(pstChannelData,CHANNEL_TYPE_MAIN);
        HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Audio_SelectSound(pstChannelData->enChannelSrcLinkPortIndex, pstChannelData->enChannelType));
#ifdef CONFIG_USER_DP_AUDIO_RESHAPE_ON
        if (((LINK_PORT_INDEX_DP_RX0 == pstChannelData->enChannelSrcLinkPortIndex)
            || (LINK_PORT_INDEX_DP_RX1 == pstChannelData->enChannelSrcLinkPortIndex))
           && ((pstChannelData->stRxVideoTiming.usHActive <= 800)
            && (pstChannelData->stRxVideoTiming.usVActive <= 600)))
        {
            Hv_Mw_Audio_SetDelayTime(50);
        }
        else
        {
            Hv_Mw_Audio_SetDelayTime(0);
        }
#endif
    }
    else/*当PIP或PBP场景时配置根据用户配置是主还是辅来确定*/
#endif
    {
        if ((CHANNEL_TYPE_MAIN == HV_COMMON_DATABASE_GET(UserData, ucAudioSource)))
        {
            if(CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
            {
                Hw_Mw_AudioPath_Mux(pstChannelData,CHANNEL_TYPE_MAIN);
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Audio_SelectSound(pstChannelData->enChannelSrcLinkPortIndex, CHANNEL_TYPE_MAIN));
#ifdef CONFIG_USER_DP_AUDIO_RESHAPE_ON
                if (((LINK_PORT_INDEX_DP_RX0 == pstChannelData->enChannelSrcLinkPortIndex)
                    || (LINK_PORT_INDEX_DP_RX1 == pstChannelData->enChannelSrcLinkPortIndex))
                   && ((pstChannelData->stRxVideoTiming.usHActive <= 800)
                    && (pstChannelData->stRxVideoTiming.usVActive <= 600)))
                {
                    Hv_Mw_Audio_SetDelayTime(50);
                }
                else
                {
                    Hv_Mw_Audio_SetDelayTime(0);
                }
#endif
            }
            else
            {
                Hw_Mw_AudioPath_Mux(&s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN],CHANNEL_TYPE_MAIN);
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Audio_SelectSound(s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex, CHANNEL_TYPE_MAIN));
#ifdef CONFIG_USER_DP_AUDIO_RESHAPE_ON
                if (((LINK_PORT_INDEX_DP_RX0 == s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex)
                    || (LINK_PORT_INDEX_DP_RX1 == s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex))
                   && ((s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].stRxVideoTiming.usHActive <= 800)
                    && (s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].stRxVideoTiming.usVActive <= 600)))
                {
                    Hv_Mw_Audio_SetDelayTime(50);
                }
                else
                {
                    Hv_Mw_Audio_SetDelayTime(0);
                }
#endif
            }
        }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        else if ((CHANNEL_TYPE_SUB == HV_COMMON_DATABASE_GET(UserData, ucAudioSource)))
        {
            if(CHANNEL_TYPE_SUB == pstChannelData->enChannelType)
            {
                Hw_Mw_AudioPath_Mux(pstChannelData,CHANNEL_TYPE_SUB);
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Audio_SelectSound(pstChannelData->enChannelSrcLinkPortIndex, CHANNEL_TYPE_SUB));
#ifdef CONFIG_USER_DP_AUDIO_RESHAPE_ON
                if (((LINK_PORT_INDEX_DP_RX0 == pstChannelData->enChannelSrcLinkPortIndex)
                    || (LINK_PORT_INDEX_DP_RX1 == pstChannelData->enChannelSrcLinkPortIndex))
                   && ((pstChannelData->stRxVideoTiming.usHActive <= 800)
                    && (pstChannelData->stRxVideoTiming.usVActive <= 600)))
                {
                    Hv_Mw_Audio_SetDelayTime(50);
                }
                else
                {
                    Hv_Mw_Audio_SetDelayTime(0);
                }
#endif
            }
            else
            {
                Hw_Mw_AudioPath_Mux(&s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB],CHANNEL_TYPE_SUB);
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Audio_SelectSound(s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex, CHANNEL_TYPE_SUB));
#ifdef CONFIG_USER_DP_AUDIO_RESHAPE_ON
                if (((LINK_PORT_INDEX_DP_RX0 == s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex)
                    || (LINK_PORT_INDEX_DP_RX1 == s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex))
                   && ((s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stRxVideoTiming.usHActive <= 800)
                    && (s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stRxVideoTiming.usVActive <= 600)))
                {
                    Hv_Mw_Audio_SetDelayTime(50);
                }
                else
                {
                    Hv_Mw_Audio_SetDelayTime(0);
                }
#endif
            }
        }
#endif
        else
        {
            /*do nothing*/
        }
    }

    return;
}

Status Hv_Mw_Channel_AudioSourceConfig(ChannelType enChannelType)
{
    HV_COMMON_DATABASE_SET(UserData, ucAudioSource, enChannelType);

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    HV_ASSERT_TRUE(enChannelType <= CHANNEL_TYPE_SUB);
#else
    HV_ASSERT_TRUE(enChannelType == CHANNEL_TYPE_MAIN);
#endif
    LinkPortIndex enChannelSrcLinkPortIndex = LINK_PORT_INDEX_INVALID;
    ChannelState enChannelState = CHANNEL_STATE_IDLE;
    if (CHANNEL_TYPE_MAIN == enChannelType)
    {
        Hv_Vos_Timer_Rstop(s_stChannelManager.astChannelData[enChannelType].pstAvWatchdogTimer);
    }
    HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Audio_ChannelMute(_AUDIO_MUTE_BIT_HW));

    enChannelSrcLinkPortIndex = s_stChannelManager.astChannelData[enChannelType].enChannelSrcLinkPortIndex;
    enChannelState = s_stChannelManager.astChannelData[enChannelType].enCurrentCHState;
    AudioSourceConfig(&s_stChannelManager.astChannelData[enChannelType]);

    if (CHANNEL_STATE_ACTIVE == enChannelState)
    {
        /*开启audio水位及中断*/
        const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
        pstInputPortManager->pfStartAudio(enChannelSrcLinkPortIndex);
        pstInputPortManager->pfCheckAudio(enChannelSrcLinkPortIndex);
        if (s_stChannelManager.astChannelData[enChannelType].enChannelSrcLinkPortIndex == LINK_PORT_INDEX_DP_RX0 ||
            s_stChannelManager.astChannelData[enChannelType].enChannelSrcLinkPortIndex == LINK_PORT_INDEX_DP_RX1)
        {
            if (pstInputPortManager->pfGetAudioStatus(s_stChannelManager.astChannelData[enChannelType].enChannelSrcLinkPortIndex) == HV_TRUE)
            {
                Hv_Mw_Audio_ChannelUnMute(_AUDIO_MUTE_BIT_HW | _AUDIO_MUTE_BIT_FS);
            }
        }
        else
        {
            // hdmi先判断CTS/N再决定声音是否解mute
            UINT32 uiCts, uiN;
            Hv_Mw_HdmiRx_GetAudioCurrentCTSN(s_stChannelManager.astChannelData[enChannelType].enChannelSrcLinkPortIndex, &uiCts, &uiN);
            if (uiCts != 0 && uiN != 0)
            {
                Hv_Mw_Audio_ChannelUnMute(_AUDIO_MUTE_BIT_HW | _AUDIO_MUTE_BIT_FS);
            }
        }
    }
    HV_LOG_INFO(CHANNEL, "Audio source switch to channel %u",enChannelType);
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_Config(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "OnFirstEnterState Hv_Mw_Channel_Config channelType=%u", pstChannelData->enChannelType);
    UCHAR8 ucAudioSource = 0;
#if (HV_PROJECT_CONFIG_TCON_POWER_CONTROL == HV_CONFIG_ON)
    if((CHANNEL_TYPE_MAIN == pstChannelData->enChannelType) && (HV_TRUE == Hv_Mw_Panel_GetTimingChangeFlag()))
    {
        SendBacklightOffToPanel();
    }
#endif
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if (CHANNEL_TYPE_SUB == pstChannelEvent->enChannelType)
    {
        Hv_Drv_DpuScaler_SetSubChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_CONFIG);
    }
#endif
    if (CHANNEL_TYPE_MAIN == pstChannelEvent->enChannelType)
    {
        Hv_Drv_DpuScaler_SetMainChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_CONFIG);
    }
    /*清除channel历史配置,停止audio/video mute timer*/
    ClearLastChannelConfig(pstChannelData);
    Hv_Vos_Timer_Rstop(pstChannelData->pstAudioMuteTimer);
    Hv_Vos_Timer_Rstop(pstChannelData->pstVideoMuteTimer);

    pstChannelData->pfMuteForceFreeRun(HV_TRUE);
    
    /*从RX获取timing，color，hdr，vrr配置*/
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    HV_ASSERT_SUCCESS(pstInputPortManager->pfGetVideoPara(pstChannelData->enChannelSrcLinkPortIndex,pstChannelData));
#ifdef HV_SCALER_DEBUG_VERSION
    /*打印从RX获取到的关键参数*/
    PrintVdeTimingParam(&pstChannelData->stRxVideoTiming, &pstChannelData->stVideoConfigParams.stColor);
#endif
    /*配置Video通路*/
    HV_ASSERT_SUCCESS(Hv_Mw_Video_ConfigDisplayDataPath(pstChannelData, &pstChannelData->stVideoConfigParams, &pstChannelData->stRxVideoTiming));
    pstChannelData->pfMuteForceFreeRun(HV_FALSE);

    /*配置audio的音源*/
    if (((HV_TRUE == s_stChannelManager.stChannelFlashConfig.bFlashSubFakeVideoSw)
     && (0 != Hv_Mw_Channel_GetChannelOnDisplay()))                                          /*放大镜是同源，不需要重复配一遍audio，否则audio会mute一下*/
     || ((PXP_MODE_CLOSE != s_stChannelManager.stChannelFlashConfig.enFlashPxPMode)
     && (0 != Hv_Mw_Channel_GetChannelOnDisplay())
     && (HV_FALSE == Hv_Mw_Channel_IsAudioOnThisChannel(pstChannelData->enChannelType))))   /*PXP非同源且audio不是当前通道，不需要配置当前通道audio，否则另一个audio会mute一下*/
    {
        HV_LOG_DEBUG(CHANNEL, "one channel on display not config audio, channelType=%u", pstChannelData->enChannelType);
    }
    else
    {
        AudioSourceConfig(pstChannelData);
        /*开启audio水位及中断*/
        ucAudioSource = HV_COMMON_DATABASE_GET(UserData, ucAudioSource);
        HV_ASSERT_TRUE(ucAudioSource < 2);
        if(pstChannelData->enChannelType == ucAudioSource)
        {
            pstInputPortManager->pfStartAudio(pstChannelData->enChannelSrcLinkPortIndex);
        }
        else
        {
            pstInputPortManager->pfStartAudio(s_stChannelManager.astChannelData[ucAudioSource].enChannelSrcLinkPortIndex);
        }
    }

    /* 配置AV Stable 检查 */
    pstChannelData->bAVStable = HV_FALSE;

    /*通知OSD重新配置通道画质参数*/
    pstChannelData->enChanelSignalState = ChanelSignalState_SignalSync;
    pstChannelData->enLastChannelSrcLinkPortIndex = pstChannelData->enChannelSrcLinkPortIndex;
    HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_SIGNAL_READY));
    Hv_Vos_Timer_Rstart(pstChannelData->pstAVcheckStableTimer, 100);

    return HV_CONTINUE;
}

static Status CheckAVStatus(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    static UINT32 uiMainCheckTimes = 0;
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    static UINT32 uiSubCheckTimes = 0;
#endif
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    UINT32 uiMuteStatus = pstInputPortManager->pfGetMuteStatus(pstChannelData->enChannelType);
    UINT32 uiDtcStatus = Hv_Drv_DpuScaler_CheckDtcStable(&pstChannelData->stVideoConfigParams);
    if(CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        if(HV_DPU_MUTE_STATUS_NORMAL == uiMuteStatus)
        {
            Hv_Drv_DpuScaler_InitFrcModeMain(HV_TRUE);
            uiMainCheckTimes++;
            if(uiMainCheckTimes >= 2)/*mute 稳定两帧之后再进入framesync模式*/
            {
                if(HV_FALSE == uiDtcStatus)
                {
                    Hv_Drv_DpuScaler_Enter_FrameSync(&pstChannelData->stVideoConfigParams);
                    pstChannelData->bAVStable = HV_FALSE;
                }
                else
                {
                    pstChannelData->bAVStable = HV_TRUE;
                    uiMainCheckTimes = 0;
                }
            }
            else
            {
                pstChannelData->bAVStable = HV_FALSE;
            }
        }
        else
        {
            pstChannelData->bAVStable = HV_FALSE;
        }
        HV_LOG_DEBUG(CHANNEL, "Mute=%u,framsync %u, Dtc %u", uiMuteStatus, Hv_Drv_DpuScaler_GetFrmsyncState(), Hv_Drv_DpuScaler_GetDtcState());
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else
    {
        if(HV_DPU_MUTE_STATUS_NORMAL == uiMuteStatus)
        {
            Hv_Drv_DpuScaler_InitFrcModeSub(HV_TRUE);
            uiSubCheckTimes++;
            if (uiSubCheckTimes >=2)
            {
                pstChannelData->bAVStable = HV_TRUE;
                uiSubCheckTimes = 0;
            }
            else
            {
                pstChannelData->bAVStable = HV_FALSE;
            }
        }
        else
        {
            pstChannelData->bAVStable = HV_FALSE;
        }
        HV_LOG_DEBUG(CHANNEL, "Mute=%u", uiMuteStatus);
    }
#endif
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_ConfigCheck(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_ConfigCheck");
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
#if (HV_PROJECT_CONFIG_TCON_POWER_CONTROL == HV_CONFIG_ON)
    const PanelManager* pstPanelManager = Hv_Mw_Panel_GetManagerPtr();
    if((CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    && (HV_TRUE == Hv_Mw_Panel_GetTimingChangeFlag()))
    {
        if (PANEL_STATE_OFF == pstPanelManager->enCurrentPanelState)
        {
            HV_LOG_DEBUG(CHANNEL, "channel StartPanelPowerOnTimer");
            Hv_Mw_Panel_StartPanelPowerOnTimer();
            HV_ASSERT_TRUE(Hv_Vos_Timer_Start(pstChannelData->pstAVcheckStableTimer));
            return HV_CONTINUE;
        }
        else if(PANEL_STATE_BLK_ON != pstPanelManager->enCurrentPanelState)
        {
            HV_LOG_DEBUG(CHANNEL, "panel is not ready, channel still wait");
            HV_ASSERT_TRUE(Hv_Vos_Timer_Start(pstChannelData->pstAVcheckStableTimer));
            return HV_CONTINUE;
        }
    }
    if ((CHANNEL_TYPE_SUB == pstChannelData->enChannelType)
        && ((CHANNEL_STATE_CONFIG == s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enCurrentCHState) 
        || (CHANNEL_STATE_SEARCH == s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enCurrentCHState)))
    {
        HV_LOG_INFO(CHANNEL, "sub ok, wait main config");
        HV_ASSERT_TRUE(Hv_Vos_Timer_Start(pstChannelData->pstAVcheckStableTimer));
        return HV_CONTINUE;
    }
#endif
    Hv_Vos_Timer_Rstop(pstChannelData->pstAVcheckStableTimer);
    HV_ASSERT_SUCCESS(CheckAVStatus(pstChannelEvent, pstChannelData));
    pstChannelData->usAVStableCheckTimes++;
    if (pstChannelData->usAVStableCheckTimes > MAX_CHANNEL_CHECK_AV_STABLE_TIMES)
    {
        pstChannelData->usAVStableCheckTimes = 0;

        UINT32 uiMuteStatus = pstInputPortManager->pfGetMuteStatus(pstChannelData->enChannelType);
        if(HV_DPU_MUTE_STATUS_NORMAL != uiMuteStatus)
        {
            HV_LOG_WARN(CHANNEL, "Reach max config check times, reset rx! %u", pstChannelData->enChannelType);
            pstInputPortManager->pfReset(pstChannelData->enChannelSrcLinkPortIndex);
            return HV_FAILURE;
        }
        else
        {
            if (DIS_TIMING_MODE_FRAMESYNC == pstChannelData->stVideoConfigParams.enTimingMode)
            {
                Hv_Drv_DpuScaler_Enter_FrameSync(&pstChannelData->stVideoConfigParams);
            }
            pstChannelData->bAVStable = HV_TRUE;
            Hv_Vos_MSleep(100); /*wait dtc stable*/
        }
    }
    
    if (HV_TRUE == pstChannelData->bAVStable)
    {
        return HV_SUCCESS;
    }
    else
    {
        HV_ASSERT_TRUE(Hv_Vos_Timer_Start(pstChannelData->pstAVcheckStableTimer));
        return HV_CONTINUE;
    }
}

static Status Hv_Mw_Channel_ConfigAbnormalProc(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_ConfigAbnormalProc usEventId = %u, enChannelType=%u", pstChannelEvent->usEventId, pstChannelData->enChannelType);
    HV_ASSERT_VALID_PTR(pstChannelData->pstAVcheckStableTimer);
    if (CHANNEL_EVENT_ID_CONFIG_CHECK_AV_STABLE == pstChannelEvent->usEventId)
    {
        Hv_Vos_Timer_Rstop(pstChannelData->pstAVcheckStableTimer);
    }
    return HV_SUCCESS;
}

VOID Notify_ChannelManager_Reconfig(VOID)
{
    ChannelEvent stChannelEvent = {0};
    stChannelEvent.usEventId = CHANNEL_EVENT_ID_DATA_PATH_RECONFIG;
    stChannelEvent.usValue = 0;
    stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
    HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
    
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    /*PIP 或者PBP打开的case 发送sub通道重配置消息*/
    if (PXP_MODE_CLOSE != Hv_Mw_Channel_GetPxpMode())
    {
        stChannelEvent.usEventId = CHANNEL_EVENT_ID_DATA_PATH_RECONFIG;
        stChannelEvent.usValue = 0;
        stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
        HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
        HV_LOG_DEBUG(CHANNEL, "receive Sub Dpu datapath reconfig");
    }
    else
    {
        /*在PIB or PBP已关闭的case 固定发送一条关闭辅助通道的消息,对于sub通道来说即使多一条关闭消息也不会产生额外的问题,
        如果是之前开启了，resume userdata导致的重配，此case会关闭掉辅通道*/
        stChannelEvent.usEventId = CHANNEL_EVENT_ID_PXP_DISABLE;
        stChannelEvent.usValue = 0;
        stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
        HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
        HV_LOG_DEBUG(CHANNEL, "receive Sub Dpu datapath disable");
    }
#endif
    return;
}

static Status Hv_Mw_Channel_Active(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    const PanelParam stPanelParam = Hv_Mw_Panel_GetCurrentPanelParam();
    pstInputPortManager->pfClearPortLastUnSyncStatus(pstChannelData->enChannelSrcLinkPortIndex);
    Hv_Vos_Timer_Rstop(pstChannelData->pstAudioMuteTimer);
    Hv_Vos_Timer_Rstop(pstChannelData->pstVideoMuteTimer);
    pstChannelData->uiMuteStatus = 0;
    pstChannelData->uiEnterNoSignalCount = 0;
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if (CHANNEL_TYPE_SUB == pstChannelEvent->enChannelType)
    {
        Hv_Drv_DpuScaler_SetSubChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_ACTIVE);
    }
    if ((PXP_MODE_MAGNIFY_GLASS_ENABLE != Hv_Mw_Channel_GetPxpMode()) && (PXP_MODE_CLOSE != Hv_Mw_Channel_GetPxpMode()))
    {
        Hv_Drv_DpuScaler_LdgSubBorderEn(HV_TRUE); /*draw pxp border*/
    }
    if (PXP_MODE_CLOSE != pstChannelData->stVideoConfigParams.enPxpMode)
    {
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_PIP_POS_PRECISE_ADJ)
        if ((PXP_MODE_PIP_ENABLE == pstChannelData->stVideoConfigParams.enPxpMode) && (HV_FALSE == pstChannelData->stVideoConfigParams.bMainFakeSwitch))
        {
            Hv_Mw_Video_SetPipWindowHPosition(HV_COMMON_DATABASE_GET(UserData, usOsdPipHPosLevel));
        }
        else
        {
            Hv_Drv_DpuScaler_SubWindowConfig(stPanelParam.usPanelHactive, stPanelParam.usPanelVactive);
        }
#else
        Hv_Drv_DpuScaler_SubWindowConfig(stPanelParam.usPanelHactive, stPanelParam.usPanelVactive);
#endif
        Hv_Drv_DpuScaler_DtcSubWindowEn(HV_TRUE);
        if ((HV_FALSE == pstChannelData->stVideoConfigParams.bMainFakeSwitch)
            && (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType))
        {
            //Hv_Drv_DpuScaler_SubLdgTopSubBlendEn(HV_TRUE);/*PXP下无信号也要显示黑框*/
            Hv_Drv_DpuScaler_SetMainFakeBlendFlag(HV_TRUE);
        }
        if (CHANNEL_TYPE_SUB == pstChannelData->enChannelType)
        {
            //Hv_Vos_Delayus(100000);
            //Hv_Drv_DpuScaler_SubLdgTopSubBlendEn(HV_TRUE);
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DPU_BRIGHT_FRAME)
            if ((7 <= HV_COMMON_DATABASE_GET(UserData, ucOsdBfSizeLevel)) && (HV_TRUE == HV_COMMON_DATABASE_GET(UserData, bBrightFrameEn)))
            {
                Hv_Drv_DpuScaler_SetMainFakeBlendFlag(HV_FALSE);
            }
            else if (HV_TRUE == HV_COMMON_DATABASE_GET(UserData, bBrightFrameEn))
            {
                Hv_Drv_DpuScaler_SetMainFakeBlendFlag(HV_TRUE);
            }
#else
            Hv_Drv_DpuScaler_SetMainFakeBlendFlag(HV_TRUE);
#endif
        }
    }
#endif
    if(HV_FAILURE == Hv_Mw_Channel_MuteOff(pstChannelData->enChannelType))
    {
        HV_LOG_INFO(CHANNEL, "Channel %u mute off fail,change to search", pstChannelData->enChannelType);
        return HV_FAILURE;
    }
    /*给OSD发送消息通知图像已正常显示*/
    pstChannelData->enChanelSignalState = ChanelSignalState_SignalSync;
    pstChannelData->enLastChannelSrcLinkPortIndex = pstChannelData->enChannelSrcLinkPortIndex;
    HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_SIGNAL_STATE_CHANGE));
    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        Hv_Mw_PQ_SetInpPatt(HV_FALSE, 0);
        HV_COMMON_DATABASE_SET(UserData, ucVideoSource, pstChannelData->enChannelSrcLinkPortIndex);
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else
    {
        HV_COMMON_DATABASE_SET(UserData, ucPxPVideoSource, pstChannelData->enChannelSrcLinkPortIndex);
    }
#endif

    Hv_Drv_DpuPQ_DmaEnable(HV_FALSE);
    Hv_Drv_DpuScaler_Enable_Vsync_Interrupt();
    Hv_Mw_Mute_Interrupt_Enable(pstChannelData->enChannelType);
    Hv_Mw_Audio_Interrupt_Enable(Hv_Mw_Channel_GetAudioSelInputPortIndex());
    pstInputPortManager->pfPostProcess(pstChannelData->enChannelSrcLinkPortIndex);
    #if (HV_CONFIG_ON == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
    Hv_Cal_DpuScaler_SetSeamlessSwitchFlag(1);   //标志位
    Hv_Cal_DpuScaler_SetMainFrcOverWrite(1);     //提前写另一个buf

    Hv_Vos_Delayus(35000);                       //将脏数据buf覆盖
    Hv_Cal_DpuScaler_SetMainFrcOverWrite(0);     // 关闭over wirte
    Hv_Cal_DpuScaler_SetMianFrcIndexFwMode(0);   // 关闭软件模式

    #endif
    s_stChannelManager.bSignalInterruption = HV_FALSE;
#if defined(HV_PROJECT_CONFIG_KVM_FUNCTION) && (HV_PROJECT_CONFIG_KVM_FUNCTION ==HV_CONFIG_ON)
    if (LINK_PORT_INDEX_DP_RX0 == pstChannelData->enChannelSrcLinkPortIndex)
    {
        Hv_Comm_Platform_SetKvmPath(KVM_TYPEC);
    }
    else
    {
        Hv_Comm_Platform_SetKvmPath(KVM_USB_B);
    }
#endif
    HV_LOG_INFO(CHANNEL, "Channel %u show video, port:%u", pstChannelData->enChannelType, pstChannelData->enChannelSrcLinkPortIndex);

    pstChannelData->pfMuteClearEn();

    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        Hv_Drv_DpuScaler_SetMainChannelState((pstChannelData->enChannelSrcLinkPortIndex << 7) | CHANNEL_STATE_ACTIVE);
        Hv_Vos_Timer_Rstart(pstChannelData->pstAvWatchdogTimer,0);
    }
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_ColorChange(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "channel Hv_Mw_Channel_ColorChange enChannelType=%u usPortIndex=%u", pstChannelEvent->enChannelType, pstChannelEvent->usValue);
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    if ((pstChannelEvent->enChannelType == pstChannelData->enChannelType)
     && (pstChannelEvent->usValue == pstChannelData->enChannelSrcLinkPortIndex))
    {
        HV_LOG_INFO(CHANNEL, "Channel ColorChange port %u success",pstChannelData->enChannelSrcLinkPortIndex);
        pstInputPortManager->pfClearPortLastUnSyncStatus(pstChannelData->enChannelSrcLinkPortIndex);
        return HV_SUCCESS;
    }
    else
    {
        /*不是期望的消息，不做任何处理*/
        HV_LOG_INFO(CHANNEL, "Channel ColorChange port %u,discard",pstChannelData->enChannelSrcLinkPortIndex);
        return HV_CONTINUE;
    }
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_TimingChange(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_TimingChange enChannelType=%u usPortIndex=%u", pstChannelEvent->enChannelType, pstChannelEvent->usValue);
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    if ((pstChannelEvent->enChannelType == pstChannelData->enChannelType)
        && (pstChannelEvent->usValue == pstChannelData->enChannelSrcLinkPortIndex))
    {

        HV_LOG_INFO(CHANNEL, "Channel timingchange port %u success",pstChannelData->enChannelSrcLinkPortIndex);
        pstInputPortManager->pfClearPortLastUnSyncStatus(pstChannelData->enChannelSrcLinkPortIndex);
        return HV_SUCCESS;
    }
    else
    {
        /*不是期望的消息，不做任何处理*/
        HV_LOG_INFO(CHANNEL, "Channel timingchange port %u,discard",pstChannelData->enChannelSrcLinkPortIndex);
        return HV_CONTINUE;
    }
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_SignalLoss(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "channel %u SignalLoss usPortIndex=%u", pstChannelEvent->enChannelType, pstChannelEvent->usValue);
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    pstChannelData->uiEnterNoSignalCount = 0;
    if ((pstChannelEvent->enChannelType == pstChannelData->enChannelType)
     && (pstChannelEvent->usValue == pstChannelData->enChannelSrcLinkPortIndex))
    {
        /*loss模式清空绑定端口，进入search态重新选择端口*/
        HV_LOG_INFO(CHANNEL, "port %u SignalLoss",pstChannelData->enChannelSrcLinkPortIndex);
        pstChannelData->enLastChannelSrcLinkPortIndex = pstChannelData->enChannelSrcLinkPortIndex;
        if(HV_FALSE == Hv_Mw_InputPort_GetCableStatus(pstChannelData->enChannelSrcLinkPortIndex))
        {
            /*freerun状态下配置，保持稳定*/
            pstChannelData->pfMuteForceFreeRun(HV_TRUE);
            if (CHANNEL_TYPE_MAIN == pstChannelEvent->enChannelType)
            {
                /*退出framesync模式，重新加载时钟，保持稳定*/
                Hv_Drv_PLL_PtcdReload();
                Hv_Drv_DpuScaler_Exit_FrameSync();
                Hv_Drv_PLL_TogglePtcdUpdate();
            }
            HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData ,OSD_EVENT_SIGNAL_PLUG_OUT));
#ifdef CONFIG_USER_TYPE_C_ON
            //HV_LOG_INFO(CHANNEL, "SignalLoss, call SendSignalLossToTypec %d !!", pstChannelData->enLastChannelSrcLinkPortIndex);
            SendSignalLossToTypec(pstChannelData->enLastChannelSrcLinkPortIndex);
#endif
        }
        
        pstInputPortManager->pfClearPortLastUnSyncStatus(pstChannelData->enChannelSrcLinkPortIndex);
        return HV_SUCCESS;
    }
    else
    {
        HV_LOG_INFO(CHANNEL, "port %u SignalLoss,discard",pstChannelData->enChannelSrcLinkPortIndex);
#ifdef CONFIG_USER_TYPE_C_ON
        SendSignalLossToTypec(pstChannelData->enLastChannelSrcLinkPortIndex);
#endif
        /*不是期望的消息，不做任何处理*/
        return HV_CONTINUE;
    }

    return HV_SUCCESS;
}

static VOID SetManagerData(const ChannelFlashConfig* pstChannelFlashConfig)
{
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    s_stChannelManager.stChannelFlashConfig.bFlashSubFakeVideoSw = pstChannelFlashConfig->bFlashSubFakeVideoSw;
    s_stChannelManager.stChannelFlashConfig.enFlashPxPMode = pstChannelFlashConfig->enFlashPxPMode;
    
    s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].stVideoConfigParams.bMainFakeSwitch = pstChannelFlashConfig->bFlashSubFakeVideoSw;
    s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].stVideoConfigParams.enPxpMode = pstChannelFlashConfig->enFlashPxPMode;
    s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams.bMainFakeSwitch = pstChannelFlashConfig->bFlashSubFakeVideoSw;
    s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams.enPxpMode = pstChannelFlashConfig->enFlashPxPMode;
#endif
    return;
}

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
static Status Hv_Mw_Channel_PxpEnable(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "rev PXP enable Command channelType=%u !!!", pstChannelData->enChannelType);

    Hv_Drv_DpuScaler_SetSubPathClkEn(1);
    Hv_Mw_Channel_MuteOn(CHANNEL_TYPE_MAIN);

    ChannelFlashConfig stChannelFlashConfig;
    stChannelFlashConfig.enFlashPxPMode =  pstChannelEvent->usValue;
    stChannelFlashConfig.bFlashSubFakeVideoSw = HV_FALSE;
    SetManagerData(&stChannelFlashConfig);
    pstChannelData->uiEnterNoSignalCount = 0;

    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        if(HV_SUCCESS != Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex))
        {
            Hv_Mw_Channel_MuteOff(pstChannelData->enChannelType);
            HV_LOG_ERROR(CHANNEL, "pxp enable Update EDID fail!");
        }
    }
    else
    {
        pstChannelData->enChannelSrcLinkPortIndex = HV_COMMON_DATABASE_GET(UserData, ucPxPVideoSource);
        if ((PXP_MODE_PIP_ENABLE == stChannelFlashConfig.enFlashPxPMode)
            && (pstChannelData->enChannelSrcLinkPortIndex == s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex))
        {
            HV_LOG_INFO(CHANNEL, "PIP mode, sub and main soure same, %u ", pstChannelData->enChannelSrcLinkPortIndex);
        }
        else
        {
            Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex);
        }
    }

    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_PxpDisable(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "rev PXP disable Command channelType=%u !!!", pstChannelData->enChannelType);
    Hv_Drv_DpuScaler_SetSubPathClkEn(0);
    Hv_Mw_Channel_MuteOn(CHANNEL_TYPE_MAIN);
    
    ChannelFlashConfig  stChannelFlashConfig;
    stChannelFlashConfig.enFlashPxPMode =  pstChannelEvent->usValue;
    stChannelFlashConfig.bFlashSubFakeVideoSw = HV_FALSE;
    SetManagerData(&stChannelFlashConfig);
    pstChannelData->uiEnterNoSignalCount = 0;

    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        if(HV_SUCCESS != Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex))
        {
            Hv_Mw_Channel_MuteOff(pstChannelData->enChannelType);
            HV_LOG_ERROR(CHANNEL, "#pxp disable Update EDID fail!");
        }
        return HV_SUCCESS;
    }
    else
    {
        Hv_Drv_DpuScaler_SubChannelClose();
        //Hv_Drv_DpuScaler_DtcSubWindowEn(HV_FALSE);
        Hv_Drv_DpuScaler_SubLdgTopSubBlendEn(HV_FALSE);
        Hv_Drv_DpuScaler_LdgSubBorderEn(HV_FALSE);
        return HV_FAILURE;
    }    
}
#endif

#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY)
static Status Hv_Mw_Channel_ManifyDisable(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "rev Manify disable Command usValue=%u channelType=%u !!!", pstChannelEvent->usValue, pstChannelData->enChannelType);
    Hv_Drv_DpuScaler_SetSubPathClkEn(0);
    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DPU_BRIGHT_FRAME)
        ChannelFlashConfig stChannelFlashConfig;
        stChannelFlashConfig.bFlashSubFakeVideoSw = pstChannelEvent->usValue;
        stChannelFlashConfig.enFlashPxPMode = PXP_MODE_CLOSE;
        pstChannelData->enChannelSrcLinkPortIndex = HV_COMMON_DATABASE_GET(UserData, ucPxPVideoSource);
        SetManagerData(&stChannelFlashConfig);
        return HV_SUCCESS;
#else
        return HV_FAILURE;
#endif
    }
    else
    {
        Hv_Drv_DpuScaler_SubLdgTopSubBlendEn(HV_FALSE);
        Hv_Vos_Delayus(20000);
        //Hv_Drv_DpuScaler_DtcSubWindowEn(HV_FALSE);
        Hv_Drv_DpuScaler_SubChannelClose();

        ChannelFlashConfig stChannelFlashConfig;
        stChannelFlashConfig.bFlashSubFakeVideoSw = pstChannelEvent->usValue;
        stChannelFlashConfig.enFlashPxPMode = PXP_MODE_CLOSE;
        pstChannelData->enChannelSrcLinkPortIndex = HV_COMMON_DATABASE_GET(UserData, ucPxPVideoSource);
        SetManagerData(&stChannelFlashConfig);
        return HV_FAILURE;  
    }
}

static Status Hv_Mw_Channel_MagnifyEnable(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "rev Manify enable Command channelType=%u !!!", pstChannelData->enChannelType);
    Hv_Drv_DpuScaler_SetSubPathClkEn(1);
    ChannelFlashConfig stChannelFlashConfig;
    stChannelFlashConfig.bFlashSubFakeVideoSw = (pstChannelEvent->usValue == 0) ? HV_FALSE : HV_TRUE;
    stChannelFlashConfig.enFlashPxPMode = PXP_MODE_PIP_ENABLE;
    const PanelParam stPanelParam = Hv_Mw_Panel_GetCurrentPanelParam();
    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DPU_BRIGHT_FRAME)
        if (HV_COMMON_DATABASE_GET(UserData, bBrightFrameEn))
        {
            SetManagerData(&stChannelFlashConfig);
            return HV_SUCCESS;
        }
#endif
        if (EDID_TYPE_PBP == Hv_Mw_InputPort_GetCurrentEdidType(pstChannelData->enChannelSrcLinkPortIndex))
        {
            SetManagerData(&stChannelFlashConfig);
            Hv_Mw_Channel_MuteOn(CHANNEL_TYPE_MAIN);
            if(HV_SUCCESS != Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex))
            {
                Hv_Mw_Channel_MuteOff(pstChannelData->enChannelType);
                HV_LOG_ERROR(CHANNEL, "#Manify enable Update EDID fail!");
            }
            return HV_SUCCESS;
        }
        else if (PXP_MODE_PIP_ENABLE == s_stChannelManager.stChannelFlashConfig.enFlashPxPMode)
        {
            SetManagerData(&stChannelFlashConfig);
            return HV_SUCCESS;      /*PIP切到放大镜重配main通路，解决sharpness开关引起的DTC问题*/
        }
        else
        {
            SetManagerData(&stChannelFlashConfig);
            return HV_FAILURE;      /*直接打开放大镜，不需要重配main通路*/
        }
    }
    else
    {
        /*放大镜模式，将主端口号赋给副,防止sub没有在search阶段没有搜索到，可以在no signal状态继续搜索*/
        pstChannelData->enChannelSrcLinkPortIndex = s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex;
        //Hv_Drv_DpuScaler_SubWindowConfig(stPanelParam.usPanelHactive, stPanelParam.usPanelVactive);
        //Hv_Drv_DpuScaler_DtcSubWindowEn(HV_TRUE);
    }

    return HV_SUCCESS;
}
#endif

static Status Hv_Mw_Channel_FreeSyncSwitch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "rev Hv_Mw_Channel_FreeSyncSwitch enChannelType=%u!!!", pstChannelData->enChannelType);

    if(HV_SUCCESS != Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex))
    {
        HV_LOG_ERROR(CHANNEL, "#freesync Update fail!");
        return HV_FAILURE;
    }
    else
    {
        /*解决rx拉hpd会延迟几百ms导致花屏问题，不能用mute去遮，否则mute会导致进search，几百ms后rx拉hpd也会导致进search*/
        Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_DISABLE);
    }
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_VRRChanged(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    /*从RX获取timing，color，hdr，vrr配置*/
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    HV_ASSERT_SUCCESS(pstInputPortManager->pfGetVideoPara(pstChannelData->enChannelSrcLinkPortIndex,pstChannelData));
    HV_ASSERT_PEEK_SUCCESS(SendSignalStateToOsd(pstChannelData, OSD_EVENT_SIGNAL_PARAM_CHANGE));
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_HdrSwitch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "rev Hv_Mw_Channel_HdrSwitch enChannelType=%u!!!", pstChannelData->enChannelType);
    if ((CHANNEL_STATE_ACTIVE == pstChannelData->enCurrentCHState)
    && (HV_SUCCESS == Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex)))
    {
        /*更新EDID后等待HPD触发search*/
        Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_DISABLE);
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

static Status Hv_Mw_Channel_ProEsportSwitch(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "rev Hv_Mw_Channel_ProEsportSwitch enChannelType=%u!!!", pstChannelData->enChannelType);
    if ((CHANNEL_STATE_ACTIVE == pstChannelData->enCurrentCHState)
    && (HV_SUCCESS == Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex)))
    {
        /*更新EDID后等待HPD触发search*/
        Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_DISABLE);
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}


static Status Hv_Mw_Channel_HdrChanged(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    UCHAR8 ucUpdate = 0;
    HDRParam* pstHdrParam = &pstChannelData->stVideoConfigParams.stHdrParam;
    ucUpdate =  pstHdrParam->xType;
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    HV_ASSERT_SUCCESS(pstInputPortManager->pfGetVideoPara(pstChannelData->enChannelSrcLinkPortIndex,pstChannelData));
    
    if(ucUpdate == pstHdrParam->xType)/*hdr same, do not tell OSD*/
    {
        Hv_Drv_DpuScaler_MainHdrProcessSOP(pstHdrParam);
        return HV_FAILURE;
    }
    else
    {
        return HV_SUCCESS;
        /* 菜单关闭HDR，不设置HDR模式和发送OSD事件 */
        if(Hv_Mw_PQ_GetHDREnable(0) != 0)
        {
            if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
            {
                Hv_Drv_DpuScaler_MainHdrProcessSOP(pstHdrParam);
            }
    #ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
            else
            {
                Hv_Drv_DpuScaler_SubHdrProcessSOP(pstHdrParam);
            }
    #endif
            /* PQ callback when HDR change */
            s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].pfPQCallback(PQCALLBACK_TIMECHANGED, &(pstChannelData->stVideoConfigParams));
        }
    }
    //return HV_SUCCESS;
}

static Status Hv_Mw_Channel_VideoMute_CheckTimeout(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    LastPortUnSyncReason enLastPortUnSyncReason = LastPortUnSyncReason_None;
    BOOL bRet = pstInputPortManager->pfGetPortLastUnSyncStatus(pstChannelData->enChannelSrcLinkPortIndex, &enLastPortUnSyncReason);
    HV_LOG_DEBUG(CHANNEL, "Mute jitter timeout, PortIndex=%u Reason=%u, bRet=%u", pstChannelData->enChannelSrcLinkPortIndex, enLastPortUnSyncReason, bRet);
    if ((HV_TRUE == bRet) && (LastPortUnSyncReason_None == enLastPortUnSyncReason))
    {
        HV_LOG_DEBUG(CHANNEL, "Channel video Mute check Timeout,Unmute!!");
        Hv_Mw_Channel_MuteOff(pstChannelData->enChannelType);
        if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
        {
            Hv_Vos_Timer_Rstart(pstChannelData->pstAvWatchdogTimer,0);
        }
    }
    pstChannelData->uiMuteStatus = 0;

    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_MuteStateNormal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    Hv_Vos_Timer_Rstart(pstChannelData->pstVideoMuteTimer,0);
    HV_LOG_DEBUG(CHANNEL, "ChannelType=%u,video  Mute Status becomes Normal,Start jitter timer", pstChannelData->enChannelType);
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_MuteStateAbnormal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    UINT32 uiMuteState  = pstChannelData->pfGetMuteState();
    UINT32 uiMuteStatus = pstChannelData->pfGetMuteStatus();

    HV_LOG_INFO(CHANNEL, "ChannelType=%u,video Mute becomes abnormal status = 0x%x, state = 0x%x", pstChannelData->enChannelType, uiMuteStatus, uiMuteState);    

    pstChannelData->pfMuteForceFreeRun(HV_FALSE);
    pstChannelData->uiMuteStatus = 1;
    Hv_Vos_Timer_Rstop(pstChannelData->pstVideoMuteTimer);
    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        Hv_Vos_Timer_Rstop(pstChannelData->pstAvWatchdogTimer);
    }

    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_AudioMuteCheckTimeout(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    /*做保护处理，防止timeout前,修改了音频输入源导*/
    if (HV_TRUE == Hv_Mw_Channel_IsAudioOnThisChannel(pstChannelData->enChannelType))
    {
        LastPortUnSyncReason enLastPortUnSyncReason = LastPortUnSyncReason_None;
        BOOL bRet = pstInputPortManager->pfGetPortLastUnSyncStatus(pstChannelData->enChannelSrcLinkPortIndex, &enLastPortUnSyncReason);
        HV_LOG_DEBUG(CHANNEL, "Channel_AudioMuteCheckTimeout GetPortLastUnSyncStatus PortIndex=%u Reason=%u, bRet=%u", pstChannelData->enChannelSrcLinkPortIndex, enLastPortUnSyncReason, bRet);
        if ((HV_TRUE == bRet) && (LastPortUnSyncReason_None == enLastPortUnSyncReason))
        {
            pstInputPortManager->pfCheckAudio(pstChannelData->enChannelSrcLinkPortIndex);
            UINT32 uiMuteStatus = pstInputPortManager->pfGetMuteStatus(pstChannelData->enChannelType);
            BOOL bAudioStatus = pstInputPortManager->pfGetAudioStatus(pstChannelData->enChannelSrcLinkPortIndex);
            if((HV_TRUE == bAudioStatus) && (HV_DPU_MUTE_STATUS_NORMAL == uiMuteStatus))
            {
                HV_ASSERT_SUCCESS(Hv_Mw_Audio_ChannelUnMute(_AUDIO_MUTE_BIT_FS | _AUDIO_MUTE_BIT_HW));
                if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
                {
                    Hv_Vos_Timer_Rstart(pstChannelData->pstAvWatchdogTimer,0);
                }
                HV_LOG_INFO(CHANNEL, "Audio normal,Unmute!");
                Hv_Vos_Timer_Rstop(pstChannelData->pstAudioMuteTimer);
            }
            else
            {
                HV_LOG_INFO(CHANNEL, "Audio abnormal,still Mute!");
                Hv_Vos_Timer_Rstart(pstChannelData->pstAudioMuteTimer,0);
            }
        }
    }
    else
    {
        /*do nothing*/
    }
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_AudioMuteStateNormal(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    if (HV_TRUE == Hv_Mw_Channel_IsAudioOnThisChannel(pstChannelData->enChannelType))
    {
        const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
        LastPortUnSyncReason enLastPortUnSyncReason = LastPortUnSyncReason_None;
        BOOL bRet = pstInputPortManager->pfGetPortLastUnSyncStatus(pstChannelData->enChannelSrcLinkPortIndex, &enLastPortUnSyncReason);
        if ((HV_TRUE == bRet) && (LastPortUnSyncReason_None == enLastPortUnSyncReason))
        {
            Hv_Mw_Audio_SelectSound(pstChannelData->enChannelSrcLinkPortIndex, pstChannelData->enChannelType);
            pstInputPortManager->pfStartAudio(pstChannelData->enChannelSrcLinkPortIndex);
            pstInputPortManager->pfCheckAudio(pstChannelData->enChannelSrcLinkPortIndex);
            UINT32 uiMuteStatus = pstInputPortManager->pfGetMuteStatus(pstChannelData->enChannelType);
            BOOL bAudioStatus = pstInputPortManager->pfGetAudioStatus(pstChannelData->enChannelSrcLinkPortIndex);
            if((HV_TRUE == bAudioStatus) && (HV_DPU_MUTE_STATUS_NORMAL == uiMuteStatus))
            {
                HV_ASSERT_SUCCESS(Hv_Mw_Audio_ChannelUnMute(_AUDIO_MUTE_BIT_FS | _AUDIO_MUTE_BIT_HW));
                if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
                {
                    Hv_Vos_Timer_Rstart(pstChannelData->pstAvWatchdogTimer,0);
                }
                HV_LOG_INFO(CHANNEL, "Audio normal,Unmute!");
            }
            else
            {
                Hv_Vos_Timer_Rstart(pstChannelData->pstAudioMuteTimer,0);
                HV_LOG_INFO(CHANNEL, "Audio or Video abnormal,still Mute!");
            }
        }
        HV_LOG_DEBUG(CHANNEL, "receive AudioMuteStateChange ChannelTye=%u, start mute timer", pstChannelData->enChannelType);
    }
    else
    {
        HV_LOG_INFO(CHANNEL, "receive AudioMuteStateChange ChannelTye=%u, but OSD AudioSource Config not in this channel", pstChannelData->enChannelType);
    }

    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_AudioFsChangeHandle(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    static UCHAR8 ucAudioFsCheckNum = 0;
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    Hv_Vos_Timer_Rstop(pstChannelData->pstAudioMuteTimer);
    if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
    {
        Hv_Vos_Timer_Rstop(pstChannelData->pstAvWatchdogTimer);
    }
    if(0 == pstChannelData->uiMuteStatus)
    {
        AudioSourceConfig(pstChannelData);
        /*音源配置选了当前通道需要解Audio mute*/
        if (HV_TRUE == Hv_Mw_Channel_IsAudioOnThisChannel(pstChannelData->enChannelType))
        {
            ucAudioFsCheckNum++;
            pstInputPortManager->pfStartAudio(pstChannelData->enChannelSrcLinkPortIndex);
            pstInputPortManager->pfCheckAudio(pstChannelData->enChannelSrcLinkPortIndex);
            UINT32 uiMuteStatus = pstInputPortManager->pfGetMuteStatus(pstChannelData->enChannelType);
            BOOL bAudioStatus = pstInputPortManager->pfGetAudioStatus(pstChannelData->enChannelSrcLinkPortIndex);
            if((HV_TRUE == bAudioStatus) && (HV_DPU_MUTE_STATUS_NORMAL == uiMuteStatus))
            {
                HV_ASSERT_SUCCESS(Hv_Mw_Audio_ChannelUnMute(_AUDIO_MUTE_BIT_FS | _AUDIO_MUTE_BIT_HW));
                if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
                {
                    Hv_Vos_Timer_Rstart(pstChannelData->pstAvWatchdogTimer,0);
                }
                ucAudioFsCheckNum = 0;
                HV_LOG_INFO(CHANNEL, "FS change Audio normal,Unmute!");
            }
            else if (ucAudioFsCheckNum <= 10)
            {
                Hv_Vos_Timer_Rstart(pstChannelData->pstAudioFsCheckTimer,0);
            }
            else
            {
                ucAudioFsCheckNum = 0;
                HV_LOG_INFO(CHANNEL, "FS change Audio or Video abnormal,still Mute!");
            }
        }
    }
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_AspectRatioConfig(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "rev Hv_Mw_Channel_AspectRatioConfig enChannelType=%u!!!", pstChannelData->enChannelType);
    Hv_Mw_Channel_MuteOn(pstChannelData->enChannelType);
    /*直接返回success，会切换到search态*/
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_Reconfig(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "rev Hv_Mw_Channel_Reconfig enChannelType=%u!!!", pstChannelData->enChannelType);
    Hv_Mw_Channel_MuteOn(pstChannelData->enChannelType);
    s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex = HV_COMMON_DATABASE_GET(UserData, ucVideoSource);
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    ChannelFlashConfig stConfigData;
    stConfigData.bFlashSubFakeVideoSw = (HV_COMMON_DATABASE_GET(UserData, bMagnifyGlassSw) != HV_FALSE) ? HV_TRUE : HV_FALSE;
    stConfigData.enFlashPxPMode       = HV_COMMON_DATABASE_GET(UserData, ucPxPMode);    
    SetManagerData(&stConfigData);
    s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex = HV_COMMON_DATABASE_GET(UserData, ucPxPVideoSource);
#endif

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if((CHANNEL_TYPE_SUB ==  pstChannelData->enChannelType)
    && ((PXP_MODE_PIP_ENABLE == Hv_Mw_Channel_GetPxpMode())
    || PXP_MODE_MAGNIFY_GLASS_ENABLE == Hv_Mw_Channel_GetPxpMode()))
    {
        HV_LOG_INFO(CHANNEL, "reconfig sub, pip and magnify not update edid");
    }
    else
    {
        Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex);
    }
#else
    Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex);
#endif
    /*返回成功直接进入search态重新配置链路*/
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_VideoSrcReselect(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "Channel source reselect ChannelType=%u!!!, PrePort:%u, newPort:%u", pstChannelData->enChannelType, pstChannelData->enChannelSrcLinkPortIndex, pstChannelEvent->usValue);
    /*reselect首先需要插黑处理，之后状态切换到search 态按照正常信号搜索流程进行新端口的信号搜索*/
    Hv_Mw_Channel_MuteOn(pstChannelData->enChannelType);
    
    pstChannelData->uiEnterNoSignalCount = 0;
    pstChannelData->usTotalSearchTimes = 0;
    pstChannelData->enChannelSrcLinkPortIndex = pstChannelEvent->usValue;

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if(PXP_MODE_PIP_ENABLE == Hv_Mw_Channel_GetPxpMode())
    {
        if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)
        {
            Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex);
            if (s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex != pstChannelData->enChannelSrcLinkPortIndex)
            {
                Hw_Mw_Channel_Update_EDID(&(s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB]), s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex);
            }
        }
        else if (s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex != pstChannelData->enChannelSrcLinkPortIndex)
        {
            Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex);
        }
    }
#endif
    if ((CHANNEL_STATE_SEARCH == pstChannelData->enCurrentCHState) && (HV_FALSE ==Hv_Vos_Timer_IsTimerActive(pstChannelData->pstPeriodSearchTimer)))
    {
        HV_LOG_ERROR(CHANNEL, "ChannelType:%u", pstChannelData->enChannelType);
        Hv_Vos_Timer_Rstart(pstChannelData->pstPeriodSearchTimer,0);
    }
    Hw_Mw_SearchTable_Init(pstChannelData);
    return HV_SUCCESS;
}

static Status Hv_Mw_Channel_MainSubSourceSwap(const ChannelEvent* pstChannelEvent, ChannelData* pstChannelData)
{
    HV_LOG_DEBUG(CHANNEL, "pxp main sub source swap");
    /*reselect首先需要插黑处理，之后状态切换到search 态按照正常信号搜索流程进行新端口的信号搜索*/
    Hv_Mw_Channel_MuteOn(pstChannelData->enChannelType);
    
    pstChannelData->enChannelSrcLinkPortIndex = pstChannelEvent->usValue;
    Hw_Mw_Channel_Update_EDID(pstChannelData, pstChannelData->enChannelSrcLinkPortIndex);
    return HV_SUCCESS;
}

#ifdef HV_SCALER_DEBUG_VERSION
CHAR8* GetChannelState(ChannelState enCurrentState)
{
    if (enCurrentState == CHANNEL_STATE_ANY_STATE)
    {
        return "AnyState";
    }
    else if (enCurrentState & CHANNEL_STATE_IDLE)
    {
        return "Idle";
    }
    else if (enCurrentState & CHANNEL_STATE_INITIAL)
    {
        return "Initial";
    }
    else if (enCurrentState & CHANNEL_STATE_SEARCH)
    {
        return "Search";
    }
    else if (enCurrentState & CHANNEL_STATE_CONFIG)
    {
        return "Config";
    }
    else if (enCurrentState & CHANNEL_STATE_ACTIVE)
    {
        return "Active";
    }
    else if (enCurrentState & CHANNEL_STATE_NO_SIGNAL)
    {
        return "NoSignal";
    }
    else if (enCurrentState & CHANNEL_STATE_BURN_IN)
    {
        return "BurnIn";
    }
    return "unknown";
}
#endif

#ifdef HV_SCALER_DEBUG_VERSION
static CHAR8* EventTypeConvert(SystemRevEventType enEventType)
{
    CHAR8* paEventType[] =
    {
        "power",
        "osd",
        "channel",
        "inputport",
        "panel",
        "timer",
        "ddc/ci"    
    };
    if(enEventType >= sizeof(paEventType)/sizeof(paEventType[0]))
    {
        return "NULL";
    }
    else
    {
        return paEventType[enEventType];
    }
}

static CHAR8* ChannelEventIDConvert(USHORT16 enEventType)
{
    CHAR8* paEventIDType[] =
    {
        "First",
        "Start",
        "Search Timeout",
        "CheckAvStable",
        "Timing Change",
        "Color Change",
        "Signal Loss",
        "Plug Out",
        "Timing Stable",
        "Rcv vrr info",
        "Allm mode change",
        "Hdr Change",
        "Pxp enable",
        "Pxp disable",
        "Sub pxp disable",
        "magnify enable",
        "magnify disable",
        "sub magnify disable",
        "Hdr switch",
        "Data patch reconfig",
        "NoSignal Timeout",
        "Mute state normal",
        "Mute check timeout",
        "Audio state change",
        "Audio check timeout",
        "Set aspect ratio",
        "Reselect video source",
        "Source swap",
        "BurnIn Timeout",
        "Freesync switch",
        "Mute abnormal",
        "Audio FS Change",
        "Av watchdog",
        "No Signal To Search",
        "Pro esport switch",
    };
    if(enEventType >= sizeof(paEventIDType)/sizeof(paEventIDType[0]))
    {
        return "NULL";
    }
    else
    {
        return paEventIDType[enEventType];
    }
}
#endif

static Status RunChannelStateMachine(ChannelEvent* pstChannelEvent, ChannelData* pstChannelData, BOOL* pbNeedInsertConvertEvent)
{
    ChannelState enNextChannelState = CHANNEL_STATE_ANY_STATE;
    Status uiStatusRet = HV_FAILURE;
    *pbNeedInsertConvertEvent = HV_FALSE;/*很关键必须置位false，否则convert消息如果在for循环中无法找到则pbNeedChangeState无法赋值为false，导致while死循环*/
    
    for (USHORT16 usIndex = 0; usIndex < ARRAY_SIZE(s_astChannelStateMachine); ++usIndex)
    {
        if ((pstChannelEvent->usEventId == s_astChannelStateMachine[usIndex].enEventId)
            && (pstChannelData->enCurrentCHState & s_astChannelStateMachine[usIndex].usAcceptStates))
        {
            /*执行Event事件对应的Action*/
            uiStatusRet = s_astChannelStateMachine[usIndex].pfActionHandle(pstChannelEvent, pstChannelData);
            if (HV_SUCCESS == uiStatusRet)
            {
                enNextChannelState = s_astChannelStateMachine[usIndex].enNextSuccessState;
            }
            else if (HV_FAILURE == uiStatusRet)
            {
                enNextChannelState = s_astChannelStateMachine[usIndex].enNextFailState;
            }
            else
            {
                /*continue 以及其他返回值场景*/
            }
#ifdef HV_SCALER_DEBUG_VERSION
            static UINT32 uiLoop = 1;
            if((CHANNEL_EVENT_ID_PERIOD_SEARCH_TIME_OUT != pstChannelEvent->usEventId) && (CHANNEL_EVENT_ID_BURN_IN_PERIOD_CHECK_TIMER != pstChannelEvent->usEventId))
            {
                if((CHANNEL_EVENT_ID_AV_WATCHDOG != pstChannelEvent->usEventId) && (CHANNEL_EVENT_ID_CONFIG_CHECK_AV_STABLE != pstChannelEvent->usEventId))
                {
                    HV_LOG_INFO(CHANNEL, "Channel %s,%s,%s,%u, port %u", GetChannelState(pstChannelData->enCurrentCHState), ChannelEventIDConvert(pstChannelEvent->usEventId), GetChannelState(enNextChannelState), pstChannelEvent->enChannelType, pstChannelData->enChannelSrcLinkPortIndex);
                    uiLoop = 1;
                }
            }
            else
            {
                if((uiLoop % 10) == 1)
                {
                    HV_LOG_INFO(CHANNEL, "Channel %s,%s,%s,%u, port %u", GetChannelState(pstChannelData->enCurrentCHState), ChannelEventIDConvert(pstChannelEvent->usEventId), GetChannelState(enNextChannelState), pstChannelEvent->enChannelType, pstChannelData->enChannelSrcLinkPortIndex);   
                }
                uiLoop++;
            }
#endif
            if ((enNextChannelState != pstChannelData->enCurrentCHState) && (enNextChannelState != CHANNEL_STATE_ANY_STATE))
            {
                 pstChannelData->enCurrentCHState = enNextChannelState;
                 *pbNeedInsertConvertEvent = HV_TRUE;
            }
            else
            {
                 *pbNeedInsertConvertEvent = HV_FALSE;
            }
            /*enCurrentCHState 已修改，不能继续匹配。保证每次只执DoChannelActionOnEventMsg一次！所以需要break退出*/
            break;
       }
    }
    return uiStatusRet;
}

Status ConvertSystemTimerEventToChannelEvent(const SystemEvent* pstSystemEvent, ChannelEvent* pstChannelEvent)
{
    Status uiStatusRet = HV_SUCCESS;
    pstChannelEvent->usValue = pstSystemEvent->uiValue;
    switch (pstSystemEvent->usEventId)
    {
        case SYS_EVENT_TIMER_CH_MAIN_PERIOD_SERACH:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_PERIOD_SEARCH_TIME_OUT;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_MAIN;
            break;
        }
        case SYS_EVENT_TIMER_CH_MAIN_AV_STABLE:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_CONFIG_CHECK_AV_STABLE;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_MAIN;
            break;
        }
        case SYS_EVENT_TIMER_MAIN_NO_SIGNAL_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_NO_SIGNAL_CHECK_TIMER;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_MAIN;
            break;
        }
        case SYS_EVENT_TIMER_MAIN_MUTE_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_MUTE_CHECK_TIMER_OUT;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_MAIN;
            break;
        }
        case SYS_EVENT_TIMER_MAIN_AUDIO_MUTE_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_AUDIO_MUTE_CHECK_TIMER_OUT;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_MAIN;
            break;
        }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        case SYS_EVENT_TIMER_CH_SUB_PERIOD_SERACH:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_PERIOD_SEARCH_TIME_OUT;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_SUB;
            break;
        }

        case SYS_EVENT_TIMER_CH_SUB_AV_STABLE:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_CONFIG_CHECK_AV_STABLE;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_SUB;
            break;
        }

        case SYS_EVENT_TIMER_SUB_NO_SIGNAL_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_NO_SIGNAL_CHECK_TIMER;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_SUB;
            break;
        }

        case SYS_EVENT_TIMER_SUB_MUTE_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_MUTE_CHECK_TIMER_OUT;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_SUB;
            break;
        }

        case SYS_EVENT_TIMER_SUB_AUDIO_MUTE_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_AUDIO_MUTE_CHECK_TIMER_OUT;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_SUB;
            break;
        }
        case SYS_EVENT_TIMER_SUB_AUDIO_FS_CHECK_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_AUDIO_FS_CHANGE;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_SUB;
            break;
        }
#endif
        case SYS_EVENT_TIMER_BURN_IN_PERIOD_CHECK_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_BURN_IN_PERIOD_CHECK_TIMER;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_MAIN;
            break;
        }
        case SYS_EVENT_TIMER_AV_WATCHDOG_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_AV_WATCHDOG;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_MAIN;
            break;
        }
        case SYS_EVENT_TIMER_MAIN_AUDIO_FS_CHECK_TIMER:
        {
            pstChannelEvent->usEventId = CHANNEL_EVENT_ID_AUDIO_FS_CHANGE;
            pstChannelEvent->enChannelType = CHANNEL_TYPE_MAIN;
            break;
        }
        case SYS_EVENT_TIMER_DATABASE_SYNC_TIMER:
        {
            break;
        }
        default:
        {
            uiStatusRet = HV_FAILURE;
            HV_LOG_ERROR(CHANNEL, "receive unknown channeTimerId =%u", pstSystemEvent->usEventId);
            break;
        }
    }
    return uiStatusRet;
}

Status Hv_Mw_Channel_ProcSystemQueueMsg(const SystemEvent* pstSystemEvent)
{
    ChannelEvent stChannelEvent = {0};
#ifdef HV_SCALER_DEBUG_VERSION
    if(SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType)
    {
        if((SYS_EVENT_TIMER_DATABASE_SYNC_TIMER != pstSystemEvent->usEventId) 
        && (SYS_EVENT_TIMER_CH_MAIN_PERIOD_SERACH != pstSystemEvent->usEventId) 
        && (SYS_EVENT_TIMER_CH_SUB_PERIOD_SERACH != pstSystemEvent->usEventId)
        && (SYS_EVENT_TIMER_AV_WATCHDOG_TIMER != pstSystemEvent->usEventId)
        && (SYS_EVENT_TIMER_BURN_IN_PERIOD_CHECK_TIMER != pstSystemEvent->usEventId)
        && (SYS_EVENT_TIMER_CH_SUB_AV_STABLE != pstSystemEvent->usEventId)
        && (SYS_EVENT_TIMER_CH_MAIN_AV_STABLE != pstSystemEvent->usEventId))
        {
            HV_LOG_INFO(CHANNEL, "Channel %s,%s", EventTypeConvert(pstSystemEvent->enEventType),TimerEventIDConvert((TIMER_EVENT_E)pstSystemEvent->usEventId));
        }   
    }
    if(SYSTEM_REV_EVENT_TYPE_CHANNEL == pstSystemEvent->enEventType)
    {
        HV_LOG_INFO(CHANNEL, "Channel %s,%s,0x%03x,%u", EventTypeConvert(pstSystemEvent->enEventType),ChannelEventIDConvert(pstSystemEvent->usEventId), pstSystemEvent->uiValue,pstSystemEvent->ucChannelType);
    }
#endif
    if (SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType)
    {
        HV_ASSERT_SUCCESS(ConvertSystemTimerEventToChannelEvent(pstSystemEvent, &stChannelEvent));
        if(SYS_EVENT_TIMER_DATABASE_SYNC_TIMER == pstSystemEvent->usEventId) /*wait for later proccess */
        {
            return HV_SUCCESS;
        }
    }
    else if (SYSTEM_REV_EVENT_TYPE_CHANNEL == pstSystemEvent->enEventType)
    {
        stChannelEvent.usEventId     = pstSystemEvent->usEventId;
        stChannelEvent.enChannelType = pstSystemEvent->ucChannelType;
        stChannelEvent.usValue       = pstSystemEvent->uiValue;
    }
    else
    {
        HV_LOG_ERROR(CHANNEL, "unknown enEventType =%u", pstSystemEvent->enEventType);
        return HV_FAILURE;        
    }
    HV_ASSERT_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));

    return HV_SUCCESS;
}

static Status ChannelTimerInit(ChannelManager* pstChannelManager)
{
    HV_TIMER_INIT_PARAMS stMainPeriodSearchTimerParam = \
    {"ChannelMainPeriodSearchTimer", HV_PROJECT_CONFIG_PERIOD_SEARCH_CHECK_SROUCE_TIMER, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_CH_MAIN_PERIOD_SERACH};
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstPeriodSearchTimer = Hv_Vos_Timer_Create(&stMainPeriodSearchTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstPeriodSearchTimer);

    HV_TIMER_INIT_PARAMS stMainAVCheckStableTimerParam = \
    {"MainAudioVideoCheckStableTimer", 200, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_CH_MAIN_AV_STABLE};
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstAVcheckStableTimer = Hv_Vos_Timer_Create(&stMainAVCheckStableTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstAVcheckStableTimer);

    HV_TIMER_INIT_PARAMS stMainNoSignalTimerParam = \
    {"MainNoSignalTimerStandbyTimer", HV_PROJECT_CONFIG_NO_SIGNAL_CHECK_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_MAIN_NO_SIGNAL_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstNoSignalTimer = Hv_Vos_Timer_Create(&stMainNoSignalTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstNoSignalTimer);

    HV_TIMER_INIT_PARAMS stMainMuteNormalTimerParam = \
    {"MuteMainAbnormalTimer", UNMUTE_VIDEO_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_MAIN_MUTE_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstVideoMuteTimer = Hv_Vos_Timer_Create(&stMainMuteNormalTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstVideoMuteTimer);

    HV_TIMER_INIT_PARAMS stMainAudioMuteAbnormalTimerParam = \
    {"AudioMuteMainAbnormalTimer", UNMUTE_AUDIO_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_MAIN_AUDIO_MUTE_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstAudioMuteTimer = Hv_Vos_Timer_Create(&stMainAudioMuteAbnormalTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstAudioMuteTimer);

    HV_TIMER_INIT_PARAMS stBurnInPeriodCheckTimerParam = \
    {"BurnInPeriodCheckTimer", BURN_IN_PERIOD_CHECK_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_BURN_IN_PERIOD_CHECK_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstBurnInPeriodCheckTimer = Hv_Vos_Timer_Create(&stBurnInPeriodCheckTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstBurnInPeriodCheckTimer);

    HV_TIMER_INIT_PARAMS stAvWatchDogTimerParam = \
    {"AvWatchDogTimer", AV_WATCHDOG_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_AV_WATCHDOG_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstAvWatchdogTimer = Hv_Vos_Timer_Create(&stAvWatchDogTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstAvWatchdogTimer);

    HV_TIMER_INIT_PARAMS stMainAudioFsCheckTimerParam = \
    {"AudioFsCheckTimer", AUDIO_FS_CHECK_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_MAIN_AUDIO_FS_CHECK_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstAudioFsCheckTimer = Hv_Vos_Timer_Create(&stMainAudioFsCheckTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pstAudioFsCheckTimer);

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    HV_TIMER_INIT_PARAMS stSubPeriodSearchTimerParam = \
    {"ChannelSubPeriodSearchTimer", HV_PROJECT_CONFIG_PERIOD_SEARCH_CHECK_SROUCE_TIMER, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_CH_SUB_PERIOD_SERACH};
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstPeriodSearchTimer = Hv_Vos_Timer_Create(&stSubPeriodSearchTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstPeriodSearchTimer);

    HV_TIMER_INIT_PARAMS stSubAVCheckStableTimerParam = \
    {"SubAudioVideoCheckStableTimer", 200, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_CH_SUB_AV_STABLE};
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstAVcheckStableTimer = Hv_Vos_Timer_Create(&stSubAVCheckStableTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstAVcheckStableTimer);

    HV_TIMER_INIT_PARAMS stSubNoSignalTimerParam = \
    {"SubNoSignalTimerStandbyTimer", HV_PROJECT_CONFIG_NO_SIGNAL_CHECK_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_SUB_NO_SIGNAL_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstNoSignalTimer = Hv_Vos_Timer_Create(&stSubNoSignalTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstNoSignalTimer);

    HV_TIMER_INIT_PARAMS stSubMuteNormalTimerParam = \
    {"MuteSubAbnormalTimer", UNMUTE_VIDEO_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_SUB_MUTE_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstVideoMuteTimer = Hv_Vos_Timer_Create(&stSubMuteNormalTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstVideoMuteTimer);

    HV_TIMER_INIT_PARAMS stSubAudioMuteAbnormalTimerParam = \
    {"AudioMuteSubAbnormalTimer", UNMUTE_AUDIO_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_SUB_AUDIO_MUTE_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstAudioMuteTimer = Hv_Vos_Timer_Create(&stSubAudioMuteAbnormalTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstAudioMuteTimer);

    HV_TIMER_INIT_PARAMS stSubAudioFsCheckTimerParam = \
    {"AudioFsCheckTimer", AUDIO_FS_CHECK_TIMER_LENGTH, HV_FALSE, NULL, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_SUB_AUDIO_FS_CHECK_TIMER};
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstAudioFsCheckTimer = Hv_Vos_Timer_Create(&stSubAudioFsCheckTimerParam);
    HV_ASSERT_VALID_PTR(pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pstAudioFsCheckTimer);
#endif
    return HV_SUCCESS;
}

const ChannelManager* Hv_Mw_Channel_GetManager(VOID)
{
    return &s_stChannelManager;
}

ChannelFlashConfig* Hv_Mw_Channel_GetManagerData(VOID)
{
    return &s_stChannelManager.stChannelFlashConfig;
}

PxpMode Hv_Mw_Channel_GetPxpMode(VOID)
{
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    const ChannelFlashConfig *pstConfigData = Hv_Mw_Channel_GetManagerData();
    if (HV_TRUE == pstConfigData->bFlashSubFakeVideoSw)
    {
        return PXP_MODE_MAGNIFY_GLASS_ENABLE;
    }
    else if (PXP_MODE_PIP_ENABLE == pstConfigData->enFlashPxPMode)
    {
        return PXP_MODE_PIP_ENABLE;
    }
    else if (PXP_MODE_PBP_ENABLE == pstConfigData->enFlashPxPMode)
    {
        return PXP_MODE_PBP_ENABLE;
    }
    else
    {
        return PXP_MODE_CLOSE;
    }
#else
    return PXP_MODE_CLOSE;
#endif
}

static Status ChannelDataInit(ChannelManager* pstChannelManager)
{
#ifdef HV_SCALER_DEBUG_VERSION
    extern UINT32 g_uiShellDebugForTest;
    /*防止debug模式下编译优化把shell_debug_cmd.c 优化掉*/
    g_uiShellDebugForTest = 1;
#endif

    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].enCurrentCHState          = CHANNEL_STATE_IDLE;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].enChannelType             = CHANNEL_TYPE_MAIN;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex = HV_COMMON_DATABASE_GET(UserData, ucVideoSource);
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].enChanelSignalState       = ChanelSignalState_Invalid;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pfMuteInit                = Hv_Drv_DpuScaler_MainMute_Init;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pfSetMuteTiming           = Hv_Drv_DpuScaler_SetMainMuteTiming;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pfGetMuteState            = Hv_Drv_DpuScaler_GetMainMuteState;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pfGetMuteStatus           = Hv_Drv_DpuScaler_GetMainMuteStatus;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pfMuteForceFreeRun        = Hv_Drv_DpuScaler_MainMuteForceFreeRun;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pfMuteClearEn             = Hv_Drv_DpuScaler_MainMuteClearEn;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pfDpuScalerConfig         = Hv_Drv_DpuMainScaler_Config;
    pstChannelManager->astChannelData[CHANNEL_TYPE_MAIN].pfPQCallback              = Hv_App_PQ_CallBack;

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].enCurrentCHState           = CHANNEL_STATE_IDLE;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].enChannelType              = CHANNEL_TYPE_SUB;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex  = HV_COMMON_DATABASE_GET(UserData, ucPxPVideoSource);
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].enChanelSignalState        = ChanelSignalState_Invalid;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pfMuteInit                 = Hv_Drv_DpuScaler_SubMute_Init;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pfSetMuteTiming            = Hv_Drv_DpuScaler_SetSubMuteTiming;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pfGetMuteState             = Hv_Drv_DpuScaler_GetSubMuteState;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pfGetMuteStatus            = Hv_Drv_DpuScaler_GetSubMuteStatus;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pfMuteForceFreeRun         = Hv_Drv_DpuScaler_SubMuteForceFreeRun;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pfMuteClearEn              = Hv_Drv_DpuScaler_SubMuteClearEn;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pfDpuScalerConfig          = Hv_Drv_DpuSubScaler_Config;
    pstChannelManager->astChannelData[CHANNEL_TYPE_SUB].pfPQCallback               = Hv_App_PQ_CallBack;

    pstChannelManager->stChannelFlashConfig.enFlashPxPMode = HV_COMMON_DATABASE_GET(UserData, ucPxPMode);
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY)
    pstChannelManager->stChannelFlashConfig.bFlashSubFakeVideoSw = (HV_COMMON_DATABASE_GET(UserData, bMagnifyGlassSw) != HV_FALSE) ? HV_TRUE : HV_FALSE;
    if (pstChannelManager->stChannelFlashConfig.bFlashSubFakeVideoSw == HV_TRUE)
    {
        pstChannelManager->stChannelFlashConfig.enFlashPxPMode = PXP_MODE_PIP_ENABLE;
    }
#endif
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DPU_BRIGHT_FRAME)
    pstChannelManager->stChannelFlashConfig.bFlashSubFakeVideoSw = (HV_COMMON_DATABASE_GET(UserData, bBrightFrameEn) != HV_FALSE) ? HV_TRUE : HV_FALSE;
    if (pstChannelManager->stChannelFlashConfig.bFlashSubFakeVideoSw == HV_TRUE)
    {
        pstChannelManager->stChannelFlashConfig.enFlashPxPMode = PXP_MODE_PIP_ENABLE;
    }
#endif
#endif

    HV_ASSERT_SUCCESS(ChannelTimerInit(pstChannelManager));
    return HV_SUCCESS;
}

Status Hv_Mw_Channel_Manager_Init(VOID)
{
    QueueReset(&s_stChannelManager.stChInnerMsgQueue);
    HV_ASSERT_SUCCESS(ChannelDataInit(&s_stChannelManager));
    Hv_Mw_Video_SetVideoPanelParam();

    VideoTimingParam    stVideoTiming = {0};
    /*default settting display control using for OSD logo, using black pattern picture*/
    VideoConfigParams stVideoConfigParams = {0};
    Hv_Mw_Video_GetFakeVideoConfigParams(&stVideoTiming, &stVideoConfigParams);

    /*设置默认rxd clock*/
    UINT32 uiDClkCfg = 0;
    UINT64 uiDClockDst = (UINT64) stVideoConfigParams.uiOutputVideoHtotal * stVideoConfigParams.uiOutputVideoVtotal * stVideoConfigParams.uiOutputFrameRate / 1000; 
    Hv_Drv_PLL_SetRxdpllPixelClock(CHANNEL_TYPE_MAIN,&uiDClkCfg, uiDClockDst);
    stVideoConfigParams.uiRxDpllFreq = uiDClkCfg;

    HV_ASSERT_SUCCESS(Hv_Drv_PLL_SetDisplayClock(&uiDClkCfg, uiDClockDst,&stVideoConfigParams));
    Hv_Drv_DpuScaler_DtcClockConfig();
    stVideoConfigParams.uiDisplayPllFreq = uiDClkCfg;
    stVideoConfigParams.uiDestDisplayPllFreq = uiDClockDst;
    HV_LOG_DEBUG(CHANNEL,"Startup Default ip Clock=%d,d_clock=%d\n", stVideoConfigParams.uiRxDpllFreq,stVideoConfigParams.uiDisplayPllFreq);
    Hv_Drv_DpuScaler_SetPortMux(CHANNEL_TYPE_MAIN, LINK_PORT_INDEX_INVALID);
    /*display control and mute hardware init*/
    s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].pfMuteInit();
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    Hv_Drv_DpuScaler_SetPortMux(CHANNEL_TYPE_SUB, LINK_PORT_INDEX_INVALID);
    s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].pfMuteInit();
#endif

    /* 初始化到可以正常打Pattern */
    s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].pfSetMuteTiming(&stVideoTiming,stVideoConfigParams.uiRxDpllFreq, stVideoConfigParams.bOsdVrrEnable);

    s_stChannelManager.bSignalInterruption = HV_FALSE;
    const PanelParam stPanelParam = Hv_Mw_Panel_GetCurrentPanelParam();
    Hv_Drv_DpuScaler_Init(stPanelParam);
    HV_ASSERT_SUCCESS(s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].pfDpuScalerConfig(&stVideoConfigParams));

    Hv_Mw_Audio_ChannelMute(_AUDIO_MUTE_BIT_HW);
    Hv_Drv_DpuScaler_SoftwareVideoMute(CHANNEL_TYPE_MAIN);

    HV_ASSERT_SUCCESS(Hv_Mw_Mute_Interrupt_Init());
    HV_ASSERT_SUCCESS(Hv_Mw_Audio_Interrupt_Init());
    HV_ASSERT_SUCCESS(Hv_Mw_Dpu_Interrupt_Init());

    Hv_Cal_DpuScaler_ResetClock_Enable();

    Hw_Mw_Channel_Update_EDID(&s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN], s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex);
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if (s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex == s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex)
    {
        HV_LOG_DEBUG(CHANNEL, "init, sub main soure same, sub not update edid %u ", s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex);
    }
    else
    {
        Hw_Mw_Channel_Update_EDID(&s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB], s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex);
    }
#endif
    Hv_Cal_OsdTmg_Init();
    Hv_Cal_Osd_InitSync();
    Hv_App_PQ_Init();
    return HV_SUCCESS;
}

Status Hv_Mw_Channel_GetSignalState(ChannelType enChannelType, 
                                    LinkPortIndex* penChannelSrcLinkPortIndex,
                                    ChanelSignalState* penChanelSignalState)
{
    HV_ASSERT_VALID_PTR(penChannelSrcLinkPortIndex);
    HV_ASSERT_VALID_PTR(penChanelSignalState);

    if (CHANNEL_TYPE_MAIN == enChannelType)
    {
        *penChannelSrcLinkPortIndex = s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enLastChannelSrcLinkPortIndex;
        *penChanelSignalState = s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChanelSignalState;
    }
    else if (CHANNEL_TYPE_SUB == enChannelType)
    {
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        *penChannelSrcLinkPortIndex = s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enLastChannelSrcLinkPortIndex;
        *penChanelSignalState = s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChanelSignalState;
#else
        *penChannelSrcLinkPortIndex = LINK_PORT_INDEX_INVALID;
        *penChanelSignalState = ChanelSignalState_Invalid;
#endif 
    }
    else
    {
        HV_LOG_ERROR(CHANNEL, "unknown enChannelType =%u", enChannelType);
    }
    HV_LOG_DEBUG(CHANNEL, "PortIndex =%u,signal state=%u", *penChannelSrcLinkPortIndex,*penChanelSignalState);
    return HV_SUCCESS;
}

Status Hv_Mw_Channel_GetVideoTiming(ChannelType enChannelType, VideoTimingParam* pstVideoTiming)
{
    LinkPortIndex   enChannelSrcLinkPortIndex = LINK_PORT_INDEX_INVALID;
    HV_ASSERT_VALID_PTR(pstVideoTiming);
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    if (CHANNEL_TYPE_MAIN == enChannelType)
    {
        enChannelSrcLinkPortIndex = s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enChannelSrcLinkPortIndex;
        HV_ASSERT_SUCCESS(pstInputPortManager->pfGetVideoPara(enChannelSrcLinkPortIndex,&s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN]));
    }
    else
    {
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        enChannelSrcLinkPortIndex = s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enChannelSrcLinkPortIndex;
        HV_ASSERT_SUCCESS(pstInputPortManager->pfGetVideoPara(enChannelSrcLinkPortIndex,&s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB]));
#endif
    }
    return HV_SUCCESS;
}

VOID Hv_Mw_Channel_SetOSDActive(BOOL bStatus)
{
    s_stChannelManager.bOSDActive = bStatus;
}

BOOL Hv_Mw_Channel_GetOSDActive(VOID)
{
    return s_stChannelManager.bOSDActive;
}

VOID Hv_Mw_Channel_MuteOn(ChannelType enChannelType)
{
    ChannelData* pstChannelData = NULL;
    pstChannelData = &s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN];
    Hv_Drv_DpuScaler_SoftwareVideoMute(enChannelType);
    if(CHANNEL_TYPE_MAIN == enChannelType)
    {
        if (CHANNEL_STATE_CONFIG != pstChannelData->enCurrentCHState)
        {
            Hv_Drv_DpuScaler_InitFrcModeMain(HV_FALSE);
            pstChannelData->pfMuteForceFreeRun(HV_TRUE);
        }
        if((Hv_Mw_OsdGetLogoState() != OSD_LOGO_DONE) || (HV_TRUE == Hv_Mw_OsdCheckIsShowing()))
        {
            HV_LOG_DEBUG(CHANNEL, "Logo or osd on display,keep backlight on");
        }
        else
        {
#ifdef CONFIG_USER_USB_OTA_ON
            if(USB_STATE_OTA_IN_PROCESSING != Hv_Mw_USB_GetUsbState())
            {
                #if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
                Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_DISABLE);
                #endif
            }
#else
            #if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
            Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_DISABLE);
            #endif
#endif
        }
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else
    {
        pstChannelData = &s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB];
        if (CHANNEL_STATE_CONFIG != pstChannelData->enCurrentCHState)
        {
            Hv_Drv_DpuScaler_InitFrcModeSub(HV_FALSE);
            pstChannelData->pfMuteForceFreeRun(HV_TRUE);
        }
    }
#endif
    if (HV_TRUE == Hv_Mw_Channel_IsAudioOnThisChannel(enChannelType))
    {
        Hv_Mw_Audio_ChannelMute(_AUDIO_MUTE_BIT_HW);
    }
    HV_LOG_DEBUG(CHANNEL, "mute on, ChannelType:%u", enChannelType);
    return;
}

Status Hv_Mw_Channel_MuteOff(ChannelType enChannelType)
{
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    const PanelManager* pstPanelManager = Hv_Mw_Panel_GetManagerPtr();
    ChannelData* pstChannelData = NULL;
    UINT32 uiMuteStatus = 0;
    UINT32 uiDtcStatus = 0;
    if(CHANNEL_TYPE_MAIN == enChannelType)
    {
        pstChannelData = &s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN];
        uiMuteStatus = pstInputPortManager->pfGetMuteStatus(CHANNEL_TYPE_MAIN);
        uiDtcStatus = Hv_Drv_DpuScaler_CheckDtcStable(&pstChannelData->stVideoConfigParams);
        if ((CHANNEL_STATE_CONFIG == pstChannelData->enCurrentCHState)
            || (CHANNEL_STATE_SEARCH == pstChannelData->enCurrentCHState))
        {
            HV_LOG_ERROR(CHANNEL, "main channel is not ready,contiue mute, ChannelType: %u", enChannelType);
            return HV_FAILURE;
        }
        if(CHANNEL_STATE_ACTIVE == pstChannelData->enCurrentCHState)
        {
            if((HV_DPU_MUTE_STATUS_NORMAL != uiMuteStatus) || (HV_TRUE != uiDtcStatus))
            {
                HV_LOG_ERROR(CHANNEL, "mute or dtc abnormal,contiue mute, ChannelType: %u", enChannelType);
                return HV_FAILURE;
            }
        }
        if(Hv_Mw_OsdGetLogoState() != OSD_LOGO_DONE)
        {
            HV_LOG_ERROR(CHANNEL, "Logo on display,contiue mute, ChannelType: %u", enChannelType);
            return HV_FAILURE;
        }
        
        HV_LOG_DEBUG(CHANNEL, "mute off, ChannelType: %u", enChannelType);

        /* 
         * 如果源不发声音，audio check中会延时等待最大超时时间，
         * 所以要先解video mute，再解audio mute，否则audio会阻塞video
         */
        if (0 != Hv_Mw_Channel_GetChannelOnDisplay())
        {
            Hv_Drv_DpuScaler_VideoUnmute(CHANNEL_TYPE_MAIN);  //显示osd不需要解插黑，只开背光
        }
        pstChannelData->pfMuteForceFreeRun(HV_FALSE);
        if(pstPanelManager->enCurrentPanelState == PANEL_STATE_BLK_ON)
        {
            Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_ENABLE);
        }

        if ((HV_TRUE == Hv_Mw_Channel_IsAudioOnThisChannel(CHANNEL_TYPE_MAIN)) && (CHANNEL_STATE_ACTIVE == pstChannelData->enCurrentCHState))
        {
            pstInputPortManager->pfCheckAudio(pstChannelData->enChannelSrcLinkPortIndex);
            if (pstChannelData->enChannelSrcLinkPortIndex == LINK_PORT_INDEX_DP_RX0 || 
                pstChannelData->enChannelSrcLinkPortIndex == LINK_PORT_INDEX_DP_RX1)
            {
                if (pstInputPortManager->pfGetAudioStatus(pstChannelData->enChannelSrcLinkPortIndex) == HV_TRUE)
                {
                    Hv_Mw_Audio_ChannelUnMute(_AUDIO_MUTE_BIT_HW | _AUDIO_MUTE_BIT_FS);
                }
                else
                {
                    Hv_Vos_Timer_Rstart(pstChannelData->pstAudioMuteTimer,0);
                }
            }
            else
            {
                // hdmi先判断CTS/N再决定声音是否解mute
                UINT32 uiCts = 0;
                UINT32 uiN   = 0;
                Hv_Mw_HdmiRx_GetAudioCurrentCTSN(pstChannelData->enChannelSrcLinkPortIndex, &uiCts, &uiN);
                if (uiCts != 0 && uiN != 0)
                {
                    Hv_Mw_Audio_ChannelUnMute(_AUDIO_MUTE_BIT_HW | _AUDIO_MUTE_BIT_FS);
                }
                else
                {
                    Hv_Vos_Timer_Rstart(pstChannelData->pstAudioMuteTimer,0);
                }
            }
       }
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else
    {
        pstChannelData = &s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB];
        uiMuteStatus = pstInputPortManager->pfGetMuteStatus(CHANNEL_TYPE_SUB);

        if ((CHANNEL_STATE_CONFIG == pstChannelData->enCurrentCHState)
            || (CHANNEL_STATE_SEARCH == pstChannelData->enCurrentCHState))
        {
            HV_LOG_ERROR(CHANNEL, "sub channel is not ready,contiue mute, ChannelType: %u", enChannelType);
            return HV_FAILURE;
        }
        if(CHANNEL_STATE_ACTIVE == pstChannelData->enCurrentCHState)
        {
            if(HV_DPU_MUTE_STATUS_NORMAL != uiMuteStatus)
            {
                HV_LOG_ERROR(CHANNEL, "mute abnormal,contiue mute, ChannelType: %u", enChannelType);
                return HV_FAILURE;
            }
        }

        Hv_Drv_DpuScaler_PQ_Debug();
        
        HV_LOG_DEBUG(CHANNEL, "mute off, ChannelType: %u", enChannelType);

        Hv_Drv_DpuScaler_VideoUnmute(CHANNEL_TYPE_SUB);
        pstChannelData->pfMuteForceFreeRun(HV_FALSE);
        if((pstPanelManager->enCurrentPanelState == PANEL_STATE_BLK_ON)
        && ((CHANNEL_STATE_NO_SIGNAL | CHANNEL_STATE_ACTIVE) & s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enCurrentCHState))
        {
            Hv_Drv_Ktx_SetBacklightPower(HV_PROJECT_CONFIG_BACKLIGHT_ENABLE);
        }
        
        if (HV_TRUE == Hv_Mw_Channel_IsAudioOnThisChannel(CHANNEL_TYPE_SUB))
        {
            pstInputPortManager->pfCheckAudio(pstChannelData->enChannelSrcLinkPortIndex);
            if (pstChannelData->enChannelSrcLinkPortIndex == LINK_PORT_INDEX_DP_RX0 || 
                pstChannelData->enChannelSrcLinkPortIndex == LINK_PORT_INDEX_DP_RX1)
            {
                if (pstInputPortManager->pfGetAudioStatus(pstChannelData->enChannelSrcLinkPortIndex) == HV_TRUE)
                {
                    Hv_Mw_Audio_ChannelUnMute(_AUDIO_MUTE_BIT_HW | _AUDIO_MUTE_BIT_FS);
                }
                else
                {
                    Hv_Vos_Timer_Rstart(pstChannelData->pstAudioMuteTimer,0);
                }
            }
            else
            {
                // hdmi先判断CTS/N再决定声音是否解mute
                UINT32 uiCts, uiN;
                Hv_Mw_HdmiRx_GetAudioCurrentCTSN(pstChannelData->enChannelSrcLinkPortIndex, &uiCts, &uiN);
                if (uiCts != 0 && uiN != 0)
                {
                    Hv_Mw_Audio_ChannelUnMute(_AUDIO_MUTE_BIT_HW | _AUDIO_MUTE_BIT_FS);
                }
                else
                {
                    Hv_Vos_Timer_Rstart(pstChannelData->pstAudioMuteTimer,0);
                }
            }
        }
    }
#endif
    return HV_SUCCESS;

}

UCHAR8 Hv_Mw_Channel_GetChannelOnDisplay(VOID)
{
    UCHAR8 ucChannelOnDisplay = 0;
    if (s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enCurrentCHState == CHANNEL_STATE_ACTIVE)
    {
        ucChannelOnDisplay = BIT_0;
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if (s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].enCurrentCHState == CHANNEL_STATE_ACTIVE)
    {
        ucChannelOnDisplay = ucChannelOnDisplay | BIT_1;
    }
#endif
    HV_LOG_DEBUG(CHANNEL, "Hv_Mw_Channel_GetChannelOnDisplay: %u", ucChannelOnDisplay);
    return ucChannelOnDisplay;
}

VOID Hv_Mw_Channel_UpdateVideoConfigParam(ChannelType enChannelType, VideoConfigParams stVideoConfigParams)
{
    if (CHANNEL_TYPE_MAIN == enChannelType)
    {
        s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].stVideoConfigParams = stVideoConfigParams;
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else
    {
        s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams = stVideoConfigParams;
    }
#endif
    return;
}

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
VOID Hv_Mw_Channel_UpdateMainRxFakeVideoParam(MainRxFakeVideoParam stMainRxFakeVideoParam)
{
    s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams.fMainFakeRatio = stMainRxFakeVideoParam.fMainFakeRatio;
    s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams.usMainFakeHsize = stMainRxFakeVideoParam.usMainFakeHsize;
    s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams.usMainFakeVsize = stMainRxFakeVideoParam.usMainFakeVsize;
    s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams.usMainFakePosH = stMainRxFakeVideoParam.usMainFakePosH;
    s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams.usMainFakePosV = stMainRxFakeVideoParam.usMainFakePosV;
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY)
    if (HV_FALSE != HV_COMMON_DATABASE_GET(UserData, bMagnifyGlassSw))
    {
        /*开启了放大镜 用1:1做scaler，cap后端cut*/
        Hv_Mw_video_CalcMagniferDdrVideoSize(&s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams);
#endif
    }
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DPU_BRIGHT_FRAME)
    if (HV_COMMON_DATABASE_GET(UserData, bBrightFrameEn))
    {
        Hv_Mw_video_CalcDcwDdrOrWtrSize(&s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].stVideoConfigParams);
    }
#endif
    return;
}
#endif

Status Hw_Mw_Channel_SendNoSignalMsgToPowerManager(BOOL bEnterFlag)
{   /*由于是无信号进待机，理论上都是channel发出，所以放在channelmanger里面*/
    HV_VOS_QUEUE_S *pstSystemQueue = Hv_Mw_System_GetSystemQueue();
    HV_ASSERT_VALID_PTR(pstSystemQueue);
    SystemEvent stEvent = {0};
    stEvent.enEventType = SYSTEM_REV_EVENT_TYPE_POWER;
    if (bEnterFlag)
    {
#ifdef CONFIG_USER_USB_OTA_ON
        if(USB_STATE_OTA_IN_PROCESSING == Hv_Mw_USB_GetUsbState())
        {
            return HV_SUCCESS;
        }
#endif
        if (s_stChannelManager.bSignalInterruption == HV_TRUE)
        {
            s_stChannelManager.bSignalInterruption = HV_FALSE;
            return HV_SUCCESS;
        }
        stEvent.usEventId = POWER_EVENT_ID_APP_TIME_OUT_OR_NO_SIGNAL;
        s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].bStandByFlag = HV_TRUE;
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].bStandByFlag = HV_TRUE;
#endif
    }
    else
    {
        stEvent.usEventId = POWER_EVENT_ID_SIGNAL_NORMAL;
        s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].bStandByFlag = HV_FALSE;
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
        s_stChannelManager.astChannelData[CHANNEL_TYPE_SUB].bStandByFlag = HV_FALSE;
#endif
    }

    HV_ASSERT_TRUE(Hv_Vos_QueueSend(pstSystemQueue, &stEvent));
    HV_LOG_DEBUG(POWER, "send StandbyMsg to PowerManager success enEventType=%u usEventId=%u!!!", stEvent.enEventType, stEvent.usEventId);
    return HV_SUCCESS;
}

VOID Hv_Mw_Channel_StopAvWatchdogTimer(VOID)
{
    Hv_Vos_Timer_Rstop(s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].pstAvWatchdogTimer);
    return;
}

Status Hv_Mw_Channel_GetChannelNoSignalSearchStatus(VOID)
{
    const PowerManager *pstPowerManager = Hv_Mw_Power_GetManagerPtr();
    /*判断Main是否有信号识别*/
    UINT32 uiMainSearch = Hw_Mw_Channel_NoSignal_SearchPort(&(s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN]));
    if ((HV_SUCCESS == uiMainSearch)
    && (POWER_STATE_STANDBY == pstPowerManager->enCurrentPowerState)
    && ((CHANNEL_STATE_NO_SIGNAL == s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enCurrentCHState) 
    || (CHANNEL_STATE_CONFIG == s_stChannelManager.astChannelData[CHANNEL_TYPE_MAIN].enCurrentCHState)))
    {
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

VOID Hv_Mw_Channel_StatusNoSignalToSearch(VOID)
{
    ChannelEvent stChannelEvent = {0};
    stChannelEvent.usEventId = CHANNEL_EVENT_ID_NO_SIGNAL_TO_SEARCH;
    stChannelEvent.usValue =0;
    stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
    HV_ASSERT_SUCCESS_VOID(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
    return;
}
