📄 ac97.c
字号:
// See "@@@" for incomplete sections or other areas of concern.
// @@@ still need work on UINT32 Ac97CloseFifo (Ac97FifoProcessingInfoT* fifoInfoP)
// @@@ Must use error checking results throughout code!
/******************************************************************************
**
** COPYRIGHT (C) 2001 Intel Corporation.
**
** This file and the software in it 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 Intel Corporation. Intel Corporation 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 Intel Corporation.
**
** FILENAME: Ac97.c
**
** PURPOSE: Driver for the AC'97 device. Includes initialization,
** API and support functions.
**
** Valid for : Subset of AC '97 Rev 2.1
**
** $Modtime: 7/17/03 1:01p $
**
** Note: Ac97SWInit() and Ac97HWSetup() are located in Ac97Platform.c
******************************************************************************/
#define _DEFINING_AC97API
#include <string.h>
#include "systypes.h"
#include "cotulla.h"
#include "dm_errors.h"
#include "timedelays.h"
#include "XsIntCtrlApi.h"
#include "XsDmaApi.h"
#include "Ac97MixerRegsApi.h"
#include "XsAc97CtrlApi.h"
#include "Ac97Api.h"
#include "Ac97.h"
#include "DM_Debug.h"
#if 0
/*
*******************************************************************************
List of high-priority functions for driver
*******************************************************************************
*/
/*
// P1
Ac97ContextCodec0 structure variable with ApiServicesP supported!
Ac97SWInit // In ...Platform.c
x Ac97HWSetup // In ...Platform.c
x Ac97HwReconfigAudio
x Ac97PowerOnAudioSubsystems
x Ac97SwRestoreDefaultsAudio
x Ac97SwSetDefaultsUcb1400
x Ac97GetAnyMixerRegister
x Ac97SetAnyMixerRegister
x Ac97GetMasterVol
x Ac97SetMasterVol
x Ac97GetRecordSelect
x Ac97SetRecordSelect
// P2
// !!! UCB1400 only supports variable rate. Special mask?
x Ac97SetHWLoopAdcToDac
x Ac97GetPcmFrontDacRate
x Ac97SetPcmFrontDacRate
x Ac97GetPcmLrAdcRate
x Ac97SetPcmLrAdcRate
x Ac97GetRecordGain
x Ac97SetRecordGain
// P3
x Ac97GetVendorIDandRev
Ac97GetMasterTone
Ac97SetMasterTone
Ac97GetMicVol
Ac97SetMicVol
Ac97GetExtendedAudioID
Ac97ResetRegistersAudio
?? Ac97InitRegsAllAudio
// P4
Ac97GetExtendedAudioStatCtrl
Ac97ResetRegistersAll
Ac97GetCapabilities
Ac97DecodeCapabilities
// P5: modem, GPIO, etc.
--------------------------------------
// ??
?? Ac97GetNumReady
?? Ac97GetPowerDownCtrlStat
*/
/*
*******************************************************************************
End: List of high-priority functions for driver
*******************************************************************************
*/
#endif
UINT32 Ac97CheckRegId (AC97MixerRegisterIdT registerIdToCheck)
{
UINT32 status = ERR_NONE;
// Register must be in range and also even. No odd registers supported
// by the spec.
if ( (registerIdToCheck < 0 ) ||
(registerIdToCheck > AC97_MR_MAX)||
(registerIdToCheck & 1) )
{
status = ERR_T_ILLPARAM;
}
return (status);
} // Ac97CheckRegId ()
//
// Note the absence of programmatic (polled) audio and modem digital data
// methods. The assumed controller effectively provides only DMA access
// to the FIFOs that mediate those types of data.
//
// There will be little or no checking for null pointers. The symptoms should
// be too massive to miss.
static
PCHAR Ac97FifoNameStrings[]=
{
"Audio In Fifo", // XS_AC97CTRL_FIFO_AUDIO_IN
"Audio Out Fifo", // XS_AC97CTRL_FIFO_AUDIO_OUT
"Mic In Fifo", // XS_AC97CTRL_FIFO_MIC_IN,
"Modem In Fifo", // XS_AC97CTRL_FIFO_MODEM_IN,
"Modem Out Fifo" // XS_AC97CTRL_FIFO_MODEM_OUT
} ;
/*
void Ac97SWInit (void) // All codecs
{
// Init all context structures to defaults
// Modify context structures based on codecs in use
//
// Set "current values" to defaults
// Default values should leave the codecs as quiet as possible, but
// with all subsystems enabled and running. Power management support
// in the DM would probably mean that subsystems are disabled and
// selectively re-enabled when wanted.
// Initialize DMA + buffer parameters to defaults (Assume 44.1 KHz sample
// rate, 20 Msec per buffer, 5 second glitch protection)
INT i;
Ac97FifoProcessingInfoT* fifoInfoP;
Ac97ContextT* ctxP; // Primary codec context structure pointer
// Initialize the Ac97ContextCodec0 context structure (for the primary codec).
// This is the only one for now.
ctxP = &Ac97ContextCodec0;
memset (ctxP, 0, sizeof (Ac97ContextT)); // Sets all to 0, NULL, FALSE
ctxP->codecId = AC97_MR_EA_ID_PRIM; // all we know now.
ctxP->audioIdForController = XS_AC97CTRL_CM_ID_PRI_CODEC;
ctxP->modemIdForController = XS_AC97CTRL_CM_ID_PRI_MODEM;
ctxP->dmaBufMode = AC97_DMA_BUF_MODE_GLITCH_RESIST;
// Standard non-zero defaults
fifoInfoP = &ctxP->fifoProcessingInfoRecords[0];
for (i = 0; i < XS_AC97CTRL_FIFO_NUM ; i++)
{
fifoInfoP->parentAc97ctxP = ctxP;
fifoInfoP->fifoId = i;
fifoInfoP->fifoNameStrP = Ac97FifoNameStrings[i];
// DMA loop mode is default only for initial release.
fifoInfoP->fifoStatus = AC97_FIFO_ST_DMA_LP_ABLE |
AC97_FIFO_ST_DMA_LP_MODE |
// AC97_FIFO_ST_FIFO_ISR_MODE |
AC97_FIFO_ST_DMA_ISR_MODE ;
// Worst case acceptable minima: latency of 145 uSec from
// DMA trigger by FIFO (Tx: 7 samples @48K Sps)
// and 8-byte burst interval of 42 uSec (2 samples @ 48K Sps)
// Low priority DMA might be OK, but try for medium.
fifoInfoP->dmaChannelPrioReq = XSDMA_CH_PR_MEDIUM;
fifoInfoP++;
} // for (Standard non-zero defaults)
// Mic In doesn't do DMA loop mode.
Ac97WriteFifoStatus (&ctxP->fifoProcessingInfoRecords
[XS_AC97CTRL_FIFO_MIC_IN],
(AC97_FIFO_ST_DMA_LP_MODE |
AC97_FIFO_ST_DMA_LP_ABLE),
AC97_CLEAR);
// For Tx direction FIFOs, record that in status word
Ac97WriteFifoStatus (&ctxP->fifoProcessingInfoRecords
[XS_AC97CTRL_FIFO_AUDIO_OUT],
AC97_FIFO_ST_DIR_TX,
AC97_SET);
Ac97WriteFifoStatus (&ctxP->fifoProcessingInfoRecords
[XS_AC97CTRL_FIFO_MODEM_OUT],
AC97_FIFO_ST_DIR_TX,
AC97_SET);
// Record the XsDma device names and FIFO interrupt IDs in corresponding
// FIFO info structures
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_AUDIO_IN]
.dmaDeviceName = XSDMA_DN_AC97_AUDIO;
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_AUDIO_OUT]
.dmaDeviceName = XSDMA_DN_AC97_AUDIO;
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_MIC_IN]
.dmaDeviceName = XSDMA_DN_AC97_MIC;
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_MODEM_IN]
.dmaDeviceName = XSDMA_DN_AC97_MODEM;
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_MODEM_OUT]
.dmaDeviceName = XSDMA_DN_AC97_MODEM;
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_AUDIO_IN]
.fifoInterruptId = XS_AC97CTRL_INT_PIINT;
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_AUDIO_OUT]
.fifoInterruptId = XS_AC97CTRL_INT_POINT;
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_MIC_IN]
.fifoInterruptId = XS_AC97CTRL_INT_MINT;
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_MODEM_IN]
.fifoInterruptId = XS_AC97CTRL_INT_MIINT;
ctxP->fifoProcessingInfoRecords [XS_AC97CTRL_FIFO_MODEM_OUT]
.fifoInterruptId = XS_AC97CTRL_INT_MOINT;
// Set up any device-specific defaults for the primary Codec.
// Function defined in Ac97Platform.c
Ac97SwSetDefaultsPrimaryCodec (ctxP);
// Set up the defaults as "current" register values in records.
// Ac97HWSetup () will send them to the codec.
Ac97SwRestoreDefaultsAudio (ctxP);
Ac97SwRestoreDefaultsModem (ctxP);
// Init the Ac97ContextCodec1 context structure
// (for the first secondary codec)
// - No secondary codec.
} // Ac97SWInit()
UINT32 Ac97ConfigGlitchProtectBufs (Ac97ContextT* ctxP)
// Default configuration
// Separate Tx and Rx buffer chains.
// Standard approach is to use 125 buffers for Rx and 125 for Tx, to
// provide 5-second glitch protection. This also introduces a 5 second
// delay between Rx and Tx data for conforming SW loopback tests.
// Used with Ac97ReadBuf and Ac97WriteBuf
{
//@@@
return 1;
}
UINT32 Ac97ConfigDoubleBufs (Ac97ContextT* ctxP)
// Separate Tx and Rx buffer chains.
// Only two buffers for Rx and two for Tx. Minimal glitch protection.
// This introduces about a 40 millisecond delay for conforming
// SW loopback tests.
// Used with Ac97GetReadBuf and Ac97PutWriteBuf
{
// @@@
return 1;
}
UINT32 Ac97ConfigDmaLoopBufs (Ac97ContextT* ctxP, BOOL enable)
// Special test setup utility.
// Applies only to paired in and out FIFOs. Mic In unaffected. (Set up by
// flags in SW init.)
// No-ops for no change.
// Error if any target FIFOs are active and change needed.
// Single Tx and Rx buffer chain, total of three buffers long.
// Use only Ac97CheckFifoStatus; Ac97ReadBuf and Ac97WriteBuf do not apply.
// No-op for same mode.
{
UINT32 status = ERR_NONE;
Ac97FifoProcessingInfoT* fifoInfoP ;
UINT32 currMode ;
INT i;
fifoInfoP = &ctxP->fifoProcessingInfoRecords[XS_AC97CTRL_FIFO_AUDIO_IN];
// Current DMA loop mode can be determined by examining just one of the
// fifos that change together.
currMode = fifoInfoP->fifoStatus & AC97_FIFO_ST_DMA_LP_MODE;
// Operate only for change to mode
if ((enable && !currMode) || (!enable && currMode))
{
fifoInfoP = &ctxP->fifoProcessingInfoRecords[0];
// Also, look for affected FIFOs that are active. That's an error.
for (i = 0; i < XS_AC97CTRL_FIFO_NUM ; i++)
{
if ((AC97_FIFO_ST_ACTIVE | AC97_FIFO_ST_DMA_LP_ABLE)
== (fifoInfoP->fifoStatus &
(AC97_FIFO_ST_ACTIVE | AC97_FIFO_ST_DMA_LP_ABLE)))
{
status = ERR_T_ALREADY_IN_USE;
}
fifoInfoP++;
} // for (look for affected FIFOs that are active)
if (!status)
{
// SET UP NEW MODE in all candidate FIFOs
fifoInfoP = &ctxP->fifoProcessingInfoRecords[0];
for (i = 0; i < XS_AC97CTRL_FIFO_NUM ; i++)
{
if (fifoInfoP->fifoStatus & AC97_FIFO_ST_DMA_LP_ABLE)
{
if (enable)
{
Ac97WriteFifoStatus (fifoInfoP,
AC97_FIFO_ST_DMA_LP_MODE,
AC97_SET);
}
else
{
Ac97WriteFifoStatus (fifoInfoP,
AC97_FIFO_ST_DMA_LP_MODE,
AC97_CLEAR);
}
}
fifoInfoP++;
} // for (change status in all candidate FIFOs)
} // if (!status: no problem, set the mode)
} // if (change to existing mode)
//@@@ need logerror here
return(status);
} // Ac97ConfigDmaLoopBufs ()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -