//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.


Module Name:    HWCTXT.H

Abstract:        Platform dependent code for the mixing audio driver.

Environment:    Samsung S5PV210 CPU and Windows 5.0 (or later)

-*/

#pragma once

#include <windows.h>
#include <pm.h>
#include <pmplatform.h>
#include <register_map.h>

#include <bsp.h>
#include <ModeInterfaceLayer.h>
#include <LowPowerableMode.h>
#include <NormalMode.h>

#include "WM8580.h"

//Temporary macro, this will be removed.
#define WM8580_MAX_REGISTER_COUNT 54
#define IIC_MUTEX_NAME   (TEXT("IIC_MUTEX"))
#define IIC_MUTEX_TIMEOUT  (5000)    // 5000 ms

typedef class HardwareContext
{
public:
    static BOOL CreateHWContext(DWORD Index);
    HardwareContext();
    ~HardwareContext();

    DWORD GetNumInputDevices()
    {
        return 1;
    }

    DWORD GetNumOutputDevices()
    {
        return 1;
    }

    DWORD GetNumMixerDevices()
    {
        return 1;
    }

    DeviceContext *GetInputDeviceContext(UINT DeviceId)
    {
        return &m_InputDeviceContext;
    }

    DeviceContext *GetOutputDeviceContext(UINT DeviceId)
    {
        return &m_OutputDeviceContext;
    }

    DWORD       GetOutputGain (void);
    MMRESULT    SetOutputGain (DWORD dwVolume);
    DWORD       GetInputGain (void);
    MMRESULT    SetInputGain (DWORD dwVolume);

    BOOL        GetOutputMute (void);
    MMRESULT    SetOutputMute (BOOL fMute);
    BOOL        GetInputMute (void);
    MMRESULT    SetInputMute (BOOL fMute);

    DWORD       ForceSpeaker (BOOL bSpeaker);
    
protected:
    void SetSpeakerEnable(BOOL bEnable);    

    DWORD m_dwOutputGain;
    DWORD m_dwInputGain;
    BOOL  m_bInputMute;
    BOOL  m_bOutputMute;
    
    USHORT m_shInputVolumeL;
    USHORT m_shInputVolumeR;
    LONG m_NumForcedSpeaker;

protected: // CODEC
    HANDLE      m_hI2CCodec;
    
    BOOL        InitIISCodec();
    VOID        WriteCodecRegister(WORD wReg, WORD wVal);
    WORD        ReadCodecRegister(WORD wReg);
    BOOL        CodecPowerControl(BOOL bOnTxPwr, BOOL bOnRxPwr);
    BOOL        CodecMuteControl(DWORD channel, BOOL bMute);    

    //CODEC SPECIFIC
    USHORT      m_WM8580_SFR_Table[WM8580_MAX_REGISTER_COUNT];
    void        I2S_Init8580Driver();
    void        WM8580_CodecInitPCMOutwithVol(
                                                        CODECport eCodecPort,
                                                        I2SOPMode eCodecOpmode,//slave(AP is master), master(AP is slave)
                                                        SerialDataFormat eFormat,//i2s
                                                        UINT32 uSampleRate,
                                                        UINT8 uBitsPerSample,
                                                        I2S_RFSLength	eMasterRFS,//when codec is master
                                                        UINT8 uVol);
    
    void        WM8580_CodecPrimOutMasterNoPLL(UINT32 uMasterRFSBFS, UINT32  uBitsFormat, UINT32 uR16, UINT8 uVol);
    void        WM8580_CodecPrimOutSlaveNoPLL(UINT32 uBitsFormat, UINT32 uR16,  UINT8 uVol);
private: //mode interface
    CRITICAL_SECTION        m_csLock;
    HANDLE                  m_hWaveEvent;
    DWORD                   m_DriverIndex;
    BOOL                    m_bInitialized;
    BOOL                    m_bDVFSFixed;
    BOOL                    m_bEnableLowPower;
    BOOL                    m_bEnableCodecMaster;	
    BOOL                    m_bSRAMSet;
    BOOL                    m_bULPARunning;

    HANDLE                  m_hPowerCon;
    HANDLE                  m_hPwrMsgQue;
    CEDEVICE_POWER_STATE    m_PowerState;
    
    volatile PIIS_REG       m_pIISReg;
    volatile PASS_CLK_REG   m_pASSClkReg;
    volatile PASS_CBOX3_REG m_pASSCommBoxReg;
    volatile PGPIO_REG      m_pGPIOReg;
    volatile PCMU_CLK_REG   m_pSysConReg;
    volatile PPMU_MISC_REG  m_pPMUMiscReg;
    volatile BSP_ARGS *     m_pBSPArgs;

    InputDeviceContext      m_InputDeviceContext;
    OutputDeviceContext     m_OutputDeviceContext;
    POutLowPowerableMode    m_pOutLowPowerableMode;
    POutNormalMode          m_pOutNormalMode;
    PInNormalMode           m_pInNormalMode;
    PInModeInterfaceLayer   m_pCurrentInMode;
    POutModeInterfaceLayer  m_pCurrentOutMode;

    static HardwareContext *pBaseClass;
    
private:    
    BOOL        MapRegisters(VOID);
    BOOL        UnMapRegisters(VOID);
    void        PowerUp(VOID);
    void        PowerDown(VOID);
    BOOL        ClockPathEnable(VOID);
    
public: //mode interface
    BOOL        Initialize(DWORD Index);
    BOOL        Deinitialize(VOID);
    DWORD       Open(VOID);
    DWORD       Close(VOID);
    BOOL        IOControl(DWORD  dwOpenData,
                            DWORD  dwCode,
                            PBYTE  pBufIn,
                            DWORD  dwLenIn,
                            PBYTE  pBufOut,
                            DWORD  dwLenOut,
                            PDWORD pdwActualOut);    
    VOID        StartOutputDMA(VOID);
    VOID        StopOutputDMA(VOID);
    VOID        StartInputDMA(VOID);
    VOID        StopInputDMA(VOID);

    //Macro Function
    void 
    Lock(VOID)
    {
        EnterCriticalSection(&m_csLock);
    }

    void 
    Unlock(VOID)
    {
        LeaveCriticalSection(&m_csLock);
    }
    
    DWORD 
    GetSupportablePowerState(VOID) 
    {
        return (DX_MASK(D0) | DX_MASK(D2) | DX_MASK(D4));
    }

    PPInModeInterfaceLayer
    GetCurrInModeInterface(VOID)
    {
        return &m_pCurrentInMode;
    }

    PPOutModeInterfaceLayer
    GetCurrOutModeInterface(VOID)
    {
        return &m_pCurrentOutMode;
    }

    VOID InitBasePointer(HardwareContext * pBase)
    {
        HardwareContext::pBaseClass = pBase;
    }
    
    static VOID 
    BaseStartOutputDMA(VOID)
    {
        pBaseClass->StartOutputDMA();
    }

    static VOID 
    BaseStopOutputDMA(VOID)
    {
        pBaseClass->StopOutputDMA();
    }    

    static VOID 
    BaseStartInputDMA(VOID)
    {
        pBaseClass->StartInputDMA();
    }

    static VOID 
    BaseStopInputDMA(VOID)
    {
        pBaseClass->StopInputDMA();
    }     

    CEDEVICE_POWER_STATE SetPowerState(CEDEVICE_POWER_STATE requestState);
    CEDEVICE_POWER_STATE GetPowerState(VOID);
}*PHardwareContext;

extern PHardwareContext g_pHWContext;

