--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/navienginebsp/naviengine_assp/i2s/i2s_psl.cpp Tue Sep 28 18:00:05 2010 +0100
@@ -0,0 +1,960 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* bsp\nwip_nec_naviengine\naviengine_assp\i2s\i2s_psl.cpp
+*
+*/
+
+
+
+#include "navi_i2s.h"
+#include <naviengine.h>
+
+#ifdef __SMP__
+static TSpinLock I2sLock = TSpinLock(TSpinLock::EOrderGenericIrqLow2);
+#endif
+
+// All channels have the same configuration.
+// base for registers are shifted for each channel by 0x400 (1<<10)
+#define HW_CHAN_SHIFT 10
+
+// Registers
+// these macros will return register address for a given interface
+#define KHwI2SControl(intefaceId) ((KHwBaseI2S0 + KHoI2SCtrl) + (intefaceId << HW_CHAN_SHIFT))
+#define KHwI2SFifoControl(intefaceId) ((KHwBaseI2S0 + KHoI2SFifoCtrl) + (intefaceId << HW_CHAN_SHIFT))
+#define KHwI2SFifoStatus(intefaceId) ((KHwBaseI2S0 + KHoI2SFifoSts) + (intefaceId << HW_CHAN_SHIFT))
+#define KHwI2SInterruptFlag(intefaceId) ((KHwBaseI2S0 + KHoI2SIntFlg) + (intefaceId << HW_CHAN_SHIFT))
+#define KHwI2SInterruptMask(intefaceId) ((KHwBaseI2S0 + KHoI2SIntMask) + (intefaceId << HW_CHAN_SHIFT))
+#define KHwI2SDataIn(intefaceId) ((KHwBaseI2S0 + KHoI2SRx) + (intefaceId << HW_CHAN_SHIFT))
+#define KHwI2SDataOut(intefaceId) ((KHwBaseI2S0 + KHoI2STx) + (intefaceId << HW_CHAN_SHIFT))
+
+#define AsspIsBitSet(addr, bit) (AsspRegister::Read32(addr)& (bit))
+#define CLEARMASK(shift,len) (((1 << len) - 1) << shift)
+#define AsspGetBits(w,shift,len) ((AsspRegister::Read32(w) >> shift) & ((1 << (len)) - 1))
+#define AsspSetBits(w,set,shift,len) (AsspRegister::Modify32(w, (CLEARMASK(shift, len)) , (set << shift)))
+
+
+NONSHARABLE_CLASS(D2sChannelNE1_TB) : public DI2sChannelBase
+ {
+public:
+ D2sChannelNE1_TB(TInt aInterfaceId);
+
+ virtual TInt ConfigureInterface(TDes8* aConfig);
+ virtual TInt GetInterfaceConfiguration(TDes8& aConfig);
+ virtual TInt SetSamplingRate(TInt aSamplingRate);
+ virtual TInt GetSamplingRate(TInt& aSamplingRate);
+ virtual TInt SetFrameLengthAndFormat(TInt aFrameLength, TInt aLeftFramePhaseLength);
+ virtual TInt GetFrameFormat(TInt& aLeftFramePhaseLength, TInt& aRightFramePhaseLength);
+ virtual TInt SetSampleLength(TInt aFramePhase, TInt aSampleLength);
+ virtual TInt GetSampleLength(TInt aFramePhase, TInt& aSampleLength);
+ virtual TInt SetDelayCycles(TInt aFramePhase, TInt aDelayCycles);
+ virtual TInt GetDelayCycles(TInt aFramePhase, TInt& aDelayCycles);
+ virtual TInt ReadReceiveRegister(TInt aFramePhase, TInt& aData);
+ virtual TInt WriteTransmitRegister(TInt aFramePhase, TInt aData);
+ virtual TInt ReadTransmitRegister(TInt aFramePhase, TInt& aData);
+ virtual TInt ReadRegisterModeStatus(TInt aFramePhase, TInt& aFlags);
+ virtual TInt EnableRegisterInterrupts(TInt aFramePhase, TInt aInterrupt);
+ virtual TInt DisableRegisterInterrupts(TInt aFramePhase, TInt aInterrupt);
+ virtual TInt IsRegisterInterruptEnabled(TInt aFramePhase, TInt& aEnabled);
+ virtual TInt EnableFIFO(TInt aFramePhase, TInt aFifoMask);
+ virtual TInt DisableFIFO(TInt aFramePhase, TInt aFifoMask);
+ virtual TInt IsFIFOEnabled(TInt aFramePhase, TInt& aEnabled);
+ virtual TInt SetFIFOThreshold(TInt aFramePhase, TInt aDirection, TInt aThreshold);
+ virtual TInt ReadFIFOModeStatus(TInt aFramePhase, TInt& aFlags);
+ virtual TInt EnableFIFOInterrupts(TInt aFramePhase, TInt aInterrupt);
+ virtual TInt DisableFIFOInterrupts(TInt aFramePhase, TInt aInterrupt);
+ virtual TInt IsFIFOInterruptEnabled(TInt aFramePhase, TInt& aEnabled);
+ virtual TInt ReadFIFOLevel(TInt aFramePhase, TInt aDirection, TInt& aLevel);
+ virtual TInt EnableDMA(TInt aFifoMask);
+ virtual TInt DisableDMA(TInt aFifoMask);
+ virtual TInt IsDMAEnabled(TInt& aEnabled);
+ virtual TInt Start(TInt aDirection);
+ virtual TInt Stop(TInt aDirection);
+ virtual TInt IsStarted(TInt aDirection, TBool& aStarted);
+
+private:
+ TBool iConfigured;
+ TInt iLastPhaseInWriteFifo;
+ TInt iLastPhaseInReadFifo;
+ };
+
+// this static method, creates the DI2sChannelBase corresponding
+// to the interfaceId passed and return the channel
+// NB: if each channel was implemented independently (e.g. on a separate file)
+// this function would have to be provided spearately and know how to map
+// the interface ID to the appropriate channel object to be created
+// (e.g. each channel would have a different implementation D2sChannelXXX
+// and this function call the appropriate constructor for each interface Id)
+
+TInt DI2sChannelBase::CreateChannels(DI2sChannelBase*& aChannel, TInt aInterfaceId)
+ {
+ DI2sChannelBase* chan = new D2sChannelNE1_TB(aInterfaceId);
+ if (!chan)
+ {
+ return KErrNoMemory;
+ }
+
+ aChannel = chan;
+
+ return KErrNone;
+ }
+
+
+// Default constructor.
+D2sChannelNE1_TB::D2sChannelNE1_TB(TInt aInterfaceId):
+ iConfigured(EFalse),
+ iLastPhaseInWriteFifo(I2s::ERight), // the first phase in write fifo should be left, so initialize to right
+ iLastPhaseInReadFifo(I2s::ERight) // the first phase in read fifo should be left, so initialize to right
+ {
+ iInterfaceId=aInterfaceId;
+ }
+
+TInt D2sChannelNE1_TB::ConfigureInterface(TDes8 *aConfig)
+ {
+ __KTRACE_OPT(KDLL, Kern::Printf("DI2sChannelNE1_TB::ConfigureInterfaceInterface (Id: %d)", iInterfaceId));
+
+ if(AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
+ {
+ return KErrInUse;
+ }
+
+ TI2sConfigBufV01 &conf = ((TI2sConfigBufV01&)*aConfig);
+
+ // this interface doesn's support EController mode
+ if (conf().iType == I2s::EController)
+ {
+ return KErrNotSupported;
+ }
+
+ if(conf().iRole == I2s::EMaster)
+ {
+ AsspRegister::Modify32(KHwI2SControl(iInterfaceId), 0, KHtI2SCtrl_MSMODE);
+ }
+
+ // copy configuration.. it will be used in Start/Stop
+ iConfig = conf(); // ok, thread context only and one client thread per channel
+
+ // select I2S format
+ AsspSetBits(KHwI2SControl(iInterfaceId), 4, KHsI2SCtrl_FORMAT, 3);
+
+ iConfigured = ETrue; // this API can only be called in thread context and we assume that a channel is for use of a single thread
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::GetInterfaceConfiguration(TDes8 &aConfig)
+ {
+ if (!iConfigured) // this API can only be called in thread context and we assume that a channel is for use of a single thread
+ {
+ aConfig.SetLength(0); //no configuration present yet..
+ }
+ else
+ {
+ TPckgBuf<TI2sConfigV01> conf(iConfig);
+ aConfig.Copy(conf);
+ }
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::SetSamplingRate(TInt aSamplingRate)
+ {
+ if (iConfig.iRole == I2s::ESlave)
+ {
+ return KErrNotSupported;
+ }
+
+ if (AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
+ {
+ return KErrInUse;
+ }
+
+ TUint32 val = 0, div = 0;
+
+ switch(aSamplingRate)
+ {
+ case I2s::E8KHz: // 0000: 8 kHz
+ div = 1; // MCLK = 24.5760 MHz(1*)
+ break;
+
+ case I2s::E11_025KHz: // 1000: 11.025 kHz
+ val = 8;
+ div = 4; // MCLK = 33.8688 MHz(4*) or 22.5792(5*) or 16.9344 MHz(6)
+ break;
+
+ case I2s::E12KHz: // 0001: 12 kHz
+ val = 1;
+ div = 1; // MCLK = 24.5760 MHz(1*) or 18.432MHz(2)
+ break;
+
+ case I2s::E16KHz: // 0010: 16 kHz
+ val = 2;
+ div = 1; // MCLK = 24.5760 MHz(1*)
+ break;
+
+ case I2s::E22_05KHz: // 1001: 22.05 kHz
+ val = 9;
+ div = 4; // MCLK = 33.8688 MHz(4*) or 22.5792(5*) or 16.9344 MHz(6)
+ break;
+
+ case I2s::E24KHz: // 0011: 24 kHz
+ val = 3;
+ div = 1; // MCLK = 24.5760 MHz(1*) or 18.432MHz(2)
+ break;
+
+ case I2s::E32KHz: // 0100: 32 kHz
+ val = 4;
+ div = 1; // MCLK = 24.5760 MHz
+ break;
+
+ case I2s::E44_1KHz: // 1010: 44.1 kHz
+ val = 10;
+ div = 4; // MCLK = 33.8688 MHz(4*) or 22.5792(5*) or 16.9344 MHz(6)
+ break;
+
+ case I2s::E48KHz: // 0101: 48 kHz
+ val = 5;
+ div = 2; // MCLK = 24.5760 MHz(1*) or 18.432MHz(2)
+ break;
+
+ default:
+ return KErrNotSupported;
+ }
+
+ TInt irq=__SPIN_LOCK_IRQSAVE(I2sLock); // seems that we must guarantee the following sequence is uninterrupted...
+ // before changing FSCLKSEL and/or FSMODE - mask I2S bit
+ // MSK_I2Sx (x=0:3): bits 18:21 in MaskCtrl Register of the System Ctrl Unit
+ AsspRegister::Modify32(KHwBaseSCU + KHoSCUClockMaskCtrl, 0, (1<<iInterfaceId)<<18);
+
+ // change the divide I2SCLK ctrl value for this channel..
+ AsspRegister::Modify32(KHwSystemCtrlBase+KHoSCUDivideI2SCLKCtrl, 0xf<<(iInterfaceId<<3), div<<(iInterfaceId<<3));
+
+ // update the KHwI2SControl register
+ AsspSetBits(KHwI2SControl(iInterfaceId), val, KHsI2SCtrl_FCKLKSEL, 4);
+
+ // after changing FSCLKSEL and FSMODE - clear MSK_I2Sx mask bit
+ AsspRegister::Modify32(KHwBaseSCU + KHoSCUClockMaskCtrl, (1<<iInterfaceId)<<18, 0);
+ __SPIN_UNLOCK_IRQRESTORE(I2sLock,irq);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::GetSamplingRate(TInt& aSamplingRate)
+ {
+ if (iConfig.iRole == I2s::ESlave)
+ {
+ return KErrNotSupported;
+ }
+
+ TUint32 val = (AsspRegister::Read32(KHwI2SControl(iInterfaceId))>>KHsI2SCtrl_FCKLKSEL) & 0xf;
+
+ switch(val)
+ {
+ case 0:
+ aSamplingRate = I2s::E8KHz; // 0000: 8 kHz
+ break;
+
+ case 8:
+ aSamplingRate = I2s::E11_025KHz; // 1000: 11.025 kHz
+ break;
+
+ case 1:
+ aSamplingRate = I2s::E12KHz; // 0001: 12 kHz
+ break;
+
+ case 2:
+ aSamplingRate = I2s::E16KHz; // 0010: 16 kHz
+ break;
+
+ case 9:
+ aSamplingRate = I2s::E22_05KHz; // 1001: 22.05 kHz
+ break;
+
+ case 3:
+ aSamplingRate = I2s::E24KHz; // 0011: 24 kHz
+ break;
+
+ case 4:
+ aSamplingRate = I2s::E32KHz; // 0100: 32 kHz
+ break;
+
+ case 10:
+ aSamplingRate = I2s::E44_1KHz; // 1010: 44.1 kHz
+ break;
+
+ case 5:
+ aSamplingRate = I2s::E48KHz; // 0101: 48 kHz
+ break;
+ }
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::SetFrameLengthAndFormat(TInt aFrameLength, TInt /*aLeftFramePhaseLength*/)
+ {
+ if (AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
+ {
+ return KErrInUse;
+ }
+
+ TUint32 val=0;
+
+ switch(aFrameLength)
+ {
+ case I2s::EFrame32Bit:
+ val = 0;
+ break;
+
+ case I2s::EFrame48Bit:
+ val = 1;
+ break;
+
+ case I2s::EFrame64Bit:
+ val = 2;
+ break;
+
+ case I2s::EFrame128Bit:
+ val = 3;
+ break;
+
+ default:
+ return KErrNotSupported;
+ };
+
+ TInt irq=__SPIN_LOCK_IRQSAVE(I2sLock); // seems that we must guarantee the following sequence is uninterrupted
+ // before changing FSCLKSEL and/or FSMODE - mask I2S bit
+ // MSK_I2Sx (x=0:3): bits 18:21 in MaskCtrl Register of the System Ctrl Unit
+ AsspRegister::Modify32(KHwBaseSCU + KHoSCUClockMaskCtrl, 0, (1<<iInterfaceId)<<18);
+
+ // update the register (3 bits at KHsI2SCtrl_FSMODE)
+ AsspSetBits(KHwI2SControl(iInterfaceId), val, KHsI2SCtrl_FSMODE, 3);
+
+ // after changing FSCLKSEL and FSMODE - clear MSK_I2Sx mask bit
+ AsspRegister::Modify32(KHwBaseSCU + KHoSCUClockMaskCtrl, (1<<iInterfaceId)<<18, 0);
+ __SPIN_UNLOCK_IRQRESTORE(I2sLock,irq);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::GetFrameFormat(TInt& aLeftFramePhaseLength, TInt& aRightFramePhaseLength)
+ {
+ TInt frameLength=0;
+ switch(AsspGetBits(KHwI2SControl(iInterfaceId), KHsI2SCtrl_FSMODE, 3))
+ {
+ case 0:
+ frameLength = I2s::EFrame32Bit;
+ break;
+
+ case 1:
+ frameLength = I2s::EFrame48Bit;
+ break;
+
+ case 2:
+ frameLength = I2s::EFrame64Bit;
+ break;
+
+ case 3:
+ frameLength = I2s::EFrame128Bit;
+ break;
+
+ default:
+ return KErrGeneral; //unexpected value??
+ };
+
+ aLeftFramePhaseLength=aRightFramePhaseLength=frameLength/2; // on NaviEngine frames are symmetrical
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::SetSampleLength(TInt /*aFramePhase*/, TInt aSampleLength)
+ {
+ if (AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
+ {
+ return KErrInUse;
+ }
+
+ TUint32 val=0;
+
+ switch(aSampleLength)
+ {
+ case I2s::ESample8Bit:
+ val = 0x8;
+ break;
+
+ case I2s::ESample16Bit:
+ val = 0x10;
+ break;
+
+ case I2s::ESample24Bit:
+ val = 0x18;
+ break;
+
+ case I2s::ESample12Bit:
+ case I2s::ESample32Bit:
+ return KErrNotSupported;
+ }
+
+ // update the register..
+ AsspSetBits(KHwI2SControl(iInterfaceId), val, KHsI2SCtrl_DLENGTH,5); // [4:0] sampling data length);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::GetSampleLength(TInt /*aFramePhase*/, TInt& aSampleLength)
+ {
+ // sample length can't be configured separately for left/right channels..
+ // .. in this chip, so aFramePhase is ignored
+
+ TUint32 val=AsspRegister::Read32(KHwI2SControl(iInterfaceId)) & 0x1F;
+
+ switch(val)
+ {
+ case 0x8:
+ aSampleLength = I2s::ESample8Bit;
+ break;
+
+ case 0x10:
+ aSampleLength = I2s::ESample16Bit;
+ break;
+
+ case 0x18:
+ aSampleLength = I2s::ESample24Bit;
+ break;
+ }
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::SetDelayCycles(TInt aFramePhase, TInt aDelayCycles)
+ {
+ return KErrNotSupported;
+ }
+
+TInt D2sChannelNE1_TB::GetDelayCycles(TInt aFramePhase, TInt& aDelayCycles)
+ {
+ return KErrNotSupported;
+ }
+
+TInt D2sChannelNE1_TB::ReadReceiveRegister(TInt aFramePhase, TInt& aData)
+ {
+ // should check here, if sample length was configured,
+ // but once the interface is properly configured, this check would add unnecessary overhead.
+
+ // since there is only one fifo for both channels in this chip,
+ // we need to read Left and then Right channel data in sequence.
+
+ TInt oldFP=__e32_atomic_swp_ord32(&iLastPhaseInReadFifo,aFramePhase); // atomic as this may be used in ISR too
+ if(aFramePhase == oldFP)
+ {
+ return KErrNotSupported;
+ }
+
+ // and get the current data from the fifo register
+ aData = AsspRegister::Read32(KHwI2SDataIn(iInterfaceId));
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::WriteTransmitRegister(TInt aFramePhase, TInt aData)
+ {
+ // should check here, if sample length was configured,
+ // but once the interface is properly configured, this check would add unnecessary overhead.
+
+ // since there is only one fifo for both channels in this chip,
+ // we need to write Left and then right channel data in sequence.
+
+ TInt oldFP=__e32_atomic_swp_ord32(&iLastPhaseInWriteFifo,aFramePhase); // atomic as this may be used in ISR too
+ if(aFramePhase == oldFP)
+ {
+ return KErrNotSupported;
+ }
+
+ // and update the fifo register
+ AsspRegister::Write32(KHwI2SDataOut(iInterfaceId), aData);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::ReadTransmitRegister(TInt aFramePhase, TInt& aData)
+ {
+ // since there is only one fifo for both channels in this chip,
+ // we can only read the data for the last written phase (either left or right)
+
+ TInt curFp=__e32_atomic_load_acq32(&iLastPhaseInWriteFifo);
+ if(aFramePhase != curFp)
+ {
+ return KErrArgument;
+ }
+
+ // read the register
+ aData = AsspRegister::Read32(KHwI2SDataOut(iInterfaceId));
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::ReadRegisterModeStatus(TInt aFramePhase, TInt& aFlags)
+ {
+ return KErrNotSupported; // register PIO mode not supported (FIFO always present)
+ }
+
+TInt D2sChannelNE1_TB::EnableRegisterInterrupts(TInt aFramePhase, TInt aInterrupt)
+ {
+ return KErrNotSupported; // register PIO mode not supported (FIFO always present)
+ }
+
+TInt D2sChannelNE1_TB::DisableRegisterInterrupts(TInt aFramePhase, TInt aInterrupt)
+ {
+ return KErrNotSupported; // register PIO mode not supported (FIFO always present)
+ }
+
+TInt D2sChannelNE1_TB::IsRegisterInterruptEnabled(TInt aFramePhase, TInt& aEnabled)
+ {
+ return KErrNotSupported; // register PIO mode not supported (FIFO always present)
+ }
+
+TInt D2sChannelNE1_TB::EnableFIFO(TInt /*aFramePhase*/, TInt aFifoMask)
+ {
+ TInt val=0;
+
+ // Set and clear fifo init bits for transmit/receive
+ // tere are only two FIFOs - not separated to phases..
+ if(aFifoMask & I2s::ETx)
+ val = KHtI2SFifoCtrl_TFIFOCLR;
+
+ if(aFifoMask & I2s::ERx)
+ val |= KHtI2SFifoCtrl_RFIFOCLR;
+
+ AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), 0, val);
+ AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), val, 0);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::DisableFIFO(TInt aFramePhase, TInt aFifoMask)
+ {
+ // fifo is always enabled in this chip..
+ return KErrNotSupported;
+ }
+
+TInt D2sChannelNE1_TB::IsFIFOEnabled(TInt /*aFramePhase*/, TInt& aEnabled)
+ {
+ // fifo is always enabled in this chip..
+ aEnabled = I2s::ERx|I2s::ETx;
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::SetFIFOThreshold(TInt aFramePhase, TInt aDirection, TInt aThreshold)
+ {
+ // supported threshold values for this chip:
+ // 011b - 16-word space available
+ // 010b - 8-word space available
+ // 001b - 4-word space available
+ // 000b - 2-word space available
+ if (aThreshold < 0)
+ {
+ return KErrNotSupported;
+ }
+
+ // Determine, what value was specified, and adjust it down to one
+ // of the possible values
+ TInt i=15;
+ while(i>1)
+ {
+ if ( aThreshold!=(aThreshold & i))
+ break;
+ i>>=1;
+ }
+ aThreshold = i+1; //this will now contain one of possible values (2-16);
+
+ // now any of 16/8/4/2, shifted right until == 0 will give us requested register_value+2
+ // (instead of using 'switch(aThreshold)')
+ i=0;
+ while(aThreshold)
+ {
+ aThreshold>>=1;
+ ++i;
+ }
+ aThreshold = i-2 >= 0 ? i-2 : 0; //if i-2 gives <0 (e.g.for aThreshold<4) -adjust to 0;
+
+ if (AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
+ {
+ return KErrInUse;
+ }
+
+ TUint32 clr, set;
+ if(aDirection & I2s::ERx) // receive fifo..
+ {
+ if (aFramePhase == I2s::ELeft)
+ {
+ clr = CLEARMASK(KHsI2SFifoCtrl_RFIFOLT, 3);
+ set = (aThreshold << KHsI2SFifoCtrl_RFIFOLT);
+ }
+
+ else //if (aFramePhase == I2s::ERight)
+ {
+ clr = CLEARMASK(KHsI2SFifoCtrl_RFIFORT, 3);
+ set = (aThreshold << KHsI2SFifoCtrl_RFIFORT);
+ }
+ }
+ else // transmit fifo..
+ {
+ if (aFramePhase == I2s::ELeft)
+ {
+ clr = CLEARMASK(KHsI2SFifoCtrl_TFIFOLT, 3);
+ set = (aThreshold << KHsI2SFifoCtrl_TFIFOLT);
+
+ }
+ else // if (aFramePhase == I2s::ERight)
+ {
+ clr = CLEARMASK(KHsI2SFifoCtrl_TFIFORT, 3);
+ set = (aThreshold << KHsI2SFifoCtrl_TFIFORT);
+ }
+ }
+ // updating register with value will also clear FIFO initialization bits..
+ AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), clr, set);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::ReadFIFOModeStatus(TInt aFramePhase, TInt& aFlags)
+ {
+ aFlags = 0;
+
+ TInt irq=__SPIN_LOCK_IRQSAVE(I2sLock); // (read and clear), can be used in ISR
+ TUint32 flags = AsspRegister::Read32(KHwI2SInterruptFlag(iInterfaceId));
+ AsspRegister::Write32(KHwI2SInterruptFlag(iInterfaceId), flags); // clear the status flags (after reading)
+ __SPIN_UNLOCK_IRQRESTORE(I2sLock,irq);
+
+ if (aFramePhase == I2s::ELeft)
+ {
+ if(flags & KHtI2SIntFlg_TFLURINT) // L-ch transmit FIFO underrun
+ aFlags |= I2s::ETxUnderrun;
+
+ if(flags & KHtI2SIntFlg_TFLEINT) // L-ch transmit FIFO reached the empty trigger level
+ aFlags |= I2s::ETxEmpty;
+
+ if(flags & KHtI2SIntFlg_RFLORINT) // L-ch receive FIFO overrun
+ aFlags |= I2s::ERxOverrun;
+
+ if(flags & KHtI2SIntFlg_RFLFINT) // L-ch receive FIFO reached the full trigger level
+ aFlags |= I2s::ERxFull;
+ }
+ else
+ {
+ if(flags & KHtI2SIntFlg_TFRURINT) // R-ch transmit FIFO underrun
+ aFlags |= I2s::ETxUnderrun;
+
+ if(flags & KHtI2SIntFlg_TFREINT) // R-ch transmit FIFO reached the empty trigger level
+ aFlags |= I2s::ETxEmpty;
+
+ if(flags & KHtI2SIntFlg_RFRORINT) // R-ch receive FIFO overrun
+ aFlags |= I2s::ERxOverrun;
+
+ if(flags & KHtI2SIntFlg_RFRFINT) // R-ch receive FIFO reached the full trigger level
+ aFlags |= I2s::ERxFull;
+ }
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::EnableFIFOInterrupts(TInt aFramePhase, TInt aInterrupt)
+ {
+ TUint32 val=0;
+
+ if(aInterrupt & I2s::ERxFull)
+ {
+ if (aFramePhase == I2s::ELeft)
+ val |= KHtI2SIntMask_RFLFINT;
+
+ if (aFramePhase == I2s::ERight)
+ val |= KHtI2SIntMask_RFRFINT;
+ }
+
+ if(aInterrupt & I2s::ETxEmpty)
+ {
+ if (aFramePhase == I2s::ELeft)
+ val |= KHtI2SIntMask_TFLEINT;
+
+ if (aFramePhase == I2s::ERight)
+ val |= KHtI2SIntMask_TFREINT;
+ }
+
+ if(aInterrupt & I2s::ERxOverrun)
+ {
+ if (aFramePhase == I2s::ELeft)
+ val |= KHtI2SIntMask_RFLORINT;
+
+ if (aFramePhase == I2s::ERight)
+ val |= KHtI2SIntMask_RFRORINT;
+ }
+
+ if(aInterrupt & I2s::ETxUnderrun)
+ {
+ if (aFramePhase == I2s::ELeft)
+ val |= KHtI2SIntMask_TFLURINT;
+
+ if (aFramePhase == I2s::ERight)
+ val |= KHtI2SIntMask_TFRURINT;
+ }
+
+ if(aInterrupt & I2s::EFramingError)
+ {
+ // not supported, do nothing
+ }
+
+ if (val)
+ {
+ // update the register
+ AsspRegister::Write32(KHwI2SInterruptMask(iInterfaceId), val);
+ }
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::DisableFIFOInterrupts(TInt aFramePhase, TInt aInterrupt)
+ {
+ TUint32 val = KHmI2SIntMask_ALL;
+
+ if(aInterrupt & I2s::ERxFull)
+ {
+ if (aFramePhase == I2s::ELeft)
+ val &= ~KHtI2SIntMask_RFLFINT;
+
+ if (aFramePhase == I2s::ERight)
+ val &= ~KHtI2SIntMask_RFRFINT;
+ }
+
+ if(aInterrupt & I2s::ETxEmpty)
+ {
+ if (aFramePhase == I2s::ELeft)
+ val &= ~KHtI2SIntMask_TFLEINT;
+
+ if (aFramePhase == I2s::ERight)
+ val &= ~KHtI2SIntMask_TFREINT;
+ }
+
+ if(aInterrupt & I2s::ERxOverrun)
+ {
+ if (aFramePhase == I2s::ELeft)
+ val &= ~KHtI2SIntMask_RFLORINT;
+
+ if (aFramePhase == I2s::ERight)
+ val &= ~KHtI2SIntMask_RFRORINT;
+ }
+
+ if(aInterrupt & I2s::ETxUnderrun)
+ {
+ if (aFramePhase == I2s::ELeft)
+ val &= ~KHtI2SIntMask_TFLURINT;
+
+ if (aFramePhase == I2s::ERight)
+ val &= ~KHtI2SIntMask_TFRURINT;
+ }
+
+ if(aInterrupt & I2s::EFramingError)
+ {
+ // not supported, do nothing
+ }
+
+ TInt irq=__SPIN_LOCK_IRQSAVE(I2sLock); // (read and clear), not used from ISR but made safe nevertheless...
+ TUint32 oldVal = AsspRegister::Read32(KHwI2SInterruptMask(iInterfaceId));
+ if (val!=oldVal)
+ {
+ // update the register
+ AsspRegister::Write32(KHwI2SInterruptMask(iInterfaceId), val);
+ }
+ __SPIN_UNLOCK_IRQRESTORE(I2sLock,irq);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::IsFIFOInterruptEnabled(TInt aFramePhase, TInt& aEnabled)
+ {
+ // check, if any interrupt is enabled..
+ TUint32 val = AsspRegister::Read32(KHwI2SInterruptMask(iInterfaceId));
+
+ aEnabled=0;
+ if(aFramePhase== I2s::ELeft)
+ {
+ if(val & KHtI2SIntMask_TFLURINT)// L-ch transmit FIFO underrun int enable
+ aEnabled |= I2s::ETxUnderrun;
+ if(val & KHtI2SIntMask_TFLEINT)// L-ch transmit FIFO reached the empty trigger level int enable
+ aEnabled |= I2s::ETxEmpty;
+ if(val & KHtI2SIntMask_RFLORINT)// L-ch receive FIFO overrun int enable
+ aEnabled |= I2s::ERxOverrun;
+ if(val & KHtI2SIntMask_RFLFINT)// L-ch receive FIFO reached the full trigger level int enable
+ aEnabled |= I2s::ERxFull;
+ }
+ else
+ {
+ if(val & KHtI2SIntMask_TFRURINT)// R-ch transmit FIFO underrun int enable
+ aEnabled |= I2s::ETxUnderrun;
+ if(val & KHtI2SIntMask_TFREINT)// R-ch transmit FIFO reached the empty trigger level int enable
+ aEnabled |= I2s::ETxEmpty;
+ if(val & KHtI2SIntMask_RFRORINT)// R-ch receive FIFO overrun int enable
+ aEnabled |= I2s::ERxOverrun;
+ if(val & KHtI2SIntMask_RFRFINT)// R-ch receive FIFO reached the full trigger level int enable
+ aEnabled |= I2s::ERxFull;
+ }
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::ReadFIFOLevel(TInt aFramePhase, TInt aDirection, TInt& aLevel)
+ {
+ // This device only allows us to see, if the receive FIFO or transmit FIFO is either
+ // empty or full, so return:
+ // TX FIFO: 1-FULL, 0-EMPTY,
+ // RX FIFO: 1-EMPTY, 0-FULL
+
+ TUint32 val = AsspRegister::Read32(KHwI2SFifoStatus(iInterfaceId));
+
+ if(aDirection & I2s::ETx)
+ {
+ if (aFramePhase == I2s::ELeft)
+ {
+ aLevel = (val & KHtI2SFifoSts_TFL_FULL) >> 17; // L-ch transmit FIFO full (bit 17)
+ }
+ else // I2s::ERight
+ {
+ aLevel = (val & KHtI2SFifoSts_TFR_FULL) >> 16; // R-ch transmit FIFO full (bit 16)
+ }
+ }
+ else // I2s::ERx
+ {
+ if (aFramePhase == I2s::ELeft)
+ {
+ aLevel = (val & KHtI2SFifoSts_RFL_EMPTY) >> 1; // L-ch receive FIFO empty (bit 1)
+ }
+ else // I2s::ERight
+ {
+ aLevel = val & KHtI2SFifoSts_RFR_EMPTY; // R-ch receive FIFO empty (bit 0)
+ }
+ }
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::EnableDMA(TInt aFifoMask)
+ {
+ TUint32 val=0;
+
+ if(aFifoMask & I2s::ETx)
+ val |= KHtI2SFifoCtrl_TDMAEN;
+
+ if(aFifoMask & I2s::ERx)
+ val |= KHtI2SFifoCtrl_RDMAEN;
+
+ AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), 0, val);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::DisableDMA(TInt aFifoMask)
+ {
+ TUint32 val=0;
+
+ if(aFifoMask & I2s::ETx)
+ val |= KHtI2SFifoCtrl_TDMAEN;
+
+ if(aFifoMask & I2s::ERx)
+ val |= KHtI2SFifoCtrl_RDMAEN;
+
+ AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), val, 0);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::IsDMAEnabled(TInt& aEnabled)
+ {
+ TUint32 val = AsspRegister::Read32(KHwI2SFifoControl(iInterfaceId));
+ aEnabled = 0;
+
+ if(val & KHtI2SFifoCtrl_TDMAEN)
+ aEnabled |= I2s::ETx;
+
+ if(val & KHtI2SFifoCtrl_RDMAEN)
+ aEnabled |= I2s::ERx;
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::Start(TInt aDirection)
+ {
+ TUint32 val=0;
+
+ if(aDirection & I2s::ERx)
+ {
+ // check, if the interface was configured for reception..
+ if (iConfig.iType != I2s::EReceiver && iConfig.iType != I2s::EBidirectional)
+ {
+ return KErrNotSupported;
+ }
+
+ __KTRACE_OPT(KDLL, Kern::Printf("I2S channel %d: Start Rx", iInterfaceId));
+ val |= KHtI2SCtrl_REN;
+ }
+ else
+ {
+ // check, if the interface was configured for transmission..
+ if (iConfig.iType != I2s::ETransmitter && iConfig.iType != I2s::EBidirectional)
+ {
+ return KErrNotSupported;
+ }
+
+ __KTRACE_OPT(KDLL, Kern::Printf("I2S channel %d: Start Tx", iInterfaceId));
+ val |= KHtI2SCtrl_TEN;
+ }
+
+ // update the register
+ AsspRegister::Modify32(KHwI2SControl(iInterfaceId), 0, val);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::Stop(TInt aDirection)
+ {
+ TUint32 val=0;
+
+ if(aDirection & I2s::ERx)
+ {
+ __KTRACE_OPT(KDLL, Kern::Printf("I2S channel %d: Stop Rx", iInterfaceId));
+ val = KHtI2SCtrl_REN;
+ }
+ else
+ {
+ __KTRACE_OPT(KDLL, Kern::Printf("I2S channel %d: Stop Rx", iInterfaceId));
+ val = KHtI2SCtrl_TEN;
+ }
+
+ // update the register
+ AsspRegister::Modify32(KHwI2SControl(iInterfaceId), val, 0);
+
+ return KErrNone;
+ }
+
+TInt D2sChannelNE1_TB::IsStarted(TInt aDirection, TBool& aStarted)
+ {
+ TUint32 val=AsspRegister::Read32(KHwI2SControl(iInterfaceId));
+
+ if(aDirection & I2s::ERx)
+ {
+ aStarted = (val & KHtI2SCtrl_REN) >> 24; // bit 24
+ }
+ else
+ {
+ aStarted = (val & KHtI2SCtrl_TEN) >> 25; // bit 25
+ }
+ return KErrNone;
+ }
+
+