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

📄 wm8753audio.c

📁 pxa270平台 windows mobile 5.2 wm9713 触摸屏+音频驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/*-----------------------------------------------------------------------------
 * Copyright (c) Wolfson Microelectronics plc.  All rights reserved.
 *
 * This software as well as any related documentation is furnished under 
 * license and may only be used or copied in accordance with the terms of the 
 * license. The information in this file is furnished for informational use 
 * only, is subject to change without notice, and should not be construed as 
 * a commitment by Wolfson Microelectronics plc. Wolfson Microelectronics plc
 * assumes no responsibility or liability for any errors or inaccuracies that
 * may appear in this document or any software that may be provided in
 * association with this document. 
 *
 * Except as permitted by such license, no part of this document may be 
 * reproduced, stored in a retrieval system, or transmitted in any form or by 
 * any means without the express written consent of Wolfson Microelectronics plc. 
 *
 * $Id: WM8753Audio.c 4477 2007-06-05 14:25:19Z fb $
 *
 * This file contains platform-independent routines for controlling the audio
 * operation on Wolfson codecs.
 *
 * Warning:
 *  This driver is specifically written for Wolfson Codecs. It is not a 
 *  general CODEC device driver.
 *
 * -----------------------------------------------------------------------------*/

/*
 * Include files
 */
#include "WMConfig.h"
#include "WMCommon.h"
#include "WMDevice.h"
#include "WMControlLink.h"
#include "WMPlatformI2S.h"
#include "WMPlatformSSP.h"
#include "WMPlatformDebug.h"
#include "WMGlobals.h"
#include "WM8753Audio.h"
#include "WM8753RegisterDefs.h"
#include "WMTestCommon.h"
#include "WMInternalTests.h"

/*
 * Only build this if we're doing Audio support for WM8753 devices.
 */
#if WM_AUDIO && WM8753_FAMILY

#ifndef WM_MCLK_FREQUENCY
    /*
     * We need to know our MCLK frequency.  This should be a value in Hz
     * such as 12000000 (for 12MHz).
     */
#   error Please define WM_MCLK_FREQUENCY (in Hz) in WMPlatformConfig.h
#endif

/*
 * Global definitions
 */

/*
 * The base for K, the fractional part of the fraction.
 */
#define PLL_K_BASE  (1U << 22)

/*
 * Which PLL to use.
 */
typedef enum tagWM8753_PLL
{
    WM8753_PLL1 = 1,
    WM8753_PLL2
} WM8753_PLL;

/*
 * A macro which works out whether the voice interface is enabled.
 */
#if WM_VOICE
#   define IS_VOICE_ENABLED( _pCtx )    \
        (_pCtx->v_pWMData->audioData.flags & WM_AUDIO_VOICE_CONFIGURED)
#else
#   define IS_VOICE_ENABLED( _pCtx )    FALSE
#endif

/*
 * A macro which works out which interface to use.
 * For HiFi playback it's HiFi.  For Voice anything it's voice.  For HiFi
 * record it's HiFi if there is no voice, otherwise it's Voice.
 */
#define STREAM_USES_HIFI( _stream, _pCtx )                                      \
    ( ( WM_STREAM_HIFI_OUT == _stream ) ||                                      \
      ( WM_STREAM_HIFI_IN == _stream && !( IS_VOICE_ENABLED(_pCtx) ) )          \
    )

/*
 * Private data
 */
typedef struct tagSampleRateSetting
{
    WM_SAMPLE_RATE  dacRate;        /* Requested DAC rate */
    WM_SAMPLE_RATE  adcRate;        /* Requested ADC rate */
    unsigned int    pllFreq;        /* PLL frequency required */
    WM_REGVAL       regSetting;     /* Value of WM8753_SAMPLERATE_MASK field
                                       or WM8753_VXCLK_DIV_MASK field */
} SampleRateSetting;

static const SampleRateSetting s_hifiRates[] =
{
    /* First the matched sample rates */
    {  8000,  8000, 12288000, 0x06 },
    { 11025, 11025, 11289600, 0x18 },
    { 12000, 12000, 12288000, 0x08 },
    { 16000, 16000, 12288000, 0x0A },
    { 22050, 22050, 11289600, 0x1A },
    { 24000, 24000, 12288000, 0x1C },
    { 32000, 32000, 12288000, 0x0C },
    { 44100, 44100, 11289600, 0x10 },
    { 48000, 48000, 12288000, 0x00 },
    { 88200, 88200, 11289600, 0x1E },
    { 96000, 96000, 12288000, 0x0E },
    /* Now the unmatched sample rates */
    {  8000, 44100, 11289600, 0x12 },
    {  8000, 48000, 12288000, 0x02 },
    { 44100,  8000, 11289600, 0x14 },
    { 48000,  8000, 12288000, 0x04 },
};

static const SampleRateSetting s_voiceRates[] =
{
    {  8000,  8000, 12288000, WM8753_VXCLK_DIV_6 },
    { 11025, 11025, 11289600, WM8753_VXCLK_DIV_4 },
    { 12000, 12000, 12288000, WM8753_VXCLK_DIV_4 },
    { 16000, 16000, 12288000, WM8753_VXCLK_DIV_3 },
    { 22050, 22050, 11289600, WM8753_VXCLK_DIV_2 },
    { 24000, 24000, 12288000, WM8753_VXCLK_DIV_2 },
    { 44100, 44100, 11289600, WM8753_VXCLK_DIV_1 },
    { 48000, 48000, 12288000, WM8753_VXCLK_DIV_1 },
};

#if WM_TESTING
typedef struct tagPLLCoeffTest
{
    unsigned int    MCLKFreq;
    unsigned int    targetFreq;
    int             N;
    int             K;
    WM_BOOL         divMclk;
} PLLCoeffTest;

static PLLCoeffTest s_PLLCoeffs[] = 
{
    { 11910000, 11289600, 7, 0x25545F, FALSE },
    { 11910000, 12288000, 8, 0x103FF8, FALSE },
    { 12000000, 11289600, 7, 0x21B08A, FALSE },
    { 12000000, 12288000, 8, 0x0C49BA, FALSE },
    { 13000000, 11289600, 6, 0x3CA2F5, FALSE },
    { 13000000, 12288000, 7, 0x23F54A, FALSE },
    { 14400000, 11289600, 6, 0x116873, FALSE },
    { 14400000, 12288000, 6, 0x34E81B, FALSE },
    { 19200000, 11289600, 9, 0x1A1CAC, TRUE },
    { 19200000, 12288000, 10, 0x0F5C29, TRUE },
    { 19680000, 11289600, 9, 0x0B6D25, TRUE },
    { 19680000, 12288000, 9, 0x3F6028, TRUE },
    { 19800000, 11289600, 9, 0x07DDBE, TRUE },
    { 19800000, 12288000, 9, 0x3B8028, TRUE },
    { 24000000, 11289600, 7, 0x21B08A, TRUE },
    { 24000000, 12288000, 8, 0x0C49BA, TRUE },
    { 26000000, 11289600, 6, 0x3CA2F5, TRUE },
    { 26000000, 12288000, 7, 0x23F54A, TRUE },
    { 27000000, 11289600, 6, 0x2C2B25, TRUE },
    { 27000000, 12288000, 7, 0x1208A6, TRUE }
};

#endif /* WM_TESTING */

/*
 * Function prototypes
 */
static WMSTATUS private_ConfigurePLL( WM_DEVICE_HANDLE   hDevice,
                                      WM8753_PLL         pll,
                                      unsigned int       targetFreq
                                    );
static void private_calcPLLCoefficients( unsigned int   MCLKFreq,
                                         unsigned int   targetFreq,
                                         int            *pN,
                                         int            *pK,
                                         WM_BOOL        *pDivMclk
                                       );

/*-----------------------------------------------------------------------------
 * Function:    WM8753SetSampleRate
 *
 * Called to set the sample rate in the audio-specific sections of the chip. 
 *
 * Parameters:
 *      hDevice      handle to the device (from WMOpenDevice)
 *      stream       The stream for which to set the sample rate
 *      sampleRate   The requested sample rate.
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h.
 *---------------------------------------------------------------------------*/
WMSTATUS WM8753SetSampleRate( WM_DEVICE_HANDLE hDevice,
                              WM_STREAM_ID     stream, 
                              WM_SAMPLE_RATE   sampleRate
                            )
{
    WM_DEVICE_CONTEXT       *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
    WMSTATUS                status;
    const SampleRateSetting *pSettings;
    unsigned int            nSettings;
    unsigned int            setting;
    WM_REGVAL               rateval;
    unsigned int            pllFreq;
    WM8753_PLL              pll;
    WM_BOOL                 isHiFi;
    WM_BOOL                 isMaster;
    WM_BOOL                 found = FALSE;

    /*
     * Look up our sample rate setting.
     * If the voice interface is enabled, we assume we will be set up
     * as HiFi DAC + Voice codec, so the VXDAC and ADC sample rates are
     * locked together.  NB: In this mode, the only way to record on the
     * HiFi interface is to set up a switch on the VX and HiFi clock lines
     * - see App Note 0152.
     */
    isHiFi = STREAM_USES_HIFI( stream, pDeviceContext );
    
    if ( isHiFi )
    {
        pSettings = s_hifiRates;
        nSettings = WM_ARRAY_COUNT( s_hifiRates );
        pll = WM8753_PLL1;
        isMaster = pDeviceContext->v_pWMData->audioData.flags & WM_AUDIO_HIFI_MASTER;
    }
    else
    {
        pSettings = s_voiceRates;
        nSettings = WM_ARRAY_COUNT( s_voiceRates );
        pll = WM8753_PLL2;
        isMaster = pDeviceContext->v_pWMData->audioData.flags & WM_AUDIO_VOICE_MASTER;
    }
    
    /*
     * Note: We don't currently handle whether ADC and DAC rates are
     * compatible.  The ADC and voice DAC will overwrite each other, and
     * the HiFi DAC will just take the first option.
     */
    if ( WM_IS_INPUT_STREAM( stream ) ) /* ADC */
    {
        for ( setting = 0; setting < nSettings; setting++ )
        {
            WM_SAMPLE_RATE adcRate = pSettings[ setting ].adcRate;
            if ( sampleRate == adcRate )
            {
                rateval = pSettings[ setting ].regSetting;
                pllFreq = pSettings[ setting ].pllFreq;
                found = TRUE;
                break;
            }
        }
    }
    else    /* output stream - DAC */
    {
        for ( setting = 0; setting < nSettings; setting++ )
        {
            WM_SAMPLE_RATE dacRate = pSettings[ setting ].dacRate;
            if ( sampleRate == dacRate )
            {
                rateval = pSettings[ setting ].regSetting;
                pllFreq = pSettings[ setting ].pllFreq;
                found = TRUE;
                break;
            }
        }
    }

    if ( !found )
    {
        status = WMS_INVALID_PARAMETER;
        goto error;
    }
    
    if ( isMaster )
    {
        /*
         * Set up the PLL.
         */
        status = private_ConfigurePLL( hDevice, pll, pllFreq );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }
    
        /*
         * Write the sample rate to the codec.
         */
        if ( isHiFi )
        {
            /*
             * Set the HiFi codec sample rate.
             */
            status = WMSetField( hDevice, 
                                 WM8753_SAMPLE_RATE_CTRL_1, 
                                 rateval << WM8753_SAMPLERATE_SHIFT,
                                 WM8753_SAMPLERATE_MASK
                            );
            if ( WM_ERROR( status ) )
            {
                goto error;
            }
        }
        else
        {
            /*
             * Set the voice codec sample rate.
             */
            status = WMSetField( hDevice, 
                                 WM8753_CLOCK_CONTROL, 
                                 rateval,	/* shift already in value */
                                 WM8753_VXCLK_DIV_MASK
                            );
            if ( WM_ERROR( status ) )
            {
                goto error;
            }
        }
    }
    else    /* => slave */
    {
        /*
         * Now set up the platform.
         */
        if ( WM_IS_HIFI_STREAM( stream ) )
        {
            /*
             * Set the I2S sample rate.
             */
            status = WMPlatformI2SSetSampleRate( hDevice, sampleRate );
            if ( WM_ERROR( status ) )
            {
                goto error;
            }
        }
    }

    /*
     * We're done.
     */
    return WMS_SUCCESS;
    
error:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    WM8753ConfigureInterface
 *
 * Configures the streaming format for the link for the given interface.
 * Note: this is not required for AC'97 streams - HIFI and MONO on AC'97
 * codecs.
 *
 * Parameters:
 *      hDevice         handle to the device (from WMOpenDevice)
 *      audioIF         the interface to configure
 *      isMaster        whether the codec masters the link
 *      format          the streaming format to use
 *      width           the number of bits per sample
 *      flags           extra configuration flags
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h.
 *---------------------------------------------------------------------------*/
WMSTATUS WM8753ConfigureInterface( WM_DEVICE_HANDLE     hDevice,
                                   WM_AUDIO_INTERFACE   audioIF,
                                   WM_BOOL              isMaster,
                                   WM_AUDIOIF_FORMAT    format,
                                   WM_AUDIOIF_WIDTH     width,
                                   WM_AUDIOIF_FLAGS     flags
                                 )
{
    WM_DEVICE_CONTEXT   *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
    WMSTATUS            status;
    WM_REGTYPE          reg;
    WM_REGVAL           controlVal = 0;
    WM_REGVAL           interfaceVal = 0, interfaceMask = 0;
    WM_REGVAL           sampleRateVal = 0, sampleRateMask = 0;
    WM_REGVAL           adcRateMode = 0;
    WM8753_PLL          pll;
    
    /*
     * Master or slave?
     */
    if ( isMaster )
        controlVal |= WM8753_MASTER;
    else
        controlVal |= WM8753_SLAVE;

    /*
     * Set data format.
     */
    switch ( format )
    {
        case WM_AUDIOIF_I2S:
            controlVal |= WM8753_DATA_FORMAT_I2S;
            break;
            
        case WM_AUDIOIF_LEFT_JUSTIFY:
            controlVal |= WM8753_DATA_FORMAT_LJUST;
            break;
            
        case WM_AUDIOIF_RIGHT_JUSTIFY:
            controlVal |= WM8753_DATA_FORMAT_RJUST;
            break;
            
        case WM_AUDIOIF_DSP_MODE_A:
            controlVal |= WM8753_DATA_FORMAT_DSP | WM8753_DSP_MODE_A;
            break;
    
        case WM_AUDIOIF_DSP_MODE_B:
            controlVal |= WM8753_DATA_FORMAT_DSP | WM8753_DSP_MODE_B;
            break;
        
        default:
            WM_TRACE( hDevice, (
                      "WM8753ConfigureInterface: unsupported format %d",

⌨️ 快捷键说明

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