root/src/add-ons/kernel/drivers/audio/echo/generic/CGMLDspCommObject.cpp
// ****************************************************************************
//
//      CGMLDspCommObject.cpp
//
//              Implementation file for GML cards (Gina24, Mona, and Layla24).
//
// ----------------------------------------------------------------------------
//
// This file is part of Echo Digital Audio's generic driver library.
// Copyright Echo Digital Audio Corporation (c) 1998 - 2005
// All rights reserved
// www.echoaudio.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// ****************************************************************************

#include "CEchoGals.h"
#include "CGMLDspCommObject.h"

//===========================================================================
//
// Set the S/PDIF output format
// 
//===========================================================================

void CGMLDspCommObject::SetProfessionalSpdif
(
        BOOL bNewStatus
)
{
        DWORD           dwControlReg;

        dwControlReg = GetControlRegister();

        //
        // Clear the current S/PDIF flags
        //
        dwControlReg &= GML_SPDIF_FORMAT_CLEAR_MASK;

        //
        // Set the new S/PDIF flags depending on the mode
        //      
        dwControlReg |=         GML_SPDIF_TWO_CHANNEL | 
                                                        GML_SPDIF_24_BIT |
                                                        GML_SPDIF_COPY_PERMIT;
        if ( bNewStatus )
        {
                //
                // Professional mode
                //
                dwControlReg |= GML_SPDIF_PRO_MODE;
                
                switch ( GetSampleRate() )
                {
                        case 32000 : 
                                dwControlReg |= GML_SPDIF_SAMPLE_RATE0 |
                                                                         GML_SPDIF_SAMPLE_RATE1;
                                break;
                                
                        case 44100 :
                                dwControlReg |= GML_SPDIF_SAMPLE_RATE0;
                                break;
                        
                        case 48000 :
                                dwControlReg |= GML_SPDIF_SAMPLE_RATE1;
                                break;
                }
        }
        else
        {
                //
                // Consumer mode
                //
                switch ( GetSampleRate() )
                {
                        case 32000 : 
                                dwControlReg |= GML_SPDIF_SAMPLE_RATE0 |
                                                                         GML_SPDIF_SAMPLE_RATE1;
                                break;
                                
                        case 48000 :
                                dwControlReg |= GML_SPDIF_SAMPLE_RATE1;
                                break;
                }
        }
        
        //
        // Handle the non-audio bit
        //
        if (m_bNonAudio)
                dwControlReg |= GML_SPDIF_NOT_AUDIO;
        
        //
        // Write the control reg
        //
        WriteControlReg( dwControlReg );

        m_bProfessionalSpdif = bNewStatus;
        
        ECHO_DEBUGPRINTF( ("CGMLDspCommObject::SetProfessionalSpdif to %s\n",
                                                        ( bNewStatus ) ? "Professional" : "Consumer") );

}       // void CGMLDspCommObject::SetProfessionalSpdif( ... )




//===========================================================================
//
// SetSpdifOutNonAudio
//
// Set the state of the non-audio status bit in the S/PDIF out status bits
// 
//===========================================================================

void CGMLDspCommObject::SetSpdifOutNonAudio(BOOL bNonAudio)
{
        DWORD           dwControlReg;

        dwControlReg = GetControlRegister();
        if (bNonAudio)
        {
                dwControlReg |= GML_SPDIF_NOT_AUDIO;
        }
        else
        {
                dwControlReg &= ~GML_SPDIF_NOT_AUDIO;
        }
        
        m_bNonAudio = bNonAudio;
        
        WriteControlReg( dwControlReg );        
}       



//===========================================================================
//
// WriteControlReg
//
// Most configuration of Gina24, Layla24, or Mona is
// accomplished by writing the control register.  WriteControlReg 
// sends the new control register value to the DSP.
// 
//===========================================================================

ECHOSTATUS CGMLDspCommObject::WriteControlReg
( 
        DWORD dwControlReg,
        BOOL    fForceWrite
)
{
        ECHO_DEBUGPRINTF(("CGMLDspCommObject::WriteControlReg 0x%lx\n",dwControlReg));

        if ( !m_bASICLoaded )
        {
                ECHO_DEBUGPRINTF(("CGMLDspCommObject::WriteControlReg - ASIC not loaded\n"));
                return( ECHOSTATUS_ASIC_NOT_LOADED );
        }
                

        if ( !WaitForHandshake() )
        {
                ECHO_DEBUGPRINTF(("CGMLDspCommObject::WriteControlReg - no handshake\n"));
                return ECHOSTATUS_DSP_DEAD;
        }

#ifdef DIGITAL_INPUT_AUTO_MUTE_SUPPORT  
        //
        // Handle the digital input auto-mute
        //      
        if (TRUE == m_fDigitalInAutoMute)
                dwControlReg |= GML_DIGITAL_IN_AUTO_MUTE;
        else
                dwControlReg &= ~GML_DIGITAL_IN_AUTO_MUTE;
#endif

        //
        // Write the control register
        //
        if (fForceWrite || (dwControlReg != GetControlRegister()) )
        {
                SetControlRegister( dwControlReg );

                ECHO_DEBUGPRINTF( ("CGMLDspCommObject::WriteControlReg: Setting 0x%lx\n",
                                                                 dwControlReg) );
                                                                 
                ClearHandshake();                                                        
                return SendVector( DSP_VC_WRITE_CONTROL_REG );
        }
        else
        {
                ECHO_DEBUGPRINTF( ("CGMLDspCommObject::WriteControlReg: control reg is already 0x%lx\n",
                                                                 dwControlReg) );
        }
        
        return ECHOSTATUS_OK;
        
} // ECHOSTATUS CGMLDspCommObject::WriteControlReg( DWORD dwControlReg )

//===========================================================================
//
// SetDigitalMode
// 
//===========================================================================

ECHOSTATUS CGMLDspCommObject::SetDigitalMode
(
        BYTE    byNewMode
)
{
        WORD            wInvalidClock;
        
        //
        // See if the current input clock doesn't match the new digital mode
        //
        switch (byNewMode)
        {
                case DIGITAL_MODE_SPDIF_RCA :
                case DIGITAL_MODE_SPDIF_OPTICAL :
                        wInvalidClock = ECHO_CLOCK_ADAT;
                        break;
                        
                case DIGITAL_MODE_ADAT :
                        wInvalidClock = ECHO_CLOCK_SPDIF;
                        break;
                        
                default :
                        wInvalidClock = 0xffff;
                        break;
        }

        if (wInvalidClock == GetInputClock())
        {
                SetInputClock( ECHO_CLOCK_INTERNAL );
                SetSampleRate( 48000 );
        }

        //
        // Clear the current digital mode
        //
        DWORD dwControlReg;
        
        dwControlReg = GetControlRegister();
        dwControlReg &= GML_DIGITAL_MODE_CLEAR_MASK;

        //
        // Tweak the control reg
        //
        switch ( byNewMode )
        {
                case DIGITAL_MODE_SPDIF_RCA :
                        break;
                        
                case DIGITAL_MODE_SPDIF_OPTICAL :
                        dwControlReg |= GML_SPDIF_OPTICAL_MODE;
                        break;
                
                case DIGITAL_MODE_ADAT :
                        dwControlReg |= GML_ADAT_MODE;
                        dwControlReg &= ~GML_DOUBLE_SPEED_MODE;
                        break;  

                default :
                        return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED;
        }
        
        //
        // Write the control reg
        //
        WriteControlReg( dwControlReg );

        m_byDigitalMode = byNewMode;

        ECHO_DEBUGPRINTF( ("CGMLDspCommObject::SetDigitalMode to %ld\n",
                                                        (DWORD) m_byDigitalMode) );

        return ECHOSTATUS_OK;

}       // ECHOSTATUS CGMLDspCommObject::SetDigitalMode


// **** CGMLDspCommObject.cpp ****