/**
 * @file hv_mw_SystemManager.c
 * @brief SystemManager source file
 * @details This file provides the following functions: \n
 *          (1) event dispatch \n
 *          (2) system task handle \n
 *          (3) Feed functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-25
 * @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-25   <td>init
 * </table>
*/
#include "hv_comm_DataType.h"
#include "hv_comm_Define.h"
#include "hv_comm_Log.h"
#include "hv_comm_shell_hvconfig.h"
#include "hv_comm_Timer.h"
#include "hv_comm_Assert.h"
#include "hv_comm_DataBase.h"
#include "hv_comm_MemParser.h"

#include "hv_mw_SystemManager.h"
#include "hv_mw_Video.h"
#include "hv_mw_Audio.h"
#include "hv_mw_StateMachine.h"
#include "hv_mw_EventHub.h"
#include "hv_mw_OsdInit.h"
#include "hv_mw_OsdTask.h"
#include "hv_mw_UrgentTask.h"
#ifdef CONFIG_USER_AMBLIGHT_ON
#include "hv_mw_AmbientLight.h"
#endif
#include "hv_mw_PowerManager.h"
#include "hv_mw_PanelManager.h"
#include "hv_mw_Channel_Manager.h"
#include "hv_mw_InputPortManager.h"
#include "hv_mw_Hdmi.h"
#include "hv_mw_Hdcp.h"
#include "hv_mw_DisplayPort.h"
#include "hv_mw_Ddcci.h"
#include "hv_mw_Factory.h"
#if (defined(CONFIG_USER_USB_OTA_ON) || defined(CONFIG_USER_USB_BILLBOARD_ON) || defined(CONFIG_USER_USB_HID_ON))
#include "hv_mw_UsbTask.h"
#endif
#ifdef CONFIG_USER_TYPE_C_ON
#include "hv_mw_TypecTask.h"
#endif
#include "hv_mw_PQ.h"

#include "hv_drv_Mailbox.h"
#include "hv_drv_PLL.h"
#include "hv_drv_Uart.h"
#include "hv_drv_Flash.h"
#include "hv_drv_Watchdog.h"
#include "hv_drv_Pinshare.h"
#include "hv_drv_Physical.h"
#include "hv_drv_Flash.h"
#include "hv_drv_Gpio.h"
#include "hv_drv_Mprt.h"
#include "hv_drv_DpuMainMute.h"
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
#include "hv_drv_DpuSubMute.h"
#endif
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_PLATFORM)
#include "HvPlatform.h"
#endif
#include "hv_app_PQ.h"
#include "hv_app_Ddcci.h"

#include "hv_chip_Config.h"

/*QueueLength 指Message Queue最大存储多少item定义*/
#define SYSTEM_QUEUE_LENGTH             100
#define OSD_QUEUE_LENGTH                100
#define EVENT_HUB_QUEUE_LENGTH          50
#define URGENT_QUEUE_LENGTH             50
#ifdef CONFIG_USER_TYPE_C_ON
#define TYPEC_QUEUE_LENGTH              100
#endif
#if (defined(CONFIG_USER_USB_OTA_ON) || defined(CONFIG_USER_USB_BILLBOARD_ON) || defined(CONFIG_USER_USB_HID_ON))
#define USB_QUEUE_LENGTH                10
#endif

/*任务栈控件大小定义,单位4字节！*/
#define SYSTEM_TASK_STACK_SIZE          2048 /*8K*/
#define OSD_TASK_STACK_SIZE             2048 /*8K*/
#define USB_TASK_STACK_SIZE             2048 /*8K*/
#define TYPEC_TASK_STACK_SIZE           2048 /*8K*/
#define EVENTHUB_TASK_STACK_SIZE        512 /*2K*/
#define AMBIENTLIGHT_TASK_STACK_SIZE    512 /*2K*/
#define URGENT_TASK_STACK_SIZE          512 /*2K*/

/*任务优先级定义,FreeRTOS数值越大代表优先级别越高*/
#define SYSTEM_TASK_PRIORITY            4
#define OSD_TASK_PRIORITY               4
#define EVENTHUB_TASK_PRIORITY          4
#define USB_TASK_PRIORITY               2
#define TYPEC_TASK_PRIORITY             4
#define AMBIENTLIGHT_TASK_PRIORITY      2
#define URGENT_TASK_PRIORITY            6

#ifdef HV_SCALER_DEBUG_VERSION
#define TEST_CLIENT_TASK_STACK_SIZE     512 /*2K*/
#define TEST_CLIENT_TASK_PRIORITY       2
#endif

/*#define configTIMER_TASK_PRIORITY       5*/

#define HV_HDMI0_RX_HPD_INT         BIT_0
#define HV_HDMI1_RX_HPD_INT         BIT_1
#define PQTOOL_SWINT_TRIGGER_VAL    BIT_3

static SystemManager s_stSystemManager;
/****************************inner  function begin*************************************************/
static VOID EventDispatch(const SystemEvent* pstSystemEvent);
static VOID SetDbgSPIDefaultType(UCHAR8 type);

/****************************inner  function begin*************************************************/
Status Hv_Mw_System_Init( VOID )
{
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_System_Init begin!!!");
    HV_VOS_IRQ_T u64Mask = 0;
    Hv_Vos_DisableIrq(&u64Mask);
    Hv_Comm_SetHotfixRegister(HOTFIX_MAIN_BOOT, HOTFIX_BOOT_MAIN);
    HV_ASSERT_SUCCESS(Hv_Drv_Phy_Init());
    Hv_Drv_PLL_Init();
    Hv_Drv_Pinshare_Init();
    Hv_Drv_Flash_ConfigPartFlag();
    Hv_Drv_Sscg_Init();
    Hv_Drv_Eeprom_Init();

    //Hv_Comm_CopyLogoData();
    HV_ASSERT_SUCCESS(Hv_Common_Db_Init());

    /* check the default uart switch */
    if (HV_FALSE == HV_COMMON_DATABASE_GET(FactoryData, bUartEnable))
    {
        Hv_Drv_EnableUart(HV_FALSE);
    }

    /* set dbgspi default type AHB, not AXI */
    SetDbgSPIDefaultType(1);

#ifdef HV_SCALER_DEBUG_VERSION
    HV_SHELL_INIT();
#endif

    HV_ASSERT_SUCCESS(Hv_Mw_Panel_Init());
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_Panel_Init success!!!");

    HV_ASSERT_SUCCESS(Hv_Mw_Power_ManagerInit());
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_Power_ManagerInit success!!!");

    HV_ASSERT_SUCCESS(Hv_Mw_InputPortManager_Init());
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_InputPortManager_Init success!!!");

    HV_ASSERT_SUCCESS(Hv_Mw_Channel_Manager_Init());
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_Channel_Manager_Init success!!!");

    HV_ASSERT_SUCCESS(Hv_App_PQ_DispCtrlInit());
    HV_LOG_DEBUG(SYSTEM, "Hv_App_PQ_DispCtrlInit success!!!");

    HV_ASSERT_SUCCESS(Hv_Mw_Audio_Init());
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_Audio_Init success!!!");

    HV_ASSERT_SUCCESS(Hv_Mw_OsdInit());
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_OsdInit success!!!");

    HV_ASSERT_SUCCESS(Hv_Mw_Ddcci_Init());
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_Ddcci_Init success!!!");
    Hv_App_Ddcci_Init();

#ifdef CONFIG_USER_AMBLIGHT_ON
    Hv_Mw_AmbientLightPwmInit();
#endif

    Hv_Drv_Flash_SetQspiMode(FLASH_STANDARD, FLASH_USE_POLLING);

    HV_LOG_DEBUG(SYSTEM, "Monitor System initial success!");
    return HV_SUCCESS;
}

VOID Hv_Mw_System_TaskCreate( VOID )
{
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_System_TaskCreate begin!!!");
    Hv_Vos_TASK_INIT_PARAMS param = {0};
    param.arg = NULL;

    param.entry = Hv_Mw_System_TaskHandle;
    param.name = "SystemManagerTask";
    param.priority = SYSTEM_TASK_PRIORITY;
    param.stackSize = SYSTEM_TASK_STACK_SIZE;
    Hv_Vos_TaskInit(&param);

    param.entry = Hv_Mw_EventHubTaskHandle;
    param.name = "EventHubTask";
    param.priority = EVENTHUB_TASK_PRIORITY;
    param.stackSize = EVENTHUB_TASK_STACK_SIZE;
    Hv_Vos_TaskInit(&param);

    param.entry = Hv_Mw_OsdTaskHandle;
    param.name = "OsdTask";
    param.priority = OSD_TASK_PRIORITY;
    param.stackSize = OSD_TASK_STACK_SIZE;
    Hv_Vos_TaskInit(&param);

    param.entry = Hv_Mw_Urgent_TaskHandle;
    param.name = "UrgentTask";
    param.priority = URGENT_TASK_PRIORITY;
    param.stackSize = URGENT_TASK_STACK_SIZE;
    s_stSystemManager.xUrgentTaskHandle = Hv_Vos_TaskInit(&param);

#ifdef HV_SCALER_DEBUG_VERSION
    param.entry = Hv_Debug_ShellTaskHandle;
    param.name = "CLITask";
    param.priority = TEST_CLIENT_TASK_PRIORITY;
    param.stackSize = TEST_CLIENT_TASK_STACK_SIZE;
    s_stSystemManager.xShellTaskHandle = Hv_Vos_TaskInit(&param);
#endif
#ifdef CONFIG_USER_AMBLIGHT_ON
    param.entry = Hv_Mw_AmbientLightTaskHandle;
    param.name = "AmbientLightTask";
    param.priority = AMBIENTLIGHT_TASK_PRIORITY;
    param.stackSize = AMBIENTLIGHT_TASK_STACK_SIZE;
    s_stSystemManager.xAmbLightTaskHandle = Hv_Vos_TaskInit(&param);
#endif
#ifdef CONFIG_USER_TYPE_C_ON
    param.entry = Hv_Mw_TypecTaskHandle;
    param.name = "TypecTask";
    param.priority = TYPEC_TASK_PRIORITY;
    param.stackSize = TYPEC_TASK_STACK_SIZE;
    Hv_Vos_TaskInit(&param);      
#endif
#if (defined(CONFIG_USER_USB_OTA_ON) || defined(CONFIG_USER_USB_BILLBOARD_ON) || defined(CONFIG_USER_USB_HID_ON))
    param.entry = Hv_Mw_UsbTaskHandle;
    param.name = "UsbTask";
    param.priority = USB_TASK_PRIORITY;
    param.stackSize = USB_TASK_STACK_SIZE;
    Hv_Vos_TaskInit(&param);      
#endif
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_PLATFORM)
    Hv_User_AddPlatformTask();
#endif
    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_System_TaskCreate end success!!!");
    return;
}

VOID Hv_Mw_System_AllMessageQueueCreate( VOID )
{
    Hv_Vos_QUEUE_INIT_PARAMS stQueueInitParam = {0};

    stQueueInitParam.queueLen = OSD_QUEUE_LENGTH;
    stQueueInitParam.itemSize = sizeof(OsdEvent);
    HV_VOS_QUEUE_S* xOsdQueue = Hv_Vos_QueueInit(&stQueueInitParam);
    HV_ASSERT_VALID_PTR_VOID(xOsdQueue);
    s_stSystemManager.xOsdQueue = xOsdQueue;

    stQueueInitParam.queueLen = SYSTEM_QUEUE_LENGTH;
    stQueueInitParam.itemSize = sizeof(SystemEvent);
    HV_VOS_QUEUE_S* xSystemQueue = Hv_Vos_QueueInit(&stQueueInitParam);
    HV_ASSERT_VALID_PTR_VOID(xSystemQueue);
    s_stSystemManager.xSystemQueue = xSystemQueue;

    stQueueInitParam.queueLen = EVENT_HUB_QUEUE_LENGTH;
    stQueueInitParam.itemSize = sizeof(Event);
    HV_VOS_QUEUE_S* xEventHubQueue = Hv_Vos_QueueInit(&stQueueInitParam);
    HV_ASSERT_VALID_PTR_VOID(xEventHubQueue);
    s_stSystemManager.xEventHubQueue = xEventHubQueue;

    stQueueInitParam.queueLen = URGENT_QUEUE_LENGTH;
    stQueueInitParam.itemSize = sizeof(UrgentEvent);
    HV_VOS_QUEUE_S* xUrgentQueue = Hv_Vos_QueueInit(&stQueueInitParam);
    HV_ASSERT_VALID_PTR_VOID(xUrgentQueue);
    s_stSystemManager.xUrgentQueue = xUrgentQueue;

#ifdef CONFIG_USER_TYPE_C_ON
    stQueueInitParam.queueLen = TYPEC_QUEUE_LENGTH;
    stQueueInitParam.itemSize = sizeof(TypecEvent);
    HV_VOS_QUEUE_S* xTypecQueue = Hv_Vos_QueueInit(&stQueueInitParam);
    HV_ASSERT_VALID_PTR_VOID(xTypecQueue);
    s_stSystemManager.xTypecQueue = xTypecQueue;
#endif

#if (defined(CONFIG_USER_USB_OTA_ON) || defined(CONFIG_USER_USB_BILLBOARD_ON) || defined(CONFIG_USER_USB_HID_ON))
    stQueueInitParam.queueLen = USB_QUEUE_LENGTH;
    stQueueInitParam.itemSize = sizeof(UsbEvent);
    HV_VOS_QUEUE_S* xUsbOtaQueue = Hv_Vos_QueueInit(&stQueueInitParam);
    HV_ASSERT_VALID_PTR_VOID(xUsbOtaQueue);
    s_stSystemManager.xUsbQueue = xUsbOtaQueue;
#endif

    HV_LOG_DEBUG(SYSTEM, "Hv_Mw_System_AllMessageQueueCreate success!!!");
    return;
}

HV_VOS_QUEUE_S* Hv_Mw_System_GetSystemQueue( VOID )
{
    return s_stSystemManager.xSystemQueue;
}

HV_VOS_QUEUE_S* Hv_Mw_System_GetOsdQueue( VOID )
{
    return s_stSystemManager.xOsdQueue;
}

#ifdef CONFIG_USER_TYPE_C_ON
HV_VOS_QUEUE_S* Hv_Mw_System_GetTypecQueue( VOID )
{
    return s_stSystemManager.xTypecQueue;
}
#endif

#if (defined(CONFIG_USER_USB_OTA_ON) || defined(CONFIG_USER_USB_BILLBOARD_ON) || defined(CONFIG_USER_USB_HID_ON))
HV_VOS_QUEUE_S* Hv_Mw_System_GetUsbQueue( VOID )
{
    return s_stSystemManager.xUsbQueue;
}
#endif

HV_VOS_QUEUE_S* Hv_Mw_System_GetEventHubQueue( VOID )
{
    return s_stSystemManager.xEventHubQueue;
}

HV_ATTR_ISR_SECTION HV_VOS_QUEUE_S* Hv_Mw_System_GetUrgentQueue( VOID )
{
    return s_stSystemManager.xUrgentQueue;
}

HV_ATTR_ISR_SECTION HV_VOS_TASK_S* Hv_Mw_System_UrgentTaskHandle( VOID )
{
    return s_stSystemManager.xUrgentTaskHandle;
}

#ifdef HV_SCALER_DEBUG_VERSION
HV_VOS_TASK_S*  Hv_Mw_System_ShellTaskHandle( VOID )
{
    return s_stSystemManager.xShellTaskHandle;
}
#endif

VOID Hv_Mw_System_TaskAndIrqEnable( VOID )
{
    HV_VOS_IRQ_T u64Mask = 0;
        
    HV_LOG_DEBUG(SYSTEM, "Monitor OS Starup!");
    /*使能任务*/
    Hv_Vos_TaskStart();
    
    /*启用中断总开关*/
    Hv_Vos_RestoreIrq(&u64Mask);
    
    return;
}

#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* OSDEventIDConvert(USHORT16 enEventType)
{
    CHAR8* paEventIDType[] =
    {
        "osd brightness",
        "osd contrast",
        "osd sharpness",
        "osd color temp",
        "osd hdr switch",
        "osd aspect ratio",
        "osd pxp config",
        "osd hdmi version",
        "osd dp version",
        "osd main source",
        "osd sub source",
        "osd pxp audio source",
        "osd volume",
        "osd audio time delay",
        "osd freesync switch",
        "osd datapatch reconfig",
        "osd pip sub window position",
        "osd pip sub window size reconfig",
        "osd video auto select source",
        "osd magnify glass switch",
        "osd magnify glass set ratio",
        "osd magnify glass set pos",
        "osd magnify glass set size",
        "osd hue r",
        "osd hue g",
        "osd hue b",
        "osd hue c",
        "osd hue m",
        "osd hue y",
        "osd sat r",
        "osd sat g",
        "osd sat b",
        "osd sat c",
        "osd sat m",
        "osd lum r",
        "osd lum g",
        "osd lum b",
        "osd lum c",
        "osd lum m",
        "osd lum y",
        "osd main or sub source swap",
        "osd video hflip",
        "osd video vflip",
        "osd auto update edid",
        "osd inp pattern",
        "osd main montage"
        "osd main montage",
        "osd over scan",
        "osd bright frame",
        "osd pro esport",
    };
    if(enEventType >= sizeof(paEventIDType) / sizeof(paEventIDType[0]))
    {
        return "NULL";
    }
    else
    {
        return paEventIDType[enEventType];
    }
}
#endif

static VOID OsdCommandEventDispatch(const SystemEvent* pstSystemEvent)
{
    UINT32 uiValue = pstSystemEvent->uiValue;
    SystemEvent stSystemEvent = {0};
    ChannelEvent stChannelEvent = {0};
#ifdef HV_SCALER_DEBUG_VERSION
    if(SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType)
    {
        HV_LOG_INFO(SYSTEM, "System %s,%s,0x%03x", EventTypeConvert(pstSystemEvent->enEventType),TimerEventIDConvert((TIMER_EVENT_E)pstSystemEvent->usEventId), pstSystemEvent->uiValue);
    }
    if(SYSTEM_REV_EVENT_TYPE_OSD_SETTING == pstSystemEvent->enEventType)
    {
        HV_LOG_INFO(SYSTEM, "System %s,%s,0x%03x", EventTypeConvert(pstSystemEvent->enEventType),OSDEventIDConvert(pstSystemEvent->usEventId), pstSystemEvent->uiValue);
    }
#endif
    switch ((SettingParamId)pstSystemEvent->usEventId)
    {
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON    
        case SETTING_PARAM_ID_PXP_CONFIG:
        {
            if (0 == uiValue)/*Pip关闭*/
            {
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_PXP_DISABLE;
                stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
                stChannelEvent.usValue = uiValue;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_SUB_PXP_DISABLE;
                stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
                stChannelEvent.usValue = uiValue;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            }
            else/*PbP打开 PiP打开*/
            {
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_PXP_ENABLE;
                stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
                stChannelEvent.usValue = uiValue;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_PXP_ENABLE;
                stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
                stChannelEvent.usValue = uiValue;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            }
            break;
        }
        case SETTING_PARAM_ID_SUB_SOURCE:
        {
            stChannelEvent.usEventId = CHANNEL_EVENT_ID_RESELECT_VIDEO_SRC;
            stChannelEvent.usValue = uiValue;
            stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
            HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            break;
        }
        case SETTING_PARAM_ID_PIP_SUB_WINDOW_SIZE_RECONFIG:
        {
            /*配置了PIP/PBP场景重新设置PIP/PBP大小需要重新配置SUB 通路*/
            if (1 == HV_COMMON_DATABASE_GET(UserData, ucPxPMode))
            {
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_DATA_PATH_RECONFIG;
                stChannelEvent.usValue = uiValue;
                stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
                HV_LOG_DEBUG(SYSTEM, "receive Sub Dpu datapath reconfig");
            }
            break;
        }
        case SETTING_PARAM_ID_MAIN_OR_SUB_SOURCE_SWAP:
        {
            const ChannelManager* pstChannelManager = Hv_Mw_Channel_GetManager();
            stChannelEvent.usEventId = CHANNEL_EVENT_ID_MAIN_SUB_SOURCE_SWAP;
            stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
            stChannelEvent.usValue = pstChannelManager->astChannelData[1].enChannelSrcLinkPortIndex;
            HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            stChannelEvent.usEventId = CHANNEL_EVENT_ID_MAIN_SUB_SOURCE_SWAP;
            stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
            stChannelEvent.usValue = pstChannelManager->astChannelData[0].enChannelSrcLinkPortIndex;
            HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            break;
        }
        case SETTING_PARAM_ID_MAGNIFY_GLASS_SWITCH:
        {
            if (0 == uiValue)/*放大镜关闭*/
            {
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_SUB_MAGNIFY_DISABLE;
                stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
                stChannelEvent.usValue = uiValue;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            }
            else if (1 == uiValue)
            {
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_MAGNIFY_ENABLE;
                stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
                stChannelEvent.usValue = uiValue;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_MAGNIFY_ENABLE;
                stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
                stChannelEvent.usValue = uiValue;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            }
            else if (3 == uiValue)
            {
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_SUB_MAGNIFY_DISABLE;
                stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
                stChannelEvent.usValue = 0;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
                stChannelEvent.usEventId = CHANNEL_EVENT_ID_MAGNIFY_DISABLE;
                stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;  /*同步刷新率，所以main也发消息*/
                stChannelEvent.usValue = 0;
                HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            }
            break;
        }
#endif
        case SETTING_PARAM_ID_MAIN_SOURCE:
        {
            stChannelEvent.usEventId = CHANNEL_EVENT_ID_RESELECT_VIDEO_SRC;
            stChannelEvent.usValue = uiValue;
            stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
            HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            break;
        }
        
        case SETTING_PARAM_ID_FREE_SYNC_SWITCH:
        {
            /*仅主通道支持FreeSync模式!!!*/
            HV_LOG_DEBUG(SYSTEM, "receive FreeSyncSitch uiValue=%u", uiValue);
            stChannelEvent.usEventId = CHANNEL_EVENT_ID_FREE_SYNC_SWITCH;
            stChannelEvent.usValue = uiValue;/*value unused*/
            stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
            HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent)); 
            break;
        }
        case SETTING_PARAM_ID_HDR_SWITCH:
        {
            stChannelEvent.usEventId = CHANNEL_EVENT_ID_HDR_SWITCH;
            stChannelEvent.usValue = HV_COMMON_DATABASE_GET(UserData, enHdrSwitch);
            stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
            HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            break;
        }
        case SETTING_PARAM_ID_PRO_ESPORT_SWITCH:
        {
            stChannelEvent.usEventId = CHANNEL_EVENT_ID_FREE_SYNC_SWITCH;
            stChannelEvent.usValue = HV_COMMON_DATABASE_GET(UserData, ucProEsportSwitch);
            stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
            HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
            break;
        }
        case SETTING_PARAM_ID_ASPECT_RATIO:
        {
            stChannelEvent.usEventId = CHANNEL_EVENT_ID_SET_ASPECT_RATIO;
            stChannelEvent.usValue = HV_COMMON_DATABASE_GET(UserData, ucProportion);
            stChannelEvent.enChannelType = CHANNEL_TYPE_MAIN;
            HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
            stChannelEvent.enChannelType = CHANNEL_TYPE_SUB;
            HV_ASSERT_PEEK_SUCCESS(Hv_Mw_Channel_SendInnerMsg(&stChannelEvent));
#endif
            break;

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

/** set debug spi default type
 *  @param[in] type 0:dbg_spi2axi; 1:dbg_spi2ahb
 */
static VOID SetDbgSPIDefaultType(UCHAR8 type)
{
    HV_W32_FIELD(SYS_REG_SH5_TOP0_REG_SH5_WDG_FILED0, reg_sh5_dbg_spi_sel, type);
    return;
}

static BOOL IsPowerTimerOutTimer(const SystemEvent* pstSystemEvent)
{
    BOOL bIsTimerEvent = (SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType);
    BOOL bIsPowerTimerEventId = (SYS_EVENT_TIMER_POWR_BEGIN <= pstSystemEvent->usEventId) && (SYS_EVENT_TIMER_POWR_END >= pstSystemEvent->usEventId);
    return  bIsTimerEvent && bIsPowerTimerEventId;
}

static BOOL IsInputPortTimerOutTimer(const SystemEvent* pstSystemEvent)
{
    BOOL bIsTimerEvent = (SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType);
    BOOL bIsInputPortTimerEventId = (SYS_EVENT_TIMER_IP_BEGIN <= pstSystemEvent->usEventId) && (SYS_EVENT_TIMER_IP_END >= pstSystemEvent->usEventId);
    return  bIsTimerEvent && bIsInputPortTimerEventId;
}

static BOOL IsChanelTimerOutTimer(const SystemEvent* pstSystemEvent)
{
    BOOL bIsTimerEvent = (SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType);
    BOOL bIsChannelTimerEventId = (SYS_EVENT_TIMER_CHANNEL_BEGIN <= pstSystemEvent->usEventId) && (SYS_EVENT_TIMER_CHANNEL_TIMER_END >= pstSystemEvent->usEventId);
    return  bIsTimerEvent && bIsChannelTimerEventId;
}

static BOOL IsPanelTimerOutTimer(const SystemEvent* pstSystemEvent)
{
    BOOL bIsTimerEvent = (SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType);
    BOOL bIsPanelTimerEventId = (SYS_EVENT_TIMER_PANEL_BEGIN <= pstSystemEvent->usEventId) && (SYS_EVENT_TIMER_PANEL_END >= pstSystemEvent->usEventId);
    return  bIsTimerEvent && bIsPanelTimerEventId;
}


static VOID EventDispatch(const SystemEvent* pstSystemEvent)
{
    if ((SYSTEM_REV_EVENT_TYPE_POWER == pstSystemEvent->enEventType) || IsPowerTimerOutTimer(pstSystemEvent))
    {
        HV_ASSERT_PEEK_SUCCESS_VOID(Hv_Mw_Power_SystemQueueMsgProc(pstSystemEvent));
    }
    else if ((SYSTEM_REV_EVENT_TYPE_INPUTPORT == pstSystemEvent->enEventType) || IsInputPortTimerOutTimer(pstSystemEvent))
    {
        HV_ASSERT_PEEK_SUCCESS_VOID(Hv_Mw_InputPort_ProcSystemQueueMsg(pstSystemEvent));
    }
    else if (SYSTEM_REV_EVENT_TYPE_OSD_SETTING == pstSystemEvent->enEventType)
    {
        OsdCommandEventDispatch(pstSystemEvent);
    }    
    else if ((SYSTEM_REV_EVENT_TYPE_PANEL == pstSystemEvent->enEventType) || IsPanelTimerOutTimer(pstSystemEvent))
    {
        HV_ASSERT_PEEK_SUCCESS_VOID(Hv_Mw_Panel_ProcSystemQueueMsg(pstSystemEvent));
    }
    else if ((SYSTEM_REV_EVENT_TYPE_CHANNEL == pstSystemEvent->enEventType) || IsChanelTimerOutTimer(pstSystemEvent))
    {
        HV_ASSERT_PEEK_SUCCESS_VOID(Hv_Mw_Channel_ProcSystemQueueMsg(pstSystemEvent));
    }
    else if (SYSTEM_REV_EVENT_TYPE_DDCCI == pstSystemEvent->enEventType)
    {
        HV_ASSERT_PEEK_SUCCESS_VOID(Hv_Mw_Ddcci_ProcSystemQueueMsg(pstSystemEvent));
    }
    else
    {
        /*Do notihng*/
    }

    if (Hv_Mw_Panel_HasInnerMsgs())
    {
        HV_ASSERT_PEEK_SUCCESS_VOID(Hv_Mw_Panel_ProcInnerMsgs());
    }

    if (Hv_Mw_InputPort_HasInnerMsgs())
    {
        HV_ASSERT_PEEK_SUCCESS_VOID(Hv_Mw_InputPort_ProcInnerMsgs());
    }

    if (Hv_Mw_Ddcci_HasInnerMsgs())
    {
        HV_ASSERT_PEEK_SUCCESS_VOID(Hv_Mw_Ddcci_ProcInnerMsgs());
    }

    if (Hv_Mw_Channel_HasInnerMsgs())
    {
        HV_ASSERT_PEEK_SUCCESS_VOID(Hv_Mw_Channel_ProcInnerMsgs());
    }

    if ((SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType)
    && (SYS_EVENT_TIMER_DATABASE_SYNC_TIMER == pstSystemEvent->usEventId))
    {
        Hv_Mw_Factory_SavePanelOnCountTime(HV_FALSE);

        /*业务流程均处理完成后周期检查database中数据是否改变，改变则同步到flash/eeprom*/
        Hv_Mw_DataBase_Sync();
        Hv_Drv_WDG_Feed(DATABASE_PERIOD_SYNC_GLOBAL_TO_FLASH_TIMER_LENGTH * 3);
    }

#if (HV_PROJECT_CONFIG_SMART_POWER == HV_CONFIG_ON)
    if ((SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType)
    && (EVENT_POWER_LOAD_CHECK_TIMER == pstSystemEvent->usEventId))
    {
        static UCHAR8 ucSwitch_Pre = SDR_TYPE;
        UCHAR8 ucSwitch = SDR_TYPE;
        UCHAR8 ucBrightness =  HV_COMMON_DATABASE_GET(UserData, ucBrightness);
        USHORT16 usPower = 0;
        const ChannelManager *pstChannelManager = Hv_Mw_Channel_GetManager();
        ucSwitch = pstChannelManager->astChannelData[0].stVideoConfigParams.stHdrParam.xType;

        HV_LOG_INFO(SYSTEM, "check loadpower HDR = %d, ucBrightness = %d", ucSwitch, ucBrightness);
        /*只有在SDR下才读取USB负载大小*/
        if (ucSwitch == SDR_TYPE)
        {
            ucSwitch_Pre = ucSwitch;

            /*周期性亮度大于70， 需要更新PD供电能力*/
            if (ucBrightness > 70)
            {
                Hv_Mw_Typec_UpdateHighPower(0);
            }
            else
            {
                Hv_Mw_Typec_UpdateHighPower(1);
            }
        }
        else if (ucSwitch_Pre != ucSwitch)
        {
            ucSwitch_Pre = ucSwitch;
            Hv_Mw_Typec_UpdateHighPower(0);
        }
    }
#endif
    return;
}

static VOID DatabaseSyncTimerStart( VOID )
{
    static HV_TIMER_INIT_PARAMS stSystemDatabaseSyncTimerParam = \
    {"SystemDatabaseSyncTimer", DATABASE_PERIOD_SYNC_GLOBAL_TO_FLASH_TIMER_LENGTH, HV_TRUE, &stSystemDatabaseSyncTimerParam, Hv_Common_Timer_DispatchEvent, SYS_EVENT_TIMER_DATABASE_SYNC_TIMER};

    s_stSystemManager.pstDatabaseSyncTimer = Hv_Vos_Timer_Create(&stSystemDatabaseSyncTimerParam);
    HV_ASSERT_VALID_PTR_VOID(s_stSystemManager.pstDatabaseSyncTimer);

    Hv_Drv_WDG_Feed(DATABASE_PERIOD_SYNC_GLOBAL_TO_FLASH_TIMER_LENGTH * 2);
    Hv_Drv_WDG_Enable();

    Hv_Vos_Timer_Start(s_stSystemManager.pstDatabaseSyncTimer);
    return;
}

#if (HV_PROJECT_CONFIG_SMART_POWER == HV_CONFIG_ON)
static VOID PowerLoadCheckTimerStart( VOID )
{
    static HV_TIMER_INIT_PARAMS stPowerLoadCheckTimerParam = \
    {"PowerLoadCheckTimer", 5000, HV_TRUE, &stPowerLoadCheckTimerParam, Hv_Common_Timer_DispatchEvent, EVENT_POWER_LOAD_CHECK_TIMER};

    s_stSystemManager.pstPowerLoadCheckTimer = Hv_Vos_Timer_Create(&stPowerLoadCheckTimerParam);
    HV_ASSERT_VALID_PTR_VOID(s_stSystemManager.pstPowerLoadCheckTimer);

    Hv_Vos_Timer_Start(s_stSystemManager.pstPowerLoadCheckTimer);
    return;
}
#endif

HV_VOS_ISR_RESULT_E Hv_Mw_System_SwIntIsrHandle(UINT32 uiIrqNum, VOID *arg)
{
    SystemEvent stSysEvent;
    HV_VOS_QUEUE_S* xSystembQueue = Hv_Mw_System_GetSystemQueue();
    HV_ASSERT_VALID_PTR_RET_NO_LOG(xSystembQueue, HV_VOS_ISR_HANDLED);

    UINT32 uiSwintStatus = Hv_Drv_Mailbox_GetSwIntStatus();

    /*Notice: Clear interrupt should use irq - HV_CHIP_IRQ_BASE. We should modify this api.*/
    Hv_Vos_WClrMiscInt(uiIrqNum - HV_CHIP_IRQ_BASE);

    Hv_Drv_Mailbox_ClearSwIntStatus(uiSwintStatus);
    
    if(PQTOOL_SWINT_TRIGGER_VAL & uiSwintStatus)
    {
        stSysEvent.enEventType = SYSTEM_REV_EVENT_TYPE_DDCCI;
        stSysEvent.ucPortIndex = DDCCI_PORT_PQTOOL;
        stSysEvent.uiValue = Hv_Drv_Mailbox_GetPQToolCmdPort();
        Hv_Vos_QueueSendFromISR(xSystembQueue, (void *)&stSysEvent);
    }

    if(HV_HDMI0_RX_HPD_INT & uiSwintStatus)
    {
        HV_Drv_HdmirRx_ResetScdcWith5V(0);
        Hv_Mw_HdmiRx_CableDetCheck(0);
    }

    if(HV_HDMI1_RX_HPD_INT & uiSwintStatus)
    {
        HV_Drv_HdmirRx_ResetScdcWith5V(1);
        Hv_Mw_HdmiRx_CableDetCheck(1);
    }

    return HV_VOS_ISR_HANDLED;
}

VOID Hv_Mw_System_SwIntIRQInit()
{
    //Register sw int handler for pq tool protocol.
    Hv_Vos_AttachIsr(HV_CHIP_IRQ_PM51, Hv_Mw_System_SwIntIsrHandle, NULL);
    Hv_Vos_UnmaskIrq(HV_CHIP_IRQ_PM51);
}

VOID Hv_Mw_System_Task_Init(VOID)
{
    Hv_Mw_System_SwIntIRQInit();
    /*Audio timer start*/
    Hv_Mw_Audio_StartSoundDelayTimer();
    /*Database period timer creat and start*/
    DatabaseSyncTimerStart();
#if (HV_PROJECT_CONFIG_SMART_POWER == HV_CONFIG_ON)
    PowerLoadCheckTimerStart();
#endif
    if (HV_TRUE == HV_COMMON_DATABASE_GET(SystemData, bFactoryMode))
    {
        Hv_Mw_FactoryModeToPm(HV_TRUE);
    }
    return;
}

VOID Hv_Mw_System_TaskHandle( VOID *arg )
{
    HV_ASSERT_VALID_PTR_VOID(s_stSystemManager.xSystemQueue);
    SystemEvent stSystemEvent = {0};

    Hv_Mw_System_Task_Init();
    for (;;)
    {
        #ifdef SW_DUMMY_DEBUG
        HV_WT32(SW_DUMMY_SM_TASK, (HV_RD32(SW_DUMMY_SM_TASK)+1));
        #endif
        if (Hv_Vos_QueueRecv(s_stSystemManager.xSystemQueue, (VOID*)&stSystemEvent))
        {
            EventDispatch(&stSystemEvent);
        }
        Hv_Vos_TaskYield();
    }
    return;
}

VOID Hv_Mw_System_SetDatabaseSyncTimerEnable(BOOL bEn)
{
    if(NULL != s_stSystemManager.pstDatabaseSyncTimer)
    {
        if(bEn)
        {
            Hv_Vos_Timer_Rstart(s_stSystemManager.pstDatabaseSyncTimer, DATABASE_PERIOD_SYNC_GLOBAL_TO_FLASH_TIMER_LENGTH);
        }
        else
        {
            Hv_Vos_Timer_Rstop(s_stSystemManager.pstDatabaseSyncTimer);
#ifdef CONFIG_USER_WATCHDOG_ON
            Hv_Drv_WDG_Disable();
#endif            
        }
    }
    return;
}

