/*
 * Copyright (c) 2017-2019, NVIDIA CORPORATION.  All rights reserved. All
 * information contained herein is proprietary and confidential to NVIDIA
 * Corporation.  Any use, reproduction, or disclosure without the written
 * permission of NVIDIA Corporation is prohibited.
 */

#ifndef _ISC_MAX96712_H_
#define _ISC_MAX96712_H_

#include "nvmedia_isc.h"

#define MAX96712_REG_GMSL1_LINK_A               0x0BCB
#define MAX96712_REG_GMSL1_LINK_B               0x0CCB
#define MAX96712_REG_GMSL1_LINK_C               0x0DCB
#define MAX96712_REG_GMSL1_LINK_D               0x0ECB
#define MAX96712_REG_GMSL1_DET_ERR_LINK_A       0x0B15
#define MAX96712_REG_GMSL1_DET_ERR_LINK_B       0x0C15
#define MAX96712_REG_GMSL1_DET_ERR_LINK_C       0x0D15
#define MAX96712_REG_GMSL1_DET_ERR_LINK_D       0x0E15
#define MAX96712_REG_GMSL2_LINK_A               0x001A
#define MAX96712_REG_GMSL2_LINK_B               0x000A
#define MAX96712_REG_GMSL2_LINK_C               0x000B
#define MAX96712_REG_GMSL2_LINK_D               0x000C
#define MAX96712_REG_GMSL2_DEC_ERR_LINK_A       0x0035
#define MAX96712_REG_GMSL2_DEC_ERR_LINK_B       0x0036
#define MAX96712_REG_GMSL2_DEC_ERR_LINK_C       0x0037
#define MAX96712_REG_GMSL2_DEC_ERR_LINK_D       0x0038
#define MAX96712_REG_GMSL2_IDLE_ERR_LINK_A      0x0039
#define MAX96712_REG_GMSL2_IDLE_ERR_LINK_B      0x003A
#define MAX96712_REG_GMSL2_IDLE_ERR_LINK_C      0x003B
#define MAX96712_REG_GMSL2_IDLE_ERR_LINK_D      0x003C

#define MAX96712_MAX_REG_ADDRESS                0x1F17

#define MAX96712_MIPI_OUT_4Bx22A                (1u << 4u)
#define MAX96712_MIPI_OUT_4Ax22B                (1u << 3u)
#define MAX96712_MIPI_OUT_2x4                   (1u << 2u)
#define MAX96712_MIPI_OUT_4x2                   (1u << 0u)

#define GET_MAX96712_GMSL_LINK(link)            (1u << link)

#define MAX96712_GMSL1_LINK_LOCK                (1u << 0u)
#define MAX96712_GMSL2_LINK_LOCK                (1u << 3u)
#define MAX96712_VID_RX8_LOCK                   (1u << 6u)
#define MAX96712_REG(reg, link)                 (reg + 0x12u * link)

#define MAX96712_MAX_NUM_LINK                   4u
#define MAX96712_NUM_VIDEO_PIPELINES            8u

#define MAX96712_OSN_COEFF_MIN                  20u
#define MAX96712_OSN_COEFF_MAX                  40u

#define MAX96712_OSC_MHZ                        25u

#define MAX96712_MAX_NUM_PHY                    4

typedef enum {
    ISC_WRITE_PARAM_CMD_MAX96712_PIPELINE_MAPPING = 0u,
    ISC_WRITE_PARAM_CMD_MAX96712_UNUSED_PIPELINE_MAPPING,
    ISC_WRITE_PARAM_CMD_MAX96712_SET_I2C_PORT,
    ISC_WRITE_PARAM_CMD_MAX96712_ENABLE_CONCATENATION,
    ISC_WRITE_PARAM_CMD_MAX96712_SWAP,
    ISC_WRITE_PARAM_CMD_MAX96712_FSYNC_MODE,
    ISC_WRITE_PARAM_CMD_MAX96712_SET_DATA_TYPE,
    ISC_WRITE_PARAM_CMD_MAX96712_SET_CSI_PREBEGIN_TIME,
    ISC_WRITE_PARAM_CMD_MAX96712_SET_CSI_POST_LENGTH,
    ISC_WRITE_PARAM_CMD_MAX96712_REPLICATION,
    ISC_WRITE_PARAM_CMD_MAX96712_SET_VIDEO_PIPELINE_MAPPING,
    ISC_WRITE_PARAM_CMD_MAX96712_SET_PG_CLK_FREQ,
    ISC_WRITE_PARAM_CMD_MAX96712_SET_PG_PIPELINE_CLK_SRC,
    ISC_WRITE_PARAM_CMD_MAX96712_ENABLE_SPECIFIC_PIPELINES,
    ISC_WRITE_PARAM_CMD_MAX96712_ENABLE_SPECIFIC_LINK,
    ISC_WRITE_PARAM_CMD_MAX96712_ENABLE_PERIODIC_AEQ,
    ISC_WRITE_PARAM_CMD_MAX96712_GMSL1_HIM_ENABLED,
    ISC_WRITE_PARAM_CMD_MAX96712_ENABLE_FORWARD_CHANNEL,
    ISC_WRITE_PARAM_CMD_MAX96712_DISABLE_FORWARD_CHANNEL,
    ISC_WRITE_PARAM_CMD_MAX96712_ENABLE_PACKET_BASED_CONTROL_CHANNEL,
    ISC_WRITE_PARAM_CMD_MAX96712_DISABLE_DE,
    ISC_WRITE_PARAM_CMD_MAX96712_SET_DBL,
} WriteParametersCmdMAX96712;

typedef enum {
    ISC_READ_PARAM_CMD_MAX96712_REV_ID,
    ISC_READ_PARAM_CMD_MAX96712_CONTROL_CHANNEL_CRC_ERROR
} ReadParametersCmdMAX96712;

typedef enum {
    ISC_CONFIG_MAX96712_ENABLE_CSI_OUT = 0u,
    ISC_CONFIG_MAX96712_DISABLE_CSI_OUT,
    ISC_CONFIG_MAX96712_SET_I2C_LOCAL_ACK,
    ISC_CONFIG_MAX96712_DISABLE_LINKS_0123,
    ISC_CONFIG_MAX96712_ENABLE_LINK_0,
    ISC_CONFIG_MAX96712_ENABLE_LINKS_01,
    ISC_CONFIG_MAX96712_ENABLE_LINKS_012,
    ISC_CONFIG_MAX96712_ENABLE_LINKS_0123,
    ISC_CONFIG_MAX96712_ENABLE_LINK_2,
    ISC_CONFIG_MAX96712_ENABLE_LINKS_23,
    ISC_CONFIG_MAX96712_ENABLE_LINKS_02,
    ISC_CONFIG_MAX96712_SET_RESET,
    ISC_CONFIG_MAX96712_SET_VIDEO_PIPELINES_SELECT,
    ISC_CONFIG_MAX96712_SET_DEFAULT_GMSL1_LEGACY,
    ISC_CONFIG_MAX96712_GMSL2_LINK_ADAPTATION_LINK0,
    ISC_CONFIG_MAX96712_GMSL2_LINK_ADAPTATION_LINK1,
    ISC_CONFIG_MAX96712_GMSL2_LINK_ADAPTATION_LINK2,
    ISC_CONFIG_MAX96712_GMSL2_LINK_ADAPTATION_LINK3,
    ISC_CONFIG_MAX96712_DISABLE_PACKET_DETECTOR,
    ISC_CONFIG_MAX96712_SET_GMSL1_MODE,
    ISC_CONFIG_MAX96712_SET_GMSL2_MODE,
    ISC_CONFIG_MAX96712_ENABLE_REPLICATION,
    ISC_CONFIG_MAX96712_DISABLE_REPLICATION,
    ISC_CONFIG_MAX96712_ENABLE_REVERSE_CHANNELS_0123,
    ISC_CONFIG_MAX96712_DISABLE_REVERSE_CHANNELS_0123,
    ISC_CONFIG_MAX96712_ADJUST_TX_AMP_AND_TIMING,
    ISC_CONFIG_MAX96712_CONFIG_MIPI_OUT_MODE,
    ISC_CONFIG_MAX96712_SET_PG_1920x1236,
    ISC_CONFIG_MAX96712_ENABLE_PG,
    ISC_CONFIG_MAX96712_ENABLE_MEMORY_ECC_ERRB,
    ISC_CONFIG_MAX96712_DISABLE_MEMORY_ECC_ERRB,
    ISC_CONFIG_MAX96712_SET_TX_SRC_ID,
    ISC_CONFIG_MAX96712_TRIGGER_DESKEW,
    ISC_CONFIG_MAX96712_CHECK_CSIPLL_LOCK
} ConfigSetsMAX96712;

typedef enum {
     ISC_MAX96712_GMSL1_MODE = 0u,
     ISC_MAX96712_GMSL2_MODE,
     ISC_MAX96712_MAX_GMSL_MODE,
} GMSLModeMax96712;

typedef enum {
     ISC_MAX96712_TXPORT_PHY_C = 0u,
     ISC_MAX96712_TXPORT_PHY_D,
     ISC_MAX96712_TXPORT_PHY_E,
     ISC_MAX96712_TXPORT_PHY_F,
} TxPortMax96712;

typedef enum {
     ISC_MAX96712_I2CPORT_0 = 0u,
     ISC_MAX96712_I2CPORT_1,
} I2CPortMax96712;

typedef enum {
     ISC_MAX96712_DPHY = 0u,
     ISC_MAX96712_CPHY,
} PHYModeMax96712;

typedef enum {
    ISC_CONFIG_MAX96712_MANUAL_SYNC = 0u,
    ISC_CONFIG_MAX96712_OSC_MANUAL_SYNC,
    ISC_CONFIG_MAX96712_EXTERNAL_SYNC,
    ISC_CONFIG_MAX96712_AUTO_SYNC,
    ISC_CONFIG_MAX96712_NUM_SYNC_MODE,
} ConfigSetMax96712SyncMode;

typedef enum {
    ISC_MAX96712_REG_GMSL1_LINK_A = 0u,
    ISC_MAX96712_REG_GMSL1_LINK_B,
    ISC_MAX96712_REG_GMSL1_LINK_C,
    ISC_MAX96712_REG_GMSL1_LINK_D,
    ISC_MAX96712_REG_GMSL1_DET_ERR_A,
    ISC_MAX96712_REG_GMSL1_DET_ERR_B,
    ISC_MAX96712_REG_GMSL1_DET_ERR_C,
    ISC_MAX96712_REG_GMSL1_DET_ERR_D,
    ISC_MAX96712_GMSL1_NUM_ERR_REG,
} ErrorRegisterMAX96712GMSL1;

typedef enum {
    ISC_MAX96712_REG_GMSL2_LINK_A = 0u,
    ISC_MAX96712_REG_GMSL2_LINK_B,
    ISC_MAX96712_REG_GMSL2_LINK_C,
    ISC_MAX96712_REG_GMSL2_LINK_D,
    ISC_MAX96712_REG_GMSL2_DEC_ERR_A,
    ISC_MAX96712_REG_GMSL2_DEC_ERR_B,
    ISC_MAX96712_REG_GMSL2_DEC_ERR_C,
    ISC_MAX96712_REG_GMSL2_DEC_ERR_D,
    ISC_MAX96712_REG_GMSL2_IDLE_ERR_A,
    ISC_MAX96712_REG_GMSL2_IDLE_ERR_B,
    ISC_MAX96712_REG_GMSL2_IDLE_ERR_C,
    ISC_MAX96712_REG_GMSL2_IDLE_ERR_D,
    ISC_MAX96712_GMSL2_NUM_ERR_REG,
} ErrorRegisterMAX96712GMSL2;

typedef enum {
    ISC_MAX96712_NO_ERROR = 0u,
    ISC_MAX96712_GMSL1_LINK_UNLOCK,
    ISC_MAX96712_GMSL2_LINK_UNLOCK,
    ISC_MAX96712_GMSL1_DET_ERR,
    ISC_MAX96712_GMSL2_DEC_ERR,
    ISC_MAX96712_GMSL2_IDLE_ERR,
    ISC_MAX96712_NUM_FAILURE_TYPES
} FailureTypeMAX96712;

typedef enum {
    ISC_MAX96712_DATA_TYPE_RAW10 = 0u,
    ISC_MAX96712_DATA_TYPE_RAW12,
    ISC_MAX96712_DATA_TYPE_RAW16,
    ISC_MAX96712_DATA_TYPE_RGB,
    ISC_MAX96712_NUM_DATA_TYPES
} DataTypeMAX96712;

typedef enum {
    ISC_MAX96712_INVALID_REV = 0u,
    ISC_MAX96712_REV_1,
    ISC_MAX96712_REV_2,
    ISC_MAX96712_REV_3,
    ISC_MAX96712_REV_4
} RevisionMAX96712;

typedef enum {
    ISC_MAX96712_MIPI_SPEED_2500_MHZ = 25u,
    ISC_MAX96712_MIPI_SPEED_2000_MHZ = 20u,
    ISC_MAX96712_MIPI_SPEED_1700_MHZ = 17u
} MipiSpeedMAX96712;

typedef enum {
    ISC_MAX96712_PG_CLK_25_MHZ = 0u,
    ISC_MAX96712_PG_CLK_75_MHZ,
    ISC_MAX96712_PG_CLK_150_MHZ,
    ISC_MAX96712_PG_CLK_375_MHZ,
    ISC_MAX96712_NUM_PG_CLK_SETTINGS,
} PGClockFreqMAX96712;

typedef enum {
    ISC_MAX96712_GMSL1_CONFIG_LINK_LOCK,
    ISC_MAX96712_GMSL2_LINK_LOCK,
    ISC_MAX96712_VIDEO_LINK_LOCK,
} LinkTypeMAX96712;

typedef enum {
    ISC_MAX96712_GPIO_0 = 0u, /* MFP0 */
    ISC_MAX96712_GPIO_1,     /* MFP1 */
    ISC_MAX96712_GPIO_2,     /* MFP2 */
    ISC_MAX96712_GPIO_3,     /* MFP3 */
    ISC_MAX96712_GPIO_4,     /* MFP4 */
    ISC_MAX96712_GPIO_5,     /* MFP5 */
    ISC_MAX96712_GPIO_6,     /* MFP6 */
    ISC_MAX96712_GPIO_7,     /* MFP7 */
    ISC_MAX96712_GPIO_8,     /* MFP8 */
} GPIOIndexMax96712;

typedef struct {
    uint8_t link;
    uint8_t serializerStream;
} VideoPipelineMappingMAX96712;

typedef union {
    struct {
        uint8_t link;
    } ConfigLink;

    struct {
        uint8_t numSensor;
    } ConcatenateVideoStream;

    struct {
        uint8_t link;
        /* flag to indicate if embedded data lines are not part of the pixel data and passed seperately
         * 0 - embedded data passed as part of pixel data,
         * 1 - embedded data passed seperately with embedded data type set */
        uint8_t embDataType;
        DataTypeMAX96712 dataType;
    } VC;

    struct {
        uint8_t syncMode; /* 0 - internal sync, 1 - external sync */
        uint32_t pclk;
        uint32_t fps;
    } FRSYNCMode;

    struct {
        uint8_t link;
    } I2CPort;

    DataTypeMAX96712 dataType;

    uint8_t csiPrebeginTime;
    uint8_t csiPostLength;

    struct {
        uint8_t source; /* the source PHY */
        uint8_t mipiOut; /* PHY configuration */
    } Replication;

    struct {
        VideoPipelineMappingMAX96712 pipelineMapping[MAX96712_NUM_VIDEO_PIPELINES];
        uint8_t numPipelines;
    } VideoPipelineMapping;

    struct {
        uint8_t link;
        uint8_t step; /* step to enable HIM mode */
    } stepHIM;

    PGClockFreqMAX96712 pgClkFreq;

    PGClockFreqMAX96712 pgPipelineClkSrc[MAX96712_NUM_VIDEO_PIPELINES];

    uint32_t numPipelines;

    uint32_t SpecificLink;
} WriteParametersParamMAX96712;

typedef union{
    RevisionMAX96712 rev;

    struct {
        uint8_t link;
        uint8_t errVal;
    } ErrorStatus;
} ReadParametersParamMAX96712;

typedef struct {
    FailureTypeMAX96712    failureType[MAX96712_MAX_NUM_LINK];
    uint8_t                link;
    uint32_t               regVal[MAX96712_MAX_NUM_LINK];
} ErrorStatusMAX96712;

typedef struct {
   uint8_t link;
   uint8_t mask;
   uint8_t result;
   FailureTypeMAX96712 errType;
} MAX96712ErrLut;

typedef struct {
    RevisionMAX96712 revision;  /* chip revision information */
    uint8_t gmslMode;           /* 0 : GMSL1, 1 : GMSL2 */
    uint8_t i2cPort;            /* 0 : 1st I2C port, 1 : 2nd I2C port */
    uint8_t txPort;             /* MIPI output port */
    uint8_t mipiCfg;            /* MIPI configuration */
    uint8_t mipiSpeed;          /* MIPI Speed specified in multiples of 100MHz */
    NvMediaBool slaveEnabled;   /* Doesn't need to control sensor/serializer
                                 * through aggregator */
    PHYModeMax96712 phyMode;    /* CPHY or DPHY */
} ContextMAX96712;

NvMediaISCDeviceDriver *GetMAX96712Driver(void);

NvMediaStatus
MAX96712CheckPresence(
    NvMediaISCDevice *handle);

NvMediaStatus
MAX96712SetDeviceConfig(
    NvMediaISCDevice *handle,
    uint32_t enumeratedDeviceConfig);

NvMediaStatus
MAX96712ReadRegister(
    NvMediaISCDevice *handle,
    uint32_t deviceIndex,
    uint32_t registerNum,
    uint32_t dataLength,
    uint8_t *dataBuff);

NvMediaStatus
MAX96712WriteRegister(
    NvMediaISCDevice *handle,
    uint32_t deviceIndex,
    uint32_t registerNum,
    uint32_t dataLength,
    uint8_t *dataBuff);

NvMediaStatus
MAX96712WriteParameters(
    NvMediaISCDevice *handle,
    uint32_t parameterType,
    uint32_t parameterSize,
    void *parameter);

NvMediaStatus
MAX96712ReadParameters(
    NvMediaISCDevice *handle,
    uint32_t parameterType,
    uint32_t parameterSize,
    void *parameter);

NvMediaStatus
MAX96712DumpRegisters(
    NvMediaISCDevice *handle);

NvMediaStatus
MAX96712GetErrorStatus(
    NvMediaISCDevice *handle,
    uint32_t parameterSize,
    void *parameter);

NvMediaStatus
MAX96712CheckLink(
    NvMediaISCDevice *handle,
    uint32_t linkIndex,
    uint32_t linkType,
    NvMediaBool display);

NvMediaStatus
MAX96712OneShotReset(
    NvMediaISCDevice *handle,
    uint32_t linkMask);

#endif /* _ISC_MAX96712_H_ */
