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

📄 wmxscaleaclink.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 4 页
字号:
    if ( !private_IsCodecReady( hDevice ) )
    {
        WM_TRACE( hDevice, ( "WMPlatformACLinkColdReset: Codec ready bit not set" ));
        status = WMS_CODEC_NOT_READY;
        goto error;
    }

#endif /* WM_USE_XLLP_AC97 */

    return WMS_SUCCESS;

error:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkWarmReset
 *
 * Forces a warm reset of the WM97xx device, waking it up again but leaving it
 * in its previous state (with all the register settings as they were before
 * the sleep).
 *
 * Note: we assume the workaround is in place for the XScale bug, and hence
 * this function can operate normally - the cold reset line is not connected
 * to our chip so we won't see it go low.
 *
 * See WMPlatformConfig.h for more details.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkWarmReset( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT	*pDeviceContext = 
									(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                    status;
    WM_BOOL						codecReady;

    /*
     * If we've got codec ready, we're already awake.
     */
    if ( private_IsCodecReady( hDevice ) )
    {
        goto done;
    }

    /* Do the warm reset */
    pDeviceContext->v_pAC97Regs->GCR |= AC97GCR_WarmReset;

    /*
     * The XScale will have gone into cold reset as a result of the warm reset
     * bug.  Take it out of cold reset to persuade it to continue.
     * 
     * Note: we can only get away with this because the reset line isn't
     * connected.
     */
    pDeviceContext->v_pAC97Regs->GCR |= AC97GCR_ColdReset;
    
    /*
     * A warm reset typically takes around 1.3 microseconds.
     * A full frame takes approx 20.83us.  It takes us somewhere between
     * one and two frames (depending on how the timing hits) to get codec
     * ready to the CPU.  Unfortunately, it then takes the PXA2xx ages to
     * notice that codec ready is set...  500us seems to work reliably.
     */
    MicroSleep( pDeviceContext, 500 );

    /* Check for codec ready. */
    codecReady = private_IsCodecReady( hDevice );
    if ( !codecReady )
    {
        WM_TRACE( hDevice, ( "WMPlatformACLinkWarmReset: Codec ready bit not set" ));
#if WM_DEBUG_CHECK_CODEC_READY
        WM_ASSERT( hDevice, codecReady );
#endif /* WM_DEBUG_CHECK_CODEC_READY */
        status = WMS_CODEC_NOT_READY;
        goto error;
    }

done:
    return WMS_SUCCESS;

error:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    private_WaitForCommandDone (static)
 *
 * Waits for the Command Done bit in the status register.  This bit is set
 * once the AC Controller has received the command address and data.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
static WMSTATUS private_WaitForCommandDone( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT	*pDeviceContext = 
									(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                    status;
    unsigned long               timeout = 0;

    while( !( pDeviceContext->v_pAC97Regs->GSR & AC97GSR_CDONE ) )
    {
        if ( ++timeout > CODEC_TIMEOUT )
        {
            status = WMS_DEVICE_BUSY;
            goto error;
        }

        /* Allow other threads to continue if we can */
		WMBeNice( hDevice );
    };
        
    return WMS_SUCCESS;

error:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    private_WaitForStatusDone (static)
 *
 * Waits for the Status Done bit in the status register.  This bit is set
 * once the AC Controller has received the status address and data.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
static WMSTATUS private_WaitForStatusDone( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT  *pDeviceContext =
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                    status;
    unsigned long               timeout = 0;

    while( !( pDeviceContext->v_pAC97Regs->GSR & AC97GSR_SDONE ) )
    {
        if ( ++timeout > CODEC_TIMEOUT )
        {
            status = WMS_DEVICE_BUSY;
            goto error;
        }

        /* Allow other threads to continue if we can */
		WMBeNice( hDevice );
    };
        
    return WMS_SUCCESS;

error:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    private_ConfigureACLinkGPIO
 *
 * This function configures the GPIO pins for the AC link on the Lubbock
 * platform, as follows:
 *
 *      Signals         Pin#        Direction       Alternate Function
 *      SYNC            GPIO31      output              2
 *      SDATA_OUT       GPIO30      output              2
 *      BIT_CLK         GPIO28      input               1
 *      SDATA_IN_0      GPIO29      input               1
 *     (SDATA_IN_1      GPIO32      input               1)
 *
 * On the Mainstone platform the SYSCLK is generated by the Bulverde processor
 *
 *      Signals         Pin#        Direction       Alternate Function
 *      SYSCLK          GPIO45      output              1
 *     (SDATA_IN_1      GPIO99      input               2)
 *
 * Note: SDATA_IN_1 is treated slightly oddly.  Slots 2-12 are multiplexed to
 * SDATA_IN_0, and hence you cannot have data on the same slot on SDATA_IN_0
 * and SDATA_IN_1 in the same frame, although you can have data on different
 * slots - e.g. if you have one codec for audio (slots 3 & 4) and one as a
 * modem (slot 5).  Slot 1 is obviously read from both to determine which line
 * to latch the data in from for that frame.
 *
 * This has the effect that codec ready appears on GSR bit 8 (PCR) for the
 * codec attached to SDATA_IN_0, and on GSR bit 9 (SCR) for the codec attached
 * to SDATA_IN_1.  For everything else the two codecs lines are effectively
 * identical - SDATA_OUT goes to both, and the address (primary or secondary)
 * determines which codec picks it up (they'd better not be both primary!).
 *
 * The net effect of this is (for Wolfson devices) that regardless of which
 * location the device is connected to, all operation is identical except the
 * codec ready bit.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
static WMSTATUS private_ConfigureACLinkGPIO( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext = 
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS status;

    WM_ASSERT( hDevice, NULL != pDeviceContext->v_pWMData );
    WM_ASSERT( hDevice, NULL != pDeviceContext->v_pGPIORegs );

    /* Only need to do this once */
    if ( pDeviceContext->v_pWMData )
    {
        if ( pDeviceContext->v_pWMData->flags & WM_GPIO_CONFIGURED_AC97 )
        {
            goto done;
        }
    }

    /*
     * Check to see if a different control interface has already
     * been initialised by another driver. 
     * If it has been we should not try to configure this interface.
     */
    if ( pDeviceContext->v_pWMData->flags & WM_GPIO_CONFIGURED_I2S )
    {
		status = WMS_RESOURCE_CONFLICT;
        goto error;
    }

    WM_ASSERT( hDevice, NULL != pDeviceContext->v_pGPIORegs );

    /* SDATAOUT and SYNC are outputs (1) */
    pDeviceContext->v_pGPIORegs->GPIO_REG(GPDR) |=
                    GPIO_BIT_SDATA_OUT | GPIO_BIT_SYNC;

    /* BITCLK and SDATA_IN0 are inputs (0) */
    pDeviceContext->v_pGPIORegs->GPIO_REG(GPDR) &=
                    ~(GPIO_BIT_BITCLK | GPIO_BIT_SDATA_IN_0);

    /* So is SDATA_IN1 - but it's a different GPIO bank, just to be awkward */
    //pDeviceContext->v_pGPIORegs->GPIO_REG_SDATA_IN_1(GPDR) &=
    //                ~GPIO_BIT_SDATA_IN_1;

    /* Set up the correct alternate functions */
    pDeviceContext->v_pGPIORegs->GPIO_ALTFN_REG =
                            (pDeviceContext->v_pGPIORegs->GPIO_ALTFN_REG & ~GPIO_ALTFN_MASK)|
                            GPIO_ALTFN_AC97_BITCLK      | 
                            GPIO_ALTFN_AC97_SDATA_IN_0  | 
                            GPIO_ALTFN_AC97_SDATA_OUT   |
                            GPIO_ALTFN_AC97_SYNC;

    //pDeviceContext->v_pGPIORegs->GPIO_ALTFN_REG_SDATA_IN_1 =
    //                        (pDeviceContext->v_pGPIORegs->GPIO_ALTFN_REG_SDATA_IN_1 & ~GPIO_ALTFN_MASK_SDATA_IN_1)
    //                       | GPIO_ALTFN_AC97_SDATA_IN_1;

    /*
     * Note: although we set up the SDATA_IN1 GPIO, the rest of the code just
     * relies on the multiplexing.
     */

    /*
     * Set up our GPIO as an alternate reset line to work
     * around the bug in the XScale (see WMPlatformConfig.h for
     * more details).
     */

    /* It's an output */
    pDeviceContext->v_pGPIORegs->RESET_GPIO_REG(GPDR) |= RESET_GPIO_MASK;

    /* Select the correct alternate function */
    pDeviceContext->v_pGPIORegs->RESET_GPIO_ALTFN_REG =
                            (pDeviceContext->v_pGPIORegs->RESET_GPIO_ALTFN_REG & ~RESET_GPIO_ALTFN_MASK)
                            | RESET_GPIO_ALTFN;

#if WM_BOARD_MAINSTONEII
    /* SYSCLK is an output (1) */
    pDeviceContext->v_pGPIORegs->GPIO_REG_AC97_SYSCLK(GPDR) |= GPIO_BIT_AC97_SYSCLK;

    pDeviceContext->v_pGPIORegs->GPIO_ALTFN_REG_AC97_SYSCLK =
                            (pDeviceContext->v_pGPIORegs->GPIO_ALTFN_REG_AC97_SYSCLK & ~GPIO_ALTFN_MASK_AC97_SYSCLK)
                            | GPIO_ALTFN_AC97_SYSCLK;

#endif /* WM_BOARD_MAINSTONEII */

    /*
     * And we're done.
     */
done:
    /* Remember it's done so we don't try to do it twice */
    if ( pDeviceContext->v_pWMData )
    {
        pDeviceContext->v_pWMData->flags |= ( WM_GPIO_CONFIGURED_AC97 | 
                                              WM_GPIO_CONFIGURED_HIFI
                                            );
    }

    return WMS_SUCCESS;

error:
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    private_UnconfigureACLinkGPIO
 *
 * This function configures the GPIO pins for the AC link on the Lubbock
 * platform, as follows:
 *
 *      Signals         Pin#        Direction       Alternate Function
 *      SYNC            GP31        output              2
 *      SDATA_OUT       GP30        output              2
 *      BIT_CLK         GP28        input               1
 *      SDATA_IN_0      GP29        input               1
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
static void private_UnconfigureACLinkGPIO( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext = 
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;

    /* We're less configured now */
    if ( pDeviceContext->v_pWMData )
    {
        pDeviceContext->v_pWMData->flags &= ~( WM_GPIO_CONFIGURED_HIFI |
                                               WM_GPIO_CONFIGURED_AC97
                                             );
    }

    return;
}

#endif /* WM_AC97 */
/*------------------------------ END OF FILE ---------------------------------*/

⌨️ 快捷键说明

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