#ifndef __PHSTBHDMI_H__
#define __PHSTBHDMI_H__

/*****************************************************************************/
/* Copyright (c) 2009 NXP B.V.                                               */
/*                                                                           */
/* This program is free software; you can redistribute it and/or modify      */
/* it under the terms of the GNU General Public License as published by      */
/* the Free Software Foundation, using version 2 of the License.             */
/*                                                                           */
/* 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 the              */
/* GNU General Public License for more details.                              */
/*                                                                           */
/* You should have received a copy of the GNU General Public License         */
/* along with this program; if not, write to the Free Software               */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307       */
/* USA.                                                                      */
/*                                                                           */
/*****************************************************************************/

/**
    @file   phStbHdmi.h
*//*

Rev Date        Author      Comments
--------------------------------------------------------------------------------
  1 20081002    estarkie     Original
  2 20090129    legendrd     add c++ support
  3 20090216    batelaan     Add constants and types from tda9983.h/tda9984.h.
  4 20090325    amccurdy     Sync with San Jose, fix kernel API conditional on
                             CONFIG_PM, add additional kernel API functions
  5 20090329    amccurdy     Simplify phStbHdmi_RegisterStatusCallback callback arg
--------------------------------------------------------------------------------
    For consistency and standardisation retain the Section Separators.
*/

#include "tmNxTypes.h"
#include "tmCompId.h"
#include <linux/ioctl.h>
#include <linux/types.h>
#if TMFL_MODE_KERNEL == 1
#include <linux/videodenc.h>
#endif

#if defined(__cplusplus)
extern "C" {
#endif

//------------------------------------------------------------------------------
//                              I O C T L ' s  constants & data structures
//------------------------------------------------------------------------------

#define HDMI_SAD_MAX_CNT    10
#define HDMI_SVD_MAX_CNT    30

typedef enum
{
    PH_STBHDMI_AFMT_SPDIF = 0,          /**< SPDIF */
    PH_STBHDMI_AFMT_I2S   = 1,          /**< I2S */
    PH_STBHDMI_AFMT_OBA   = 2,          /**< One bit audio / DSD */
    PH_STBHDMI_AFMT_DST   = 3,          /**< DST */
    PH_STBHDMI_AFMT_HBR   = 4           /**< HBR */
}
phStbHdmi_audio_fmt_t;

typedef enum
{
    PH_STBHDMI_SMPLSIZE_HEADER = 0,     /**< Refer to stream header */
    PH_STBHDMI_SMPLSIZE_16BITS = 1,     /**< 16 bits sample size */
    PH_STBHDMI_SMPLSIZE_20BITS = 2,     /**< 20 bits sample size */
    PH_STBHDMI_SMPLSIZE_24BITS = 3      /**< 24 bits sample size */
}
phStbHdmi_sample_size_t;

typedef enum
{
    PH_STBHDMI_AFS_32K    = 0,          /**< 32 kHz */
    PH_STBHDMI_AFS_32k    = 0,          /**< 32 kHz (small k, legacy alias) */
    PH_STBHDMI_AFS_44_1K  = 1,          /**< 44.1 kHz */
    PH_STBHDMI_AFS_44_1k  = 1,          /**< 44.1 kHz (small k, legacy alias) */
    PH_STBHDMI_AFS_48K    = 2,          /**< 48 kHz */
    PH_STBHDMI_AFS_88_2K  = 3,          /**< 88.2 kHz */
    PH_STBHDMI_AFS_96K    = 4,          /**< 96 kHz */
    PH_STBHDMI_AFS_176_4K = 5,          /**< 176.4 kHz */
    PH_STBHDMI_AFS_192K   = 6           /**< 192 kHz */
}
phStbHdmi_afs_t;

// For use with phStbHdmi_setAudio
typedef struct
{
    phStbHdmi_audio_fmt_t audioFmt;
    phStbHdmi_sample_size_t sampleSize;
    phStbHdmi_afs_t samplingFrequency;
    UInt8 channelAllocation;
}
phStbHdmi_aud_t;

// For use with PH_STBHDMI_IOCTL_GET_EDID_DATA
typedef struct
{
    int bufsize;
    void *pData;
    int bufferFilled;                   /**< Number of bytes returned */
}
phStbHdmi_raw_edid_t;

// For use with PH_STBHDMI_IOCTL_GET_AUDIO_CAP
//
// ModeChans bits[6:3]description (from CEA861 spec)
//
//  0 = Reserved
//  1 = Linear PCM
//  2 = AC3
//  3 = MPEG1 (layer1 & 2)
//  4 = MP3 (MPEG1 layer 3)
//  5 = MPEG2 (MultiChannels)
//  6 = AAC
//  7 = DTS
//  8 = ATRAC
//  9 = One Bit Audio
// 10 = Dolby Digital +
// 11 = DTS-HD
// 12 = MAT (MLP)
// 13 = DST
// 14 = WMA Pro
// 15 = Reserved for audio format 15

// ModeChans bits[2:0] descriptions
// Number of channels - 1

// Freqs description bits[6:0]
// Bit 0 = 32kHz
// Bit 1 = 44.1kHz
// Bit 2 = 48kHz
// Bit 3 = 88.2kHz
// Bit 4 = 96kHz
// Bit 5 = 176.4kHz
// Bit 6 = 192kHz
typedef struct
{
    UInt8 ModeChans;            /**< Bits[6:3]: EIA/CEA861 mode; Bits[2:0]: channels */
    UInt8 Freqs;                /**< Bits for each supported frequency */
    UInt8 Byte3;                /**< EIA/CEA861B p83: data depending on audio mode */
}
phStbHdmi_EdidSad_t;

// audioFlags description
//
// speakersAlloc description bits[6:0]
// Bit 0 = FL/FR
// Bit 1 = LFE
// Bit 2 = FC
// Bit 3 = RL/RR
// Bit 4 = RC
// Bit 5 = FLC/FRC
// Bit 6 = RLC/RRC
//
// Bit 7 = Support basic audio
typedef struct
{
    UInt fmtsAvail;
    UInt8 audioFlags;
    phStbHdmi_EdidSad_t edidAFmts[HDMI_SAD_MAX_CNT];
    UInt8 speakersAlloc;
}
phStbHdmi_audio_cap_t;

// For use with PH_STBHDMI_IOCTL_GET_VIDEO_CAP
typedef struct
{
    UInt fmtsAvail;
    UInt8 videoFlags;
    UInt8 edidVFmts[HDMI_SVD_MAX_CNT];
}
phStbHdmi_video_cap_t;

// For use with PH_STBHDMI_IOCTL_WAIT_CALLBACK_STATUS
#define STATUS_HOTPLUG_INACTIVE         (0x0 << 0)  /**< Hotplug inactive */
#define STATUS_HOTPLUG_ACTIVE           (0x1 << 0)  /**< Hotplug active */
#define STATUS_HOTPLUG_INVALID          (0x2 << 0)  /**< Invalid Hotplug */
#define STATUS_HOTPLUG_BITMASK          (0x3 << 0)

#define STATUS_RX_SENSE_INACTIVE        (0x0 << 2)  /**< RxSense inactive */
#define STATUS_RX_SENSE_ACTIVE          (0x1 << 2)  /**< RxSense active */
#define STATUS_RX_SENSE_INVALID         (0x2 << 2)  /**< Invalid RxSense */
#define STATUS_RX_SENSE_BITMASK         (0x3 << 2)

#define STATUS_EDID_READ                (0x0 << 4)  /**< All blocks read OK */
#define STATUS_EDID_READ_INCOMPLETE     (0x1 << 4)  /**< All blocks read OK but buffer too small to return all of them */
#define STATUS_EDID_ERROR               (0x2 << 4)  /**< Block 0 OK, checksum error in one or more other blocks */
#define STATUS_EDID_ERROR_INCOMPLETE    (0x3 << 4)  /**< Block 0 OK, checksum error in one or more other blocks and buffer too small to return all of them */
#define STATUS_EDID_NOT_READ            (0x4 << 4)  /**< EDID not read or checksum error in block 0 */
#define STATUS_EDID_BITMASK             (0x7 << 4)

#define STATUS_USER_UNBLOCK_WAIT        (0x1 << 7)  /**< user call PH_STBHDMI_IOCTL_UNBLOCK_CALLBACK */

#define STATUS_HDCP_NOT_ENABLE          (0x0 << 8)  /**< Status of HDCP return to user, bit 8..10 */
#define STATUS_HDCP_FAILURE             (0x1 << 8)
#define STATUS_HDCP_BUSY                (0x2 << 8)
#define STATUS_HDCP_ENABLE              (0x3 << 8)
#define STATUS_HDCP_UNKNOWN_ERR         (0x4 << 8)
#define STATUS_HDCP_BITMASK             (0x7 << 8)

// For use with PH_STBHDMI_IOCTL_START_HDCP
typedef struct
{
    UInt16 hdcpSeed;
    UInt16 overrideBlueScreen;                      /**< non-zero to disable bluescreen during authentication (debug, will fail certification... ?) */
}
phStbHdmi_start_hdcp_t;

// For use with PH_STBHDMI_IOCTL_SET_TEST_PATTERN
#define HDMI_PATTERN_OFF                (0)         /**< Turn off pattern (if any) */
#define HDMI_PATTERN_CBAR4              (1)         /**< Insert 4-bar colour bar */
#define HDMI_PATTERN_CBAR8              (2)         /**< Insert 8-bar colour bar */
#define HDMI_PATTERN_BLUE               (3)         /**< Insert Blue screen */

// For use with PH_STBHDMI_IOCTL_GET_TX_OBJECT
#define MIN_TXOBJECT_SIZE               (2000)
#define MAX_TXOBJECT_SIZE               (10000)
typedef struct
{
    char *pData;
    UInt32 size;
}
phStbHdmi_TxObject_t;


//------------------------------------------------------------------------------
//                              I O C T L ' s  definition
//------------------------------------------------------------------------------

/** The base of phStbHdmi ioctls. */
#define PH_STBHDMI_IOCTL_BASE                   0x83
#define PH_STBHDMI_IOCTL_SET_AUDIO_RATE         _IOW(PH_STBHDMI_IOCTL_BASE, 0, int)
#define PH_STBHDMI_IOCTL_SET_VIDEO_MODE         _IOW(PH_STBHDMI_IOCTL_BASE, 1, int)
#define PH_STBHDMI_IOCTL_GET_EDID_BLKCNT        _IOW(PH_STBHDMI_IOCTL_BASE, 2, int)
#define PH_STBHDMI_IOCTL_GET_EDID_DATA          _IOW(PH_STBHDMI_IOCTL_BASE, 3, int)
#define PH_STBHDMI_IOCTL_DISABLE_HDMI_OUTPUT    _IOW(PH_STBHDMI_IOCTL_BASE, 4, int)
#define PH_STBHDMI_IOCTL_ENABLE_HDMI_OUTPUT     _IOW(PH_STBHDMI_IOCTL_BASE, 5, int)
#define PH_STBHDMI_IOCTL_GET_AUDIO_CAP          _IOW(PH_STBHDMI_IOCTL_BASE, 6, int)
#define PH_STBHDMI_IOCTL_GET_VIDEO_CAP          _IOW(PH_STBHDMI_IOCTL_BASE, 7, int)
#define PH_STBHDMI_IOCTL_GET_HOTPLUG_STATUS     _IOW(PH_STBHDMI_IOCTL_BASE, 8, int)
#define PH_STBHDMI_IOCTL_GET_RXSENSE_STATUS     _IOW(PH_STBHDMI_IOCTL_BASE, 9, int)
#define PH_STBHDMI_IOCTL_GET_SINK_TYPE          _IOW(PH_STBHDMI_IOCTL_BASE,10, int)
#define PH_STBHDMI_IOCTL_WAIT_CALLBACK_STATUS   _IOW(PH_STBHDMI_IOCTL_BASE,11, int)
#define PH_STBHDMI_IOCTL_UNBLOCK_CALLBACK       _IOW(PH_STBHDMI_IOCTL_BASE,12, int)
#define PH_STBHDMI_IOCTL_DISABLE_AUDIO_OUTPUT   _IOW(PH_STBHDMI_IOCTL_BASE,13, int)
#define PH_STBHDMI_IOCTL_ENABLE_AUDIO_OUTPUT    _IOW(PH_STBHDMI_IOCTL_BASE,14, int)
#define PH_STBHDMI_IOCTL_START_HDCP             _IOW(PH_STBHDMI_IOCTL_BASE,15, int)
#define PH_STBHDMI_IOCTL_STOP_HDCP              _IOW(PH_STBHDMI_IOCTL_BASE,16, int)
#define PH_STBHDMI_IOCTL_GET_HDCP_STATUS        _IOW(PH_STBHDMI_IOCTL_BASE,17, int)
#define PH_STBHDMI_IOCTL_USE_ALT_480P           _IOW(PH_STBHDMI_IOCTL_BASE,18, int)
#define PH_STBHDMI_IOCTL_SET_TEST_PATTERN       _IOW(PH_STBHDMI_IOCTL_BASE,19, int)
#define PH_STBHDMI_IOCTL_GET_TX_OBJECT          _IOW(PH_STBHDMI_IOCTL_BASE,20, int)

#if TMFL_MODE_KERNEL == 1

/**
 * @brief phStbHdmi operations.
 */
typedef struct phStbHdmi_Ops
{
    /** open/release and usage marking */
    struct module *owner;

    /* -------------------------------------------------------------------- */
    /* Kernel space functions                                               */
    /* -------------------------------------------------------------------- */

    /** Set the video mode according to info->var */
    int (*phStbHdmi_set_mode)(struct videodenc_info *info);

    /** Blank the display */
    int (*phStbHdmi_blank)(struct videodenc_info *info, int blank);

    /** Display the specified test pattern */
    int (*phStbHdmi_test_pattern)(struct videodenc_info *info, int test_pattern);

    /** Enable HDMI Audio */
    int (*phStbHdmi_enable_audio)(void);

    /** Disable HDMI Audio */
    int (*phStbHdmi_disable_audio)(void);

    /** Enter Power Saving Mode */
    int (*phStbHdmi_suspend)(struct platform_device* p_dev, pm_message_t event);

    /** Leave Power Saving Mode */
    int (*phStbHdmi_resume)(struct platform_device* p_dev);

    /** Set the audio output rate */
    tmErrorCode_t (*phStbHdmi_setAudioRate)(phStbHdmi_afs_t audioRate);

    /** Get audio capabilities. */
    tmErrorCode_t (*phStbHdmi_getAudioCap)(phStbHdmi_audio_cap_t *pAudioCap);

    /** Set audio configuration. */
    tmErrorCode_t (*phStbHdmi_setAudio)(phStbHdmi_aud_t *pStrAudio);

    /** Register HDMI status change callback */
    tmErrorCode_t (*phStbHdmi_RegisterStatusCallback)(void (*pCallback) (unsigned long status));

    /** Unregister HDMI status change callback */
    tmErrorCode_t (*phStbHdmi_UnRegisterStatusCallback)(void);

    /** Call to initialize HDMI device AFTER the video denc/Vo output is stable */
    tmErrorCode_t (*phStbHdmi_InitializeHDMIDevice)(void);

    /** Return true if the HDMI device is capable of supporting multi-channel audio, false otherwise */
    int (*phStbHdmi_MultiChannelPCMSupported)(void);

    /* -------------------------------------------------------------------- */
    /* ioctl handlers                                                       */
    /* -------------------------------------------------------------------- */

    /** Set the audio output rate */
    int (*phStbHdmi_ioctlSetAudioRate)(unsigned long arg);

    /** Set the display mode */
    int (*phStbHdmi_ioctl_set_mode)(struct videodenc_info * info);

    /** Get the number of EDID blocks present on the connected HDMI/DVI display */
    int (*phStbHdmi_ioctlGetEdidBlkCnt)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Get the EDID data from the connected HDMI/DVI display */
    int (*phStbHdmi_ioctlGetEdidData)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Enable/Disable HDMI/DVI output */
    int (*phStbHdmi_ioctlEnableDisableHdmi)(tmUnitSelect_t txUnit, int disable);

    /** Get the Audio capabilities of the connected HDMI/DVI display */
    int (*phStbHdmi_ioctlGetAudioCap)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Get the Video capabilities of the connected HDMI/DVI display */
    int (*phStbHdmi_ioctlGetVideoCap)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Get the current Hotplug status */
    int (*phStbHdmi_ioctlGetHotplugStatus)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Get the current Rxsense status */
    int (*phStbHdmi_ioctlGetRxSenseStatus)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Get the connected sink type (HDMI/DVI) */
    int (*phStbHdmi_ioctlGetSinkType)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Enable callback of HDMI events */
    int (*phStbHdmi_ioctlWaitCallbackStatus)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Disable callback of HDMI events */
    int (*phStbHdmi_ioctlUserUnblockWaitStatus)(void);

    /** Enable/Disable HDMI Audio output */
    int (*phStbHdmi_ioctlEnableDisableAudio)(tmUnitSelect_t txUnit, int disable);

    /** Start High-Bandwidth Digital Content Protection */
    int (*phStbHdmi_ioctlStartHdcp)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Stop High-Bandwidth Digital Content Protection */
    int (*phStbHdmi_ioctlStopHdcp)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Get the status of the High-Bandwidth Digital Content Protection */
    int (*phStbHdmi_ioctlGetHdcpStatus)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Display the specified test pattern */
    int (*phStbHdmi_ioctl_test_pattern)(struct videodenc_info *info, int test_pattern);

    /** Get the TxObjects from the lower level driver */
    int (*phStbHdmi_ioctlGetTmHdmiTxobject)(tmUnitSelect_t txUnit, unsigned long arg);

    /** Handle extended (device specific) IOCTLs */
    int (*phStbHdmi_ioctlExtended)(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, struct videodenc_info *info);
} phStbHdmi_Ops_t;

/** Register the HDMI lower-level (device specific) driver with
    phStbHdmi, and register a videodenc.
    @param Hdmi_funcs @b IN Function pointers
*/
extern int phStbHdmi_Register(phStbHdmi_Ops_t Hdmi_funcs);

/** Enable audio.
    @retval -ENOSYS If no HDMI device registered successfully. */
extern int phStbHdmi_EnableAudio(void);

/** Disable audio.
    @retval -ENOSYS If no HDMI device registered successfully. */
extern int phStbHdmi_DisableAudio(void);

/** Set audio rate.
    @retval TM_ERR_NOT_SUPPORTED If no HDMI device registered successfully. */
extern tmErrorCode_t phStbHdmi_SetAudioRate(phStbHdmi_afs_t audioRate);

/** Get audio capabilities.
    @retval TM_ERR_NOT_SUPPORTED If no HDMI device registered successfully. */
extern tmErrorCode_t phStbHdmi_GetAudioCap(phStbHdmi_audio_cap_t *pAudioCap);

/** Set audio features.
    @retval TM_ERR_NOT_SUPPORTED If no HDMI device registered successfully. */
extern tmErrorCode_t phStbHdmi_SetAudio(phStbHdmi_aud_t *pStrAudio);

/** Register HDMI status change callback
    @retval TM_ERR_NOT_SUPPORTED If no HDMI device registered successfully. */
extern tmErrorCode_t phStbHdmi_RegisterStatusCallback(void (*pCallback) (unsigned long status));

/** Unregister HDMI status change callback
    @retval TM_ERR_NOT_SUPPORTED If no HDMI device registered successfully. */
extern tmErrorCode_t phStbHdmi_UnRegisterStatusCallback(void);

/** Call to initialize HDMI device AFTER the video denc/Vo output is stable
    @retval TM_ERR_NOT_SUPPORTED If no HDMI device registered successfully. */
extern tmErrorCode_t phStbHdmi_InitializeHDMIDevice(void);

/** Return true if the HDMI device is capable of supporting multi-channel audio, false otherwise
    @retval false If no HDMI device registered successfully. */
extern int phStbHdmi_MultiChannelPCMSupported(void);

#endif

#if defined(__cplusplus)
}
#endif
#endif /* __PHSTBHDMI_H__ */

