/*---------------------------------------------------------------------------*
  Project:  TwlSDK - include - dsp
  File:     dsp_if.h

  Copyright 2007-2008 Nintendo. All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law. They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Date:: 2008-09-17#$
  $Rev: 8556 $
  $Author: okubata_ryoma $
 *---------------------------------------------------------------------------*/

#ifndef TWL_DSP_IF_H_
#define TWL_DSP_IF_H_

#include <twl/types.h>
#include <twl/hw/ARM9/ioreg_DSP.h>
#include <nitro/os/common/emulator.h>

#ifdef __cplusplus
extern "C" {
#endif

/*===========================================================================*/

/*---------------------------------------------------------------------------*
    Constant Definitions
 *---------------------------------------------------------------------------*/
typedef enum
{
    DSP_FIFO_MEMSEL_DATA    = (0x0 << REG_DSP_PCFG_MEMSEL_SHIFT),
    DSP_FIFO_MEMSEL_MMIO    = (0x1 << REG_DSP_PCFG_MEMSEL_SHIFT),
    DSP_FIFO_MEMSEL_PROGRAM = (0x5 << REG_DSP_PCFG_MEMSEL_SHIFT)
}
DSPFifoMemSel;

typedef enum
{
    DSP_FIFO_RECV_2B            = (0x0 << REG_DSP_PCFG_DRS_SHIFT),
    DSP_FIFO_RECV_16B           = (0x1 << REG_DSP_PCFG_DRS_SHIFT),
    DSP_FIFO_RECV_32B           = (0x2 << REG_DSP_PCFG_DRS_SHIFT),
    DSP_FIFO_RECV_CONTINUOUS    = (0x3 << REG_DSP_PCFG_DRS_SHIFT)
}
DSPFifoRecvLength;

typedef enum
{
    DSP_FIFO_INTR_SEND_EMPTY        = REG_DSP_PCFG_WFEIE_MASK,
    DSP_FIFO_INTR_SEND_FULL         = REG_DSP_PCFG_WFFIE_MASK,
    DSP_FIFO_INTR_RECV_NOT_EMPTY    = REG_DSP_PCFG_RFNEIE_MASK,
    DSP_FIFO_INTR_RECV_FULL         = REG_DSP_PCFG_RFFIE_MASK
}
DSPFifoIntr;

// for complex API
typedef enum
{
    DSP_FIFO_FLAG_SRC_INC   = (0UL << 0),
    DSP_FIFO_FLAG_SRC_FIX   = (1UL << 0),

    DSP_FIFO_FLAG_DEST_INC  = (0UL << 1),
    DSP_FIFO_FLAG_DEST_FIX  = (1UL << 1),

    DSP_FIFO_FLAG_RECV_UNIT_CONTINUOUS  = (0UL << 8),
    DSP_FIFO_FLAG_RECV_UNIT_2B          = (1UL << 8),
    DSP_FIFO_FLAG_RECV_UNIT_16B         = (2UL << 8),
    DSP_FIFO_FLAG_RECV_UNIT_32B         = (3UL << 8),
    DSP_FIFO_FLAG_RECV_MASK             = (3UL << 8)
}
DSPFifoFlag;

// Support the load process for old specifications a little longer.
#define DSP_SUPPORT_OBSOLETE_LOADER

/*---------------------------------------------------------------------------*
    Structure Definitions
 *---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*
    Function Definitions
 *---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*
  Name:         DSP_PowerOn

  Description:  Turn on power to the DSP block but do not reset it yet.
                You should call DSP_ResetOff() to boot the DSP.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_PowerOnCore(void);
SDK_INLINE void DSP_PowerOn(void)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_PowerOnCore();
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_PowerOff

  Description:  Turns off power to the DSP block.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_PowerOffCore(void);
SDK_INLINE void DSP_PowerOff(void)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_PowerOffCore();
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_ResetOn

  Description:  Resets the DSP.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_ResetOnCore(void);
SDK_INLINE void DSP_ResetOn(void)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_ResetOnCore();
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_ResetOff

  Description:  Boots the DSP if it is in the Reset state.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_ResetOffCore(void);
SDK_INLINE void DSP_ResetOff(void)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_ResetOffCore();
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_ResetOffEx

  Description:  Boots the DSP if it is in the Reset state.

  Arguments:    bitmap: Enables interrupts for receiving data from a DSP bitmap.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_ResetOffExCore(u16 bitmap);
SDK_INLINE void DSP_ResetOffEx(u16 bitmap)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_ResetOffExCore(bitmap);
    }
}


/*---------------------------------------------------------------------------*
  Name:         DSP_ResetInterface

  Description:  Resets the interface registers.
                This should be called from the Reset state.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_ResetInterfaceCore(void);
SDK_INLINE void DSP_ResetInterface(void)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_ResetInterfaceCore();
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_EnableRecvDataInterrupt

  Description:  Enables interrupts for receiving data from the DSP.

  Arguments:    dataNo:     Target data register (0-2)

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_EnableRecvDataInterruptCore(u32 dataNo);
SDK_INLINE void DSP_EnableRecvDataInterrupt(u32 dataNo)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_EnableRecvDataInterruptCore(dataNo);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_DisableRecvDataInterrupt

  Description:  Disables interrupts for receiving data from the DSP.

  Arguments:    dataNo:     Target data register (0-2)

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_DisableRecvDataInterruptCore(u32 dataNo);
SDK_INLINE void DSP_DisableRecvDataInterrupt(u32 dataNo)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_DisableRecvDataInterruptCore(dataNo);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_SendDataIsEmpty

  Description:  Whether the DSP received data that has been sent.

  Arguments:    dataNo:     Target data register (0-2)

  Returns:      None.
 *---------------------------------------------------------------------------*/
BOOL DSP_SendDataIsEmptyCore(u32 dataNo);
SDK_INLINE BOOL DSP_SendDataIsEmpty(u32 dataNo)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        return DSP_SendDataIsEmptyCore(dataNo);
    }
    return FALSE;
}

/*---------------------------------------------------------------------------*
  Name:         DSP_RecvDataIsReady

  Description:  Whether data has been sent from the DSP.

  Arguments:    dataNo:     Target data register (0-2)

  Returns:      None.
 *---------------------------------------------------------------------------*/
BOOL DSP_RecvDataIsReadyCore(u32 dataNo);
SDK_INLINE BOOL DSP_RecvDataIsReady(u32 dataNo)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        return DSP_RecvDataIsReadyCore(dataNo);
    }
    return FALSE;
}

/*---------------------------------------------------------------------------*
  Name:         DSP_SendData

  Description:  Sends data to the DSP.

  Arguments:    dataNo:     Target data register (0-2)
                data:       data to send

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_SendDataCore(u32 dataNo, u16 data);
SDK_INLINE void DSP_SendData(u32 dataNo, u16 data)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_SendDataCore(dataNo, data);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_RecvData

  Description:  Receives data from the DSP.

  Arguments:    dataNo:     Target data register (0-2)

  Returns:      The received data.
 *---------------------------------------------------------------------------*/
u16 DSP_RecvDataCore(u32 dataNo);
SDK_INLINE u16 DSP_RecvData(u32 dataNo)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        return DSP_RecvDataCore(dataNo);
    }
    return 0;
}

/*---------------------------------------------------------------------------*
  Name:         DSP_EnableFifoInterrupt

  Description:  Enables FIFO interrupts.

  Arguments:    type:       One of the DSPFifoIntr values

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_EnableFifoInterruptCore(DSPFifoIntr type);
SDK_INLINE void DSP_EnableFifoInterrupt(DSPFifoIntr type)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_EnableFifoInterruptCore(type);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_DisableFifoInterrupt

  Description:  Disables FIFO interrupts.

  Arguments:    type:       One of the DSPFifoIntr values

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_DisableFifoInterruptCore(DSPFifoIntr type);
SDK_INLINE void DSP_DisableFifoInterrupt(DSPFifoIntr type)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_DisableFifoInterruptCore(type);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_SendFifoEx

  Description:  Writes data to the DSP memory space.

  Arguments:    memsel: One of the DSPFifoMemSel values
                dest:   Destination address (in half words).
                        If you want to set the high address, ask the DSP to set
                        the DMA register.
                src:    Data to send.
                size:   Data length to send (in half words).
                flags:  Bitwise OR of DSPFifoFlag values to specify a special mode
                        without DSP_FIFO_FLAG_RECV_UNIT_*

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_SendFifoExCore(DSPFifoMemSel memsel, u16 dest, const u16 *src, int size, u16 flags);
SDK_INLINE void DSP_SendFifoEx(DSPFifoMemSel memsel, u16 dest, const u16 *src, int size, u16 flags)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_SendFifoExCore(memsel, dest, src, size, flags);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_SendFifo

  Description:  Writes data to the DSP memory space normally.

  Arguments:    memsel: One of the DSPFifoMemSel values
                dest:   Destination address (in half words).
                        If you want to set the high address, ask the DSP to set
                        the DMA register.
                src:    Data to send.
                size:   Data length to send (in half words).

  Returns:      None.
 *---------------------------------------------------------------------------*/
static inline void DSP_SendFifo(DSPFifoMemSel memsel, u16 dest, const u16 *src, int size)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_SendFifoExCore(memsel, dest, src, size, 0);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_RecvFifoEx

  Description:  Reads data from the DSP memory space.

  Arguments:    memsel: One of the DSPFifoMemSel values without a PROGRAM area
                dest:   Data to receive.
                src:    Source address (in half words).
                        If you want to set the high address, ask the DSP to set
                        the DMA register.
                size:   Data length to receive (in half words).
                        Ignored unless in continuous mode
                flags:  Bitwise OR of DSPFifoFlag values to specify a special mode

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_RecvFifoExCore(DSPFifoMemSel memsel, u16 *dest, u16 src, int size, u16 flags);
SDK_INLINE void DSP_RecvFifoEx(DSPFifoMemSel memsel, u16 *dest, u16 src, int size, u16 flags)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_RecvFifoExCore(memsel, dest, src, size, flags);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_RecvFifo

  Description:  Reads data from the DSP memory space normally.

  Arguments:    memsel: One of the DSPFifoMemSel values
                dest:   Data to receive.
                src:    Source address (in half words).
                        If you want to set the high address, ask the DSP to set
                        the DMA register.
                size:   Data length to receive (in half words).

  Returns:      None.
 *---------------------------------------------------------------------------*/
static inline void DSP_RecvFifo(DSPFifoMemSel memsel, u16* dest, u16 src, int size)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_RecvFifoExCore(memsel, dest, src, size, 0);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_SetCommandReg

  Description:  Sets the command register to signal to the DSP.

  Arguments:    data:       Data

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_SetCommandRegCore(u32 regNo, u16 data);
SDK_INLINE void DSP_SetCommandReg(u32 regNo, u16 data)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_SetCommandRegCore(regNo, data);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_GetReplyReg

  Description:  Gets the reply register to be received from the DSP.

  Arguments:    None.

  Returns:      data.
 *---------------------------------------------------------------------------*/
u16 DSP_GetReplyRegCore(u32 regNo);
SDK_INLINE u16 DSP_GetReplyReg(u32 regNo)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        return DSP_GetReplyRegCore(regNo);
    }
    return 0;
}

/*---------------------------------------------------------------------------*
  Name:         DSP_SetSemaphore

  Description:  Sets the semaphore to signal to the DSP.
                NOTE: The received semaphore is an individual register.

  Arguments:    mask:       Bit mask to set

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_SetSemaphoreCore(u16 mask);
SDK_INLINE void DSP_SetSemaphore(u16 mask)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_SetSemaphoreCore(mask);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_GetSemaphore

  Description:  Gets the semaphore to be received from the DSP.
                NOTE: The sent semaphore is an individual register

  Arguments:    None.

  Returns:      The bit mask set by the DSP
 *---------------------------------------------------------------------------*/
u16 DSP_GetSemaphoreCore(void);
SDK_INLINE u16 DSP_GetSemaphore(void)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        return DSP_GetSemaphoreCore();
    }
    return 0;
}

/*---------------------------------------------------------------------------*
  Name:         DSP_ClearSemaphore

  Description:  Clears the semaphore to be received from the DSP.

  Arguments:    mask:       Bit mask to clear

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_ClearSemaphoreCore(u16 mask);
SDK_INLINE void DSP_ClearSemaphore(u16 mask)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_ClearSemaphoreCore(mask);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_MaskSemaphore

  Description:  Masks semaphores to send interrupts to the ARM9.

  Arguments:    mask:       Bit mask to disable interrupts

  Returns:      None.
 *---------------------------------------------------------------------------*/
void DSP_MaskSemaphoreCore(u16 mask);
SDK_INLINE void DSP_MaskSemaphore(u16 mask)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        DSP_MaskSemaphoreCore(mask);
    }
}

/*---------------------------------------------------------------------------*
  Name:         DSP_CheckSemaphoreRequest

  Description:  Whether there is requested interrupt by a semaphore.

  Arguments:    None.

  Returns:      TRUE if requested.
 *---------------------------------------------------------------------------*/
BOOL DSP_CheckSemaphoreRequestCore(void);
SDK_INLINE BOOL DSP_CheckSemaphoreRequest(void)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        return DSP_CheckSemaphoreRequestCore();
    }
    return FALSE;
}

#if defined(DSP_SUPPORT_OBSOLETE_LOADER)
/*---------------------------------------------------------------------------*
 * The following is a discontinued candidate interface that is not thought to be used at the present
 *---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*
  Name:         DSP_LoadFileAuto

  Description:  Loads a DSP program in the COFF format and assigns the required WRAM to the DSP.

  Arguments:    image:     COFF file

  Returns:      TRUE if success
 *---------------------------------------------------------------------------*/
BOOL DSP_LoadFileAutoCore(const void *image);
SDK_INLINE BOOL DSP_LoadFileAuto(const void *image)
{
    if (OS_IsRunOnTwl() == TRUE)
    {
        return DSP_LoadFileAutoCore(image);
    }
    return FALSE;
}

#endif


/*===========================================================================*/

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* TWL_DSP_IF_H_ */
