/* 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: brianpc.huang $
 * $Date: 2015/05/29 $
 * $RCSfile: sif_if.h,v $
 * $Revision: #1 $
 *
 *---------------------------------------------------------------------------*/


/** @file sif_if.h
 *  This file describes SIF module exported functions, error code and definitions.
 */

#ifndef SIF_IF_H
#define SIF_IF_H


//---------------------------------------------------------------------------
// Include files
//---------------------------------------------------------------------------
#include "drvcust_if.h"

#include "x_os.h"
#include "x_typedef.h"


//---------------------------------------------------------------------------
// Constant definitions
//---------------------------------------------------------------------------
//#define SIF_CHECK_SDA_LOW

//---------------------------------------------------------------------------
// Type definitions
//---------------------------------------------------------------------------
typedef enum {
    SIF_BUS_SYSTEM_I2C = 0,
    SIF_BUS_TUNER_I2C  = 1,
    SIF_BUS_SECOND_I2C = 2,
    SIF_BUS_PDWNC_I2C  = 3,
    SIF_BUS_PDWNC_I2C_1 = 4,
    SIF_BUS_SECURE_I2C = 5,
    SIF_BUS_MAX
} SIF_BUS_ID_T;

typedef enum
{
    SIF_ERROR_NODEV       = -1,       // SIF device doesn't ack to SIF master
    SIF_ERROR_SUBADDR     = -2,       // There is error when SIF master transmits subaddress data
    SIF_ERROR_DATA        = -3,       // There is error when SIF master transmits/receives data
    SIF_ERROR_BUS_BUSY    = -4,       // SIF bus is busy, can't access
    SIF_ERROR_PARAM       = -5,       // Function parameter is invalid
    SIF_ERROR_TIMEOUT     = -6,       // SIF semaphore timeout
} SIF_ERROR_T;

/* function pointer type */
typedef VOID (*SIF_ASYNC_NFY_FCT)(VOID *pvNfyData, UINT16 u2Result);

typedef enum
{
    SIF_ASYNC_REQ_READ   =  0,  
    SIF_ASYNC_REQ_WRITE   =  1,  
} SIF_ASYNC_REQ_TYPE_T;

#ifdef SIF_CHECK_SDA_LOW
typedef struct _SIF_BUS_STATUS_
{
    UINT8 SIF_BUS_SDA;
    UINT8 SIF_BUS_SCL;
} SIF_BUS_STATUS_T;
#endif

typedef struct
{
    UINT8 u1RequestType;      /* SIF_ASYNC_REQ_READ or  SIF_ASYNC_REQ_WRITE */
    UINT8 u1CHannelID;      /* SIF bus ID */
    UINT16 u2ClkDiv;      /* Parameter of divider to divide 27Mhz for SCL */
    UINT8 u1DevAddr;      /* SIF device address */
    UINT8 u1WordAddrNum;      /* SIF word address length */
    UINT32 u4WordAddr;      /* SIF word address. Format XX B2 B1 B0. B2 is sent on SIF bus first */
    UINT8 *pu1Buf;      /* Pointer to user's buffer */
    UINT16 u2ByteCnt;      /* Number of byte to transfer. Max = 256 bytes */
    SIF_ASYNC_NFY_FCT pfnNfy;      /* callback function pointer */
    VOID *pvNfyData;      /* callback function parameter */
} SIF_ASYNC_REQ_T;
	
typedef struct _SIF_OPERATIONS_T 
{  
    VOID (*pfn_Init)(VOID);
    VOID (*pfn_Stop)(VOID);    
    UINT16 (*pfn_X_Read)(UINT8, UINT16, UINT8, UINT8, UINT32, UINT8*, UINT16);
	UINT16 (*pfn_X_Sp_Read)(UINT8, UINT16, UINT8, UINT8, UINT32, UINT8*, UINT16);
    UINT16 (*pfn_X_Write)(UINT8, UINT16, UINT8, UINT8, UINT32, UINT8*, UINT16);
    VOID (*pfn_ISRHandler)(UINT16);
} SIF_OPERATIONS_T;

typedef struct _SIF_STRUCT_T 
{
    UINT8 u1SifMaster;
    SIF_OPERATIONS_T rSifOps;
} SIF_STRUCT_T;


//---------------------------------------------------------------------------
// Inter-file functions
//---------------------------------------------------------------------------
EXTERN INT32 _SIF_Diag(VOID);


//---------------------------------------------------------------------------
// Public functions
//---------------------------------------------------------------------------
/** SIF_Init
 *  Initialize SIF module.
 *  @param   VOID
 *  @return  VOID
 */
EXTERN VOID SIF_Init(VOID);


/** SIF_Stop
 *  Terminate SIF module.
 *  @param   VOID
 *  @return  VOID
 */
EXTERN VOID SIF_Stop(VOID);


/** SIF_Read
 *  Read data with word address from SIF module from SIF_BUS_SYSTEM_I2C.
 *  @param  u2ClkDiv    Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr   Serial interface device address.
 *  @param  u1WordAddr  Serial interface word address.
 *  @param  pu1Buf      Pointer to user's buffer.
 *  @param  u2ByteCnt   Number of byte to read. Max = 256 bytes.
 *  @retval > 0         Actual number of bytes read.
 *  @retval = 0         Error
 */
EXTERN UINT16 SIF_Read(UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddr,
                       UINT8 *pu1Buf, UINT16 u2ByteCnt);


/** SIF_ReadNoSubAddr
 *  Read data without word address from SIF module from SIF_BUS_SYSTEM_I2C.
 *  @param  u2ClkDiv    Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr   Serial interface device address.
 *  @param  pu1Buf      Pointer to user's buffer.
 *  @param  u2ByteCnt   Number of byte to read. Max = 256 bytes.
 *  @retval > 0         Actual number of bytes read.
 *  @retval = 0         Error
 */
EXTERN UINT16 SIF_ReadNoSubAddr(UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 *pu1Buf,
                                UINT16 u2ByteCnt);


/** SIF_TunerReadNoSubAddr
 *  NIM module api: read data without word address from SIF module from SIF_BUS_TUNER_I2C.
 *  @param  u2ClkDiv    Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr   Serial interface device address.
 *  @param  pu1Buf      Pointer to user's buffer.
 *  @param  u2ByteCnt   Number of byte to read. Max = 256 bytes.
 *  @retval > 0         Actual number of bytes read.
 *  @retval = 0         Error
 */
EXTERN UINT16 SIF_TunerReadNoSubAddr(UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 *pu1Buf,
                                     UINT16 u2ByteCnt);


/** SIF_Write
 *  Write data with word address to SIF module on SIF_BUS_SYSTEM_I2C.
 *  @param  u2ClkDiv    Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr   Serial interface device address.
 *  @param  u1WordAddr  Serial interface word address.
 *  @param  pu1Buf      Pointer to user's buffer.
 *  @param  u2ByteCnt   Number of byte to write. Max = 256 bytes.
 *  @retval > 0         Actual number of bytes written.
 *  @retval = 0         Error
 */
EXTERN UINT16 SIF_Write(UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddr,
                        UINT8 *pu1Buf, UINT16 u2ByteCnt);


/** SIF_WriteNoSubAddr
 *  Write data without word address to SIF module on SIF_BUS_SYSTEM_I2C.
 *  @param  u2ClkDiv    Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr   Serial interface device address.
 *  @param  pu1Buf      Pointer to user's buffer.
 *  @param  u2ByteCnt   Number of byte to write. Max = 256 bytes.
 *  @retval > 0         Actual number of bytes written.
 *  @retval = 0         Error
 */
EXTERN UINT16 SIF_WriteNoSubAddr(UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 *pu1Buf,
                                 UINT16 u2ByteCnt);


/** SIF_TunerWriteNoSubAddr
 *  NIM module api: write data without word address to SIF module on SIF_BUS_TUNER_I2C.
 *  @param  u2ClkDiv    Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr   Serial interface device address.
 *  @param  pu1Buf      Pointer to user's buffer.
 *  @param  u2ByteCnt   Number of byte to write. Max = 256 bytes.
 *  @retval > 0         Actual number of bytes written.
 *  @retval = 0         Error
 */
EXTERN UINT16 SIF_TunerWriteNoSubAddr(UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 *pu1Buf,
                                      UINT16 u2ByteCnt);


/** SIF_ReadMultipleSubAddress
 *  Read data with word address, of which length up to three, from SIF module from SIF_BUS_SYSTEM_I2C.
 *  @param  u2ClkDiv        Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr       Serial interface device address.
 *  @param  u1WordAddrNum   Serial interface word address length.
 *  @param  u4WordAddr      Serial interface word address. Format XX B2 B1 B0. B2 is sent on SIF bus first.
 *  @param  pu1Buf          Pointer to user's buffer.
 *  @param  u2ByteCnt       Number of byte to read. Max = 256 bytes.
 *  @retval > 0             Actual number of bytes read.
 *  @retval = 0             Error
 */
EXTERN UINT16 SIF_ReadMultipleSubAddr(UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddrNum, UINT32 u4WordAddr,
                                      UINT8 *pu1Buf, UINT16 u2ByteCnt);


/** SIF_WriteMultipleSubAddress
 *  Write data with word address, of which length up to three, to SIF module on SIF_BUS_SYSTEM_I2C.
 *  @param  u2ClkDiv        Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr       Serial interface device address.
 *  @param  u1WordAddrNum   Serial interface word address length.
 *  @param  u4WordAddr      Serial interface word address. Format XX B2 B1 B0. B2 is sent on SIF bus first.
 *  @param  pu1Buf          Pointer to user's buffer.
 *  @param  u2ByteCnt       Number of byte to read. Max = 256 bytes.
 *  @retval > 0             Actual number of bytes written.
 *  @retval = 0             Error
 */
EXTERN UINT16 SIF_WriteMultipleSubAddr(UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddrNum, UINT32 u4WordAddr,
                                       UINT8 *pu1Buf, UINT16 u2ByteCnt);

#ifdef CONFIG_I2C_MT53XX
/** SIF_Xfer_Read
 *  Read data with channel ID, word address, of which length up to three, from SIF module.
 *  @param  u1ChannelID     SIF bus ID.
 *  @param  u2ClkDiv        Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr       Serial interface device address.
 *  @param  u1WordAddrNum   Serial interface word address length.
 *  @param  u4WordAddr      Serial interface word address. Format XX B2 B1 B0. B2 is sent on SIF bus first.
 *  @param  pu1Buf          Pointer to user's buffer.
 *  @param  u2ByteCnt       Number of byte to read. Max = 256 bytes.
 *  @retval > 0             Actual number of bytes read.
 *  @retval = 0             Error
 */
UINT16 SIF_Xfer_Read(UINT8 u1CHannelID, UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddrNum, UINT32 u4WordAddr,
                  UINT8* pu1Buf, UINT16 u2ByteCnt);
/** SIF_Xfer_Write
 *  Write data with channel ID, word address, of which length up to three, to SIF module.
 *  @param  u1ChannelID     SIF bus ID.
 *  @param  u2ClkDiv        Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr       Serial interface device address.
 *  @param  u1WordAddrNum   Serial interface word address length.
 *  @param  u4WordAddr      Serial interface word address. Format XX B2 B1 B0. B2 is sent on SIF bus first.
 *  @param  pu1Buf          Pointer to user's buffer.
 *  @param  u2ByteCnt       Number of byte to write. Max = 256 bytes.
 *  @retval > 0             Actual number of bytes written.
 *  @retval = 0             Error
 */
UINT16 SIF_Xfer_Write(UINT8 u1CHannelID, UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddrNum, UINT32 u4WordAddr,
                   UINT8* pu1Buf, UINT16 u2ByteCnt);

BOOL SIF_IS_SUSPENDED(UINT8 u1CHannelID);

#endif

/** SIF_X_Read
 *  Read data with channel ID, word address, of which length up to three, from SIF module.
 *  @param  u1ChannelID     SIF bus ID.
 *  @param  u2ClkDiv        Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr       Serial interface device address.
 *  @param  u1WordAddrNum   Serial interface word address length.
 *  @param  u4WordAddr      Serial interface word address. Format XX B2 B1 B0. B2 is sent on SIF bus first.
 *  @param  pu1Buf          Pointer to user's buffer.
 *  @param  u2ByteCnt       Number of byte to read. Max = 256 bytes.
 *  @retval > 0             Actual number of bytes read.
 *  @retval = 0             Error
 */
EXTERN UINT16 SIF_X_Read(UINT8 u1CHannelID, UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddrNum,
                         UINT32 u4WordAddr, UINT8 *pu1Buf, UINT16 u2ByteCnt);

EXTERN UINT16 SIF_X_SpecialRead(UINT8 u1CHannelID, UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddrNum,
                         UINT32 u4WordAddr, UINT8 *pu1Buf, UINT16 u2ByteCnt);

/** SIF_X_Write
 *  Write data with channel ID, word address, of which length up to three, to SIF module.
 *  @param  u1ChannelID     SIF bus ID.
 *  @param  u2ClkDiv        Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr       Serial interface device address.
 *  @param  u1WordAddrNum   Serial interface word address length.
 *  @param  u4WordAddr      Serial interface word address. Format XX B2 B1 B0. B2 is sent on SIF bus first.
 *  @param  pu1Buf          Pointer to user's buffer.
 *  @param  u2ByteCnt       Number of byte to write. Max = 256 bytes.
 *  @retval > 0             Actual number of bytes written.
 *  @retval = 0             Error
 */

EXTERN UINT16 SIF_X_Write(UINT8 u1CHannelID, UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddrNum,
                          UINT32 u4WordAddr, UINT8 *pu1Buf, UINT16 u2ByteCnt);

/** SIF_X_Write_SpecialDemod
 *  Write data with channel ID, word address, of which length up to three, to SIF module.
 *  @param  u1ChannelID     SIF bus ID.
 *  @param  u2ClkDiv        Parameter of divider to divide 27Mhz for SCL.
 *  @param  u1DevAddr       Serial interface device address.
 *  @param  u1WordAddrNum   Serial interface word address length.
 *  @param  u4WordAddr      Serial interface word address. Format XX B2 B1 B0. B2 is sent on SIF bus first.
 *  @param  pu1Buf          Pointer to user's buffer.
 *  @param  u2ByteCnt       Number of byte to write. Max = 256 bytes.
 *  @retval > 0             Actual number of bytes written.
 *  @retval = 0             Error
 */

EXTERN UINT16 SIF_X_Write_SpecialDemod(UINT8 u1CHannelID, UINT16 u2ClkDiv, UINT8 u1DevAddr, UINT8 u1WordAddrNum, UINT32 u4WordAddr, UINT8 *pu1Buf, UINT16 u2ByteCnt);

EXTERN void SIF_pm_str_suspend(void);

EXTERN void SIF_pm_str_resume(void);

#ifdef SIF_CHECK_SDA_LOW
EXTERN SIF_BUS_STATUS_T SIF_CheckBusStatus (VOID);
EXTERN INT32 SIF_SendStopBit(VOID);
#endif

#endif /* SIF_IF_H */
