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

/*-----------------------------------------------------------------------------
 *
 * $Author: dtvbm11 $
 * $Date: 2015/11/10 $
 * $RCSfile: drv_resume.c,v $
 * $Revision: #1 $
 *
 *---------------------------------------------------------------------------*/

/** @file drv_resume.c
 *  This file implements for full driver resume.
 */
#include <linux/kernel.h> 
#include <linux/module.h>
#include <linux/opm_device.h>

#if defined(CC_SUPPORT_STR)

//panel                 
#include "nptv_if.h"    
#include "drv_vdoclk.h" 
#include "drv_display.h"
#include "drv_video.h"  

#include "x_mid.h"
#include "hw_hdmi.h"
#include "hw_lvds.h"
#include "hw_mempll.h"
#include "hw_cpupll.h"
#include "hw_ifpll.h"
#include "hw_pll_group.h"

extern void vDrvODSuspend(void);
extern void vDrvODResume(void);
extern void vDrvMIBSuspend(void);
extern void vDrvMIBResume(void);
extern void vDrvScposSuspend(void);
extern void vDrvScposResume(void);
extern void AUD_pm_str_suspend(void);
extern void AUD_pm_str_resume(void);
#ifdef CC_SUPPORT_VENC
extern void VENC_pm_str_suspend(void);
extern void VENC_pm_str_resume(void);
#endif
extern void OSD_pm_suspend(void);
extern void OSD_pm_resume(void);
extern void GCPU_pm_str_suspend(void);
extern void GCPU_pm_str_resume(void);
extern void GFX_pm_suspend(void);
extern void GFX_pm_resume(void);
extern void DMX_pm_str_suspend(void);
extern void DMX_pm_str_resume(void);
extern void CHIP_CPU_Resume(void);
extern void CHIP_CPU_Suspend(void);
extern void VDEC_pm_str_suspend(void);
extern void VDEC_pm_str_resume(void);
extern void Image_pm_str_suspend(void);
extern void Image_pm_str_resume(void);
extern void Imgrz_pm_str_suspend(void);
extern void Imgrz_pm_str_resume(void);
extern void B2R_pm_str_suspend(void);
extern void B2R_pm_str_resume(void);
extern void SIF_pm_str_suspend(void);
extern void SIF_pm_str_resume(void);
extern void PWM_pm_str_suspend(void);
extern void PWM_pm_str_resume(void);
extern void vDrvPostprocSuspend(void);
extern void vDrvLcDimPQSuspend(void);
extern void vDrvLcdimSpiSuspend(void);
extern void vDrvPostprocResume(void);
extern void vDrvLcDimPQResume(void);
extern void vDrvLcdimSpiResume(void);
extern void TVD_pm_resume(void);
extern void TVD_pm_suspend(void);
extern void ATD_pm_str_resume(void);
extern void ATD_pm_str_suspend(void);
extern void VBI_pm_resume(void);
extern void VBI_pm_suspend(void);
extern void TVE_pm_resume(void);
extern void TVE_pm_suspend(void);
EXTERN void    PCMCIA_pm_str_suspend(void);
EXTERN void    PCMCIA_pm_str_resume(void);
extern void HDMI_pm_suspend(void);
extern void HDMI_pm_resume(void);
extern void ADC_pm_resume(void);
extern void vDrvMJCResume(void);
extern void vDrvMJCSuspend(void);

//LVDS
extern void vDrvLVDSSuspend(void);
extern void vDrvLVDSResume(void);
extern void vDrvVOPLLSuspend(void);
extern void vDrvVOPLLResume(void);

extern BOOL MID_EnableRegionReadProtect(UINT32 u4Region, BOOL onoff);

extern void vDrvDisplayInit_pm_resume(void);

extern void PDWNC_EnterSuspend(void);
extern void PDWNC_Resume(void);
extern void PDWNC_SetSuspendMode(void);
extern void PDWNC_SetResumeMode(void);

 static int __devinit _mt53xx_STR_probe(struct opm_device *pdev)
{
	printk("_mt53xx_STR_probe\n");
	return 0;
}

static int __devexit _mt53xx_STR_remove(struct opm_device *pdev)
{
	printk("_mt53xx_STR_remove\n");
	return 0;	
}

#define ENABLE_JTAG_TO_DEBUG
#ifdef ENABLE_JTAG_TO_DEBUG
INT32 CLI_Parser(const CHAR *szCmdBuf);
#endif
#define DEBUG_FUNCTION_CALL(x)\
    do{\
	printk(#x"\n");\
	x;\
    } while (0)
extern void mt5396_register_mid_function(unsigned int (*func)(unsigned int));
static int _mt53xx_STR_suspend(struct opm_device *pdev, pm_message_t state)
{
    printk("_mt53xx_STR_suspend\n");
    PDWNC_SetSuspendMode();

#ifdef ENABLE_JTAG_TO_DEBUG
    CLI_Parser("b.jtag 1");
#endif
    DEBUG_FUNCTION_CALL(vDrvLVDSSuspend());
    DEBUG_FUNCTION_CALL(bApiVideoMainSubSrc(0xff, 0xfe));
    DEBUG_FUNCTION_CALL(bApiVideoMainSubSrc(0xfe, 0xff));
    DEBUG_FUNCTION_CALL(vDrvVOPLLSuspend());
    //DEBUG_FUNCTION_CALL(Tuner_pm_str_suspend());
    DEBUG_FUNCTION_CALL(vDrvODSuspend());
    DEBUG_FUNCTION_CALL(vDrvMJCSuspend());
    DEBUG_FUNCTION_CALL(vDrvMIBSuspend());
    DEBUG_FUNCTION_CALL(vDrvPostprocSuspend());
    DEBUG_FUNCTION_CALL(vDrvLcDimPQSuspend());
    DEBUG_FUNCTION_CALL(vDrvLcdimSpiSuspend()); 
    DEBUG_FUNCTION_CALL(AUD_pm_str_suspend());
    DEBUG_FUNCTION_CALL(OSD_pm_suspend());
    DEBUG_FUNCTION_CALL(GFX_pm_suspend());
    DEBUG_FUNCTION_CALL(GCPU_pm_str_suspend());
    DEBUG_FUNCTION_CALL(DMX_pm_str_suspend());
    DEBUG_FUNCTION_CALL(VDEC_pm_str_suspend());
    DEBUG_FUNCTION_CALL(Image_pm_str_suspend());
    DEBUG_FUNCTION_CALL(Imgrz_pm_str_suspend());
    DEBUG_FUNCTION_CALL(TVD_pm_suspend());
    DEBUG_FUNCTION_CALL(ATD_pm_str_suspend());
    DEBUG_FUNCTION_CALL(VBI_pm_suspend());
    DEBUG_FUNCTION_CALL(TVE_pm_suspend());
    DEBUG_FUNCTION_CALL(B2R_pm_str_suspend());
    DEBUG_FUNCTION_CALL(PCMCIA_pm_str_suspend());
    DEBUG_FUNCTION_CALL(HDMI_pm_suspend());
    DEBUG_FUNCTION_CALL(SIF_pm_str_suspend());
    DEBUG_FUNCTION_CALL(PWM_pm_str_suspend());
    DEBUG_FUNCTION_CALL(vDrvScposSuspend());
    PDWNC_EnterSuspend();  

    mt5396_register_mid_function(MID_WarmBootRegionProtect);
#if 0
    MID_WarmBootRegionProtect(TRUE);
#endif
        
	return 0;
}

extern void vDrvVideoMuteColor(UINT32 u4VdpId, UINT32 u4MuteColor);
static int _mt53xx_STR_resume(struct opm_device *pdev)
{
    printk("_mt53xx_STR_resume\n");
#if 0
    MID_WarmBootRegionProtect(FALSE);
#endif
    PDWNC_SetResumeMode();

#if 1//tmp close
    DEBUG_FUNCTION_CALL(vDrvScposResume());
    DEBUG_FUNCTION_CALL(vDrvVOPLLResume());
    DEBUG_FUNCTION_CALL(vDrvODResume());
    DEBUG_FUNCTION_CALL(vDrvMJCResume());
    DEBUG_FUNCTION_CALL(vDrvMIBResume());
    DEBUG_FUNCTION_CALL(vDrvLcDimPQResume());
    DEBUG_FUNCTION_CALL(vDrvLcdimSpiResume());        
    DEBUG_FUNCTION_CALL(vDrvPostprocResume());
    DEBUG_FUNCTION_CALL(AUD_pm_str_resume());
    DEBUG_FUNCTION_CALL(OSD_pm_resume());
    DEBUG_FUNCTION_CALL(GFX_pm_resume());
    DEBUG_FUNCTION_CALL(GCPU_pm_str_resume());
    DEBUG_FUNCTION_CALL(DMX_pm_str_resume());
    DEBUG_FUNCTION_CALL(VDEC_pm_str_resume());
    DEBUG_FUNCTION_CALL(Image_pm_str_resume());
    DEBUG_FUNCTION_CALL(Imgrz_pm_str_resume());
    DEBUG_FUNCTION_CALL(TVD_pm_resume());
    DEBUG_FUNCTION_CALL(SIF_pm_str_resume());
    DEBUG_FUNCTION_CALL(ATD_pm_str_resume());
    //DEBUG_FUNCTION_CALL(Tuner_pm_str_resume());
    DEBUG_FUNCTION_CALL(VBI_pm_resume());
    DEBUG_FUNCTION_CALL(TVE_pm_resume());
    DEBUG_FUNCTION_CALL(B2R_pm_str_resume());
    DEBUG_FUNCTION_CALL(PCMCIA_pm_str_resume());
    DEBUG_FUNCTION_CALL(HDMI_pm_resume());
    DEBUG_FUNCTION_CALL(PWM_pm_str_resume());

    DEBUG_FUNCTION_CALL(vDrvDisplayInit_pm_resume());
    DEBUG_FUNCTION_CALL(ADC_pm_resume());// please put it after the one who call VOPLL_pm_resume();
    DEBUG_FUNCTION_CALL(vDrvLVDSResume());
    //vDrvVideoMuteColor(SV_VP_MAIN, 0);
#else
    vApiPanelPowerSequence(TRUE); //tmp
#endif
    // send a fake power key
    PDWNC_Resume();
        
    return 0;
}

#if 0
static struct platform_driver _mt53xx_STR_driver =
{
	.probe          = _mt53xx_STR_probe,
	.remove         = _mt53xx_STR_remove,
	.suspend        = _mt53xx_STR_suspend,
	.resume         = _mt53xx_STR_resume,
	.driver		= {
	        .name	= "mt53xx_STR",
		.owner	= THIS_MODULE,
	},
};

static struct platform_device _mt53xx_STR_device = {
	.name			= "mt53xx_STR",
	.id			= 0
};

int  mt53xx_STR_init(void)
{
	printk("mt53xx_STR_init\n");
	platform_device_register(&_mt53xx_STR_device);    
	return platform_driver_register(&_mt53xx_STR_driver);
}
#endif

#if 1 // def CONFIG_OPM
#include <linux/opm_device.h>
#include <linux/err.h>

extern void PDWNC_Reboot(void);
static int opmcls_reboot;
void opmcls_shutdown(struct opm_device *devptr)
{
	printk("opmcls_shutdown\n");
	if(opmcls_reboot)
		PDWNC_Reboot();
}

static struct opm_driver opmcls_driver_reboot = {
	.shutdown	= opmcls_shutdown,
	.driver		= {
		.name	= "opm_sysclass"
	},
};

static struct opm_device *device;

static struct opm_driver _mt53xx_STR_driver = {
	.probe		= _mt53xx_STR_probe,
	.remove		= _mt53xx_STR_remove,
	.suspend        = _mt53xx_STR_suspend,
	.resume         = _mt53xx_STR_resume,
	.driver		= {
		.name	= "mt53xx_STR",
		.owner	= THIS_MODULE,
	},
};
static struct opm_device *device;

int  mt53xx_STR_init(void)
{
	int err;

	if ((err = opm_driver_register(&_mt53xx_STR_driver)) < 0)
		return err;
	if ((err = opm_driver_register(&opmcls_driver_reboot)) < 0)
		return err;
	device = opm_device_register_simple("mt53xx_STR",0,ORDER_IGNORE);
	if (IS_ERR(device))
		return -ENODEV;						 
	return 0;
}
#endif

#endif
