⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wm8753audio.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 3 页
字号:
            break;

        default:
            status = WMS_UNSUPPORTED;
            goto error;
    }

    /*
     * Work out our settings based on the interface.
     */
    if ( WM_AUDIOIF_HIFI == audioIF )
    {
        isMaster = WM_AUDIOIF_DEFAULT_HIFI_IS_MASTER;
        format = WM_AUDIOIF_DEFAULT_HIFI_FORMAT;
        width = WM_AUDIOIF_DEFAULT_HIFI_WIDTH;
        flags = WM_AUDIOIF_DEFAULT_HIFI_FLAGS;
        configuredFlag = WM_AUDIO_HIFI_CONFIGURED;
    }
    else
    {
        isMaster = WM_AUDIOIF_DEFAULT_VOICE_IS_MASTER;
        format = WM_AUDIOIF_DEFAULT_VOICE_FORMAT;
        width = WM_AUDIOIF_DEFAULT_VOICE_WIDTH;
        flags = WM_AUDIOIF_DEFAULT_VOICE_FLAGS;
        configuredFlag = WM_AUDIO_VOICE_CONFIGURED;
    }

    /*
     * Configure the interface if we haven't already done so.
     */
    if ( !pDeviceContext->v_pWMData || 
         !(pDeviceContext->v_pWMData->audioData.flags & configuredFlag)
       )
    {
        status = WMAudioConfigureInterface( hDevice,
                                            audioIF,
                                            isMaster,
                                            format,
                                            width,
                                            flags
                                          );
        if ( WM_ERROR( status ) )
        {
            WM_TRACE( hDevice,
                      ( "WM8753EnableStream: WMAudioConfigureInterface failed: %s",
                        WMStatusText( status )
                      )
                    );
            goto error;
        }
        
        WM_ASSERT( hDevice,
                   WMS_RETURN_TRUE == WMAudioIsInterfaceConfigured( hDevice, audioIF )
                 );
    }
    
    return WMS_SUCCESS;
    
error:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    WM8753DisableStream
 *
 * Called to disable the given stream.  This unconfigures the interface.
 *
 * Parameters:
 *      hDevice         handle to the device (from WMOpenDevice)
 *      stream          The stream to enable
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h.
 *---------------------------------------------------------------------------*/
WMSTATUS WM8753DisableStream( WM_DEVICE_HANDLE hDevice,
                              WM_STREAM_ID     stream
							)
{
    WM_DEVICE_CONTEXT   *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
    WMSTATUS            status, enabled;
    WM_AUDIO_INTERFACE  audioIF;
    
    /*
     * Work out our which interface we need.
     */
    switch ( stream )
    {
        case WM_STREAM_HIFI_OUT:
            enabled = WMAudioIsStreamEnabled( hDevice, WM_STREAM_HIFI_IN );
            if ( WMS_RETURN_FALSE == enabled )
                audioIF = WM_AUDIOIF_HIFI;
            else
                audioIF = WM_AUDIOIF_NONE;
            break;

        case WM_STREAM_HIFI_IN:
            if ( !IS_VOICE_ENABLED( pDeviceContext ) )
            {
                /* 
                 * We're set up for HiFi only.
                 */
                enabled = WMAudioIsStreamEnabled( hDevice, WM_STREAM_HIFI_OUT );
                if ( WMS_RETURN_FALSE == enabled )
                    audioIF = WM_AUDIOIF_HIFI;
                else
                    audioIF = WM_AUDIOIF_NONE;
                break;
            }
            
            /*
             * Else we're set up for HiFi DAC + voice codec => "HiFi in" is really
             * voice in.  Fall through.
             */
        case WM_STREAM_VOICE_IN:
            enabled = WMAudioIsStreamEnabled( hDevice, WM_STREAM_VOICE_OUT );
            if ( WMS_RETURN_FALSE == enabled )
                audioIF = WM_AUDIOIF_VOICE;
            else
                audioIF = WM_AUDIOIF_NONE;
            break;
            
        case WM_STREAM_VOICE_OUT:
            enabled = WMAudioIsStreamEnabled( hDevice, WM_STREAM_VOICE_IN );
            if ( WMS_RETURN_FALSE == enabled )
                audioIF = WM_AUDIOIF_VOICE;
            else
                audioIF = WM_AUDIOIF_NONE;
            break;

        default:
            status = WMS_UNSUPPORTED;
            goto error;
    }

    /*
     * Unconfigure the interface, if it's not still in use.
     */
    if ( WM_AUDIOIF_NONE != audioIF )
    {
    	status = WMAudioUnconfigureInterface( hDevice,
                                              audioIF
                                            );
        if ( WM_ERROR( status ) )
        {
            WM_TRACE( hDevice,
                      ( "WM8753DisableStream: WMAudioUnconfigureInterface failed: %s",
                        WMStatusText( status )
                      )
                    );
            goto error;
        }
        
        WM_ASSERT( hDevice,
                   WMS_RETURN_FALSE == WMAudioIsInterfaceConfigured( hDevice, audioIF )
                 );
    }
        
    return WMS_SUCCESS;
    
error:
    return status;
}

#if WM_VOICE && defined( DEBUG )
/*-----------------------------------------------------------------------------
 * Function:    WM8753VoiceDumpRegs
 *
 * Dump all the Voice DAC related registers
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *
 * Returns:     none
 *---------------------------------------------------------------------------*/
void WM8753VoiceDumpRegs( WM_DEVICE_HANDLE hDevice )
{
    WM_REGVAL reg = 0;

    WM_TRACE( hDevice, ("  WM8753 Voice DAC Reg Dump") );
    WM_TRACE( hDevice, ("-----------------------------") );

    WMRead( hDevice, WM8753_VOICE_AUDIO_INTERFACE, &reg );

    WM_TRACE( hDevice, ("Voice Audio Interface 0x03 = 0x%04X", reg ) );

    WMRead( hDevice, WM8753_INTERFACE_CONTROL, &reg );

    WM_TRACE( hDevice, ("Interface Control 0x05 = 0x%04X", reg ) );

    WMRead( hDevice, WM8753_SAMPLE_RATE_CTRL_1, &reg );

    WM_TRACE( hDevice, ("Sample Rate Control 1 0x06 = 0x%04X", reg ) );

    WMRead( hDevice, WM8753_SAMPLE_RATE_CTRL_2, &reg );

    WM_TRACE( hDevice, ("Sample Rate Control 2 0x07 = 0x%04X", reg ) );

    WMRead( hDevice, WM8753_CLOCK_CONTROL, &reg );

    WM_TRACE( hDevice, ("Clock Control 0x34 = 0x%04X", reg ) );

    WMRead( hDevice, WM8753_PLL2_CONTROL_1, &reg );

    WM_TRACE( hDevice, ("PLL2 Control 1 0x39 = 0x%04X", reg ) );

    WMRead( hDevice, WM8753_PLL2_CONTROL_2, &reg );

    WM_TRACE( hDevice, ("PLL2 Control 2 0x3A = 0x%04X", reg ) );

    WMRead( hDevice, WM8753_PLL2_CONTROL_3, &reg );

    WM_TRACE( hDevice, ("PLL2 Control 3 0x3B = 0x%04X", reg ) );

    WMRead( hDevice, WM8753_PLL2_CONTROL_4, &reg );

    WM_TRACE( hDevice, ("PLL2 Control 4 0x3C = 0x%04X", reg ) );

    WMPlatformDumpSSP2Regs( hDevice );
}
#endif /* WM_VOICE && DEBUG */

/*-----------------------------------------------------------------------------
 * Function:    private_ConfigurePLL
 *
 * Configures the PLL for the given frequency.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *      WM8753_PLL  the PLL to configure
 *      targetFreq  the target output frequency
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
static WMSTATUS private_ConfigurePLL( WM_DEVICE_HANDLE   hDevice,
                                      WM8753_PLL         pll,
                                      unsigned int       targetFreq
                                    )
{
    WMSTATUS    status;
    int         N, K;
    WM_BOOL     divMclk;
    WM_REGTYPE  baseReg;
    WM_REGVAL   controlVal;

    /*
     * Work out our base register.
     */
    if ( WM8753_PLL1 == pll )
    {
        baseReg = WM8753_PLL1_CONTROL_1;
    }
    else
    {
        baseReg = WM8753_PLL2_CONTROL_1;
    }
    
    /*
     * Set our coefficients.
     */
    private_calcPLLCoefficients( WM_MCLK_FREQUENCY,
                                 targetFreq,
                                 &N,
                                 &K,
                                 &divMclk
                               );
    status = WMWrite( hDevice, baseReg + 1 , WM8753_PLL_R2VAL( N, K ) );
    if ( WM_ERROR( status ) )
    {
        goto error;
    }
    status = WMWrite( hDevice, baseReg + 2 , WM8753_PLL_R3VAL( N, K ) );
    if ( WM_ERROR( status ) )
    {
        goto error;
    }
    status = WMWrite( hDevice, baseReg + 3 , WM8753_PLL_R4VAL( N, K ) );
    if ( WM_ERROR( status ) )
    {
        goto error;
    }
    
    /*
     * Now set up the PLL.
     */
    controlVal = WM8753_PLL_ENABLE         |
                 WM8753_PLL_ACTIVE         |
                 WM8753_PLLOUT_DIV2        |
                 WM8753_CLOCKOUT_PLL;
    if ( divMclk )
        controlVal |= WM8753_MCLK_DIV2;
        
    status = WMWrite( hDevice, baseReg, controlVal );
    if ( WM_ERROR( status ) )
    {
        goto error;
    }

    /*
     * And enable the bits in clock control.
     */
    if ( WM8753_PLL1 == pll )
    {
        status = WMSetField( hDevice,
                             WM8753_CLOCK_CONTROL,
                             ( WM8753_MCLKSEL_PLL1 |
                               WM8753_GP1CLK1_CLOCK ),
                             ( WM8753_MCLKSEL_MASK |
                               WM8753_GP1CLK1_MASK )
                            );
    }
    else
    {
        status = WMSetField( hDevice,
                             WM8753_CLOCK_CONTROL,
                             ( WM8753_PCMCLKSEL_PLL2 |
                               WM8753_VXCLOCK_PLL2   |
                               WM8753_GP2CLK2_CLOCK ),
                             ( WM8753_PCMCLKSEL_MASK |
                               WM8753_VXCLOCK_MASK   |
                               WM8753_GP2CLK2_MASK )
                            );
    }
    if ( WM_ERROR( status ) )
    {
        goto error;
    }
    
    /*
     * And we're done.
     */
    return WMS_SUCCESS;
    
error:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    private_calcPLLCoefficients
 *
 * Calculates the PLL coefficients for the given MCLK and target frequency.
 *
 * Parameters:
 *      MCLKFreq    the MCLK frequency
 *      targetFreq  the target output frequency
 *      pN          variable to receive N value
 *      pK          variable to receive K value
 *      pDivMclk    variable to receive whether to use MCLK/2 instead of MCLK
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
static void private_calcPLLCoefficients( unsigned int   MCLKFreq,
                                         unsigned int   targetFreq,
                                         int            *pN,
                                         int            *pK,
                                         WM_BOOL        *pDivMclk
                                       )
{
    double  multiplier;
    double  fraction;

    /* Use MCLK/2 if freq > 15MHz */    
    if ( MCLKFreq > 15000000 )
    {
        multiplier = 16.0;
        *pDivMclk = TRUE;
    }
    else
    {
        multiplier = 8.0;
        *pDivMclk = FALSE;
    }
        
    /* Work out the fraction */
    fraction = multiplier * targetFreq / (double) MCLKFreq;
    
    /* Now convert to N and K values */
    *pN = (int) fraction;
    *pK = (int) ((((double) PLL_K_BASE) * (fraction - (double) *pN)) + 0.5);
}

#if WM_TESTING
/*-----------------------------------------------------------------------------
 * Function:    WMTest8753Internals
 *
 * This function tests the internal code in WM8753Audio.c.
 *
 * Parameters:
 *      hDevice     device handle to use
 *
 * Returns:     WM_BOOL
 *      TRUE iff it worked.
 *---------------------------------------------------------------------------*/
WMTEST_START( WMTest8753Internals( WM_DEVICE_HANDLE hDevice ) )
{
    unsigned int coeff;
    
    /*
     * Test the PLL coefficients.
     */
    for ( coeff = 0; coeff < WM_ARRAY_COUNT( s_PLLCoeffs ); coeff++ )
    {
        int     N, K;
        WM_BOOL divMclk;
        
        const PLLCoeffTest *pTest = &s_PLLCoeffs[coeff];
        private_calcPLLCoefficients( pTest->MCLKFreq,
                                     pTest->targetFreq,
                                     &N,
                                     &K,
                                     &divMclk
                                   );
        WMTEST_EQUALS( N, pTest->N );
        WMTEST_EQUALS( K, pTest->K );
        WMTEST_LESS_EQUAL( divMclk, pTest->divMclk );
    }
}
WMTEST_END

#endif  /* WM_TESTING */

#endif  /* WM_AUDIO && WM8753_FAMILY */

/*------------------------------ END OF FILE ---------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -