navienginebsp/naviengine_assp/i2s/i2s_psl.cpp
changeset 0 5de814552237
equal deleted inserted replaced
-1:000000000000 0:5de814552237
       
     1 /*
       
     2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 * bsp\nwip_nec_naviengine\naviengine_assp\i2s\i2s_psl.cpp
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "navi_i2s.h"
       
    22 #include <naviengine.h>
       
    23 
       
    24 #ifdef __SMP__
       
    25 static TSpinLock I2sLock = TSpinLock(TSpinLock::EOrderGenericIrqLow2);
       
    26 #endif
       
    27 
       
    28 // All channels have the same configuration. 
       
    29 // base for registers are shifted for each channel by 0x400 (1<<10)
       
    30 #define HW_CHAN_SHIFT 10
       
    31 
       
    32 // Registers 
       
    33 // these macros will return register address for a given interface
       
    34 #define KHwI2SControl(intefaceId)		((KHwBaseI2S0 + KHoI2SCtrl)     + (intefaceId << HW_CHAN_SHIFT))
       
    35 #define KHwI2SFifoControl(intefaceId) 	((KHwBaseI2S0 + KHoI2SFifoCtrl) + (intefaceId << HW_CHAN_SHIFT))
       
    36 #define KHwI2SFifoStatus(intefaceId) 	((KHwBaseI2S0 + KHoI2SFifoSts)  + (intefaceId << HW_CHAN_SHIFT))
       
    37 #define KHwI2SInterruptFlag(intefaceId) ((KHwBaseI2S0 + KHoI2SIntFlg)   + (intefaceId << HW_CHAN_SHIFT))
       
    38 #define KHwI2SInterruptMask(intefaceId)	((KHwBaseI2S0 + KHoI2SIntMask)  + (intefaceId << HW_CHAN_SHIFT))
       
    39 #define KHwI2SDataIn(intefaceId) 		((KHwBaseI2S0 + KHoI2SRx)       + (intefaceId << HW_CHAN_SHIFT))
       
    40 #define KHwI2SDataOut(intefaceId) 		((KHwBaseI2S0 + KHoI2STx)       + (intefaceId << HW_CHAN_SHIFT))
       
    41 
       
    42 #define AsspIsBitSet(addr, bit)	     (AsspRegister::Read32(addr)& (bit))
       
    43 #define CLEARMASK(shift,len)         (((1 << len) - 1) << shift)
       
    44 #define AsspGetBits(w,shift,len)     ((AsspRegister::Read32(w) >> shift) & ((1 << (len)) - 1))
       
    45 #define AsspSetBits(w,set,shift,len) (AsspRegister::Modify32(w, (CLEARMASK(shift, len)) , (set << shift)))
       
    46 
       
    47 
       
    48 NONSHARABLE_CLASS(D2sChannelNE1_TB) : public DI2sChannelBase
       
    49 	{
       
    50 public:
       
    51 	D2sChannelNE1_TB(TInt aInterfaceId);
       
    52 	
       
    53 	virtual TInt ConfigureInterface(TDes8* aConfig);
       
    54 	virtual TInt GetInterfaceConfiguration(TDes8& aConfig);
       
    55 	virtual TInt SetSamplingRate(TInt aSamplingRate);
       
    56 	virtual TInt GetSamplingRate(TInt& aSamplingRate);
       
    57 	virtual TInt SetFrameLengthAndFormat(TInt aFrameLength, TInt aLeftFramePhaseLength);
       
    58 	virtual TInt GetFrameFormat(TInt& aLeftFramePhaseLength, TInt& aRightFramePhaseLength);
       
    59 	virtual TInt SetSampleLength(TInt aFramePhase, TInt aSampleLength);
       
    60 	virtual TInt GetSampleLength(TInt aFramePhase, TInt& aSampleLength);
       
    61 	virtual TInt SetDelayCycles(TInt aFramePhase, TInt aDelayCycles);
       
    62 	virtual TInt GetDelayCycles(TInt aFramePhase, TInt& aDelayCycles);
       
    63 	virtual TInt ReadReceiveRegister(TInt aFramePhase, TInt& aData);
       
    64 	virtual TInt WriteTransmitRegister(TInt aFramePhase, TInt aData);
       
    65 	virtual TInt ReadTransmitRegister(TInt aFramePhase, TInt& aData);
       
    66 	virtual TInt ReadRegisterModeStatus(TInt aFramePhase, TInt& aFlags);
       
    67 	virtual TInt EnableRegisterInterrupts(TInt aFramePhase, TInt aInterrupt);
       
    68 	virtual TInt DisableRegisterInterrupts(TInt aFramePhase, TInt aInterrupt);
       
    69 	virtual TInt IsRegisterInterruptEnabled(TInt aFramePhase, TInt& aEnabled);
       
    70 	virtual TInt EnableFIFO(TInt aFramePhase, TInt aFifoMask);
       
    71 	virtual TInt DisableFIFO(TInt aFramePhase, TInt aFifoMask);
       
    72 	virtual TInt IsFIFOEnabled(TInt aFramePhase, TInt& aEnabled);
       
    73 	virtual TInt SetFIFOThreshold(TInt aFramePhase, TInt aDirection, TInt aThreshold);
       
    74 	virtual TInt ReadFIFOModeStatus(TInt aFramePhase, TInt& aFlags);
       
    75 	virtual TInt EnableFIFOInterrupts(TInt aFramePhase, TInt aInterrupt);
       
    76 	virtual TInt DisableFIFOInterrupts(TInt aFramePhase, TInt aInterrupt);
       
    77 	virtual TInt IsFIFOInterruptEnabled(TInt aFramePhase, TInt& aEnabled);
       
    78 	virtual TInt ReadFIFOLevel(TInt aFramePhase, TInt aDirection, TInt& aLevel);
       
    79 	virtual TInt EnableDMA(TInt aFifoMask);
       
    80 	virtual TInt DisableDMA(TInt aFifoMask);
       
    81 	virtual TInt IsDMAEnabled(TInt& aEnabled);
       
    82 	virtual TInt Start(TInt aDirection);
       
    83 	virtual TInt Stop(TInt aDirection);
       
    84 	virtual TInt IsStarted(TInt aDirection, TBool& aStarted);		
       
    85 
       
    86 private: 
       
    87 	TBool iConfigured;
       
    88 	TInt iLastPhaseInWriteFifo;
       
    89 	TInt iLastPhaseInReadFifo;
       
    90 	};
       
    91 
       
    92 // this static method, creates the DI2sChannelBase corresponding
       
    93 // to the interfaceId passed and return the channel
       
    94 // NB: if each channel was implemented independently (e.g. on a separate file)
       
    95 // this function would have to be provided spearately and know how to map
       
    96 // the interface ID to the appropriate channel object to be created
       
    97 // (e.g. each channel would have a different implementation D2sChannelXXX
       
    98 // and this function call the appropriate constructor for each interface Id)
       
    99 
       
   100 TInt DI2sChannelBase::CreateChannels(DI2sChannelBase*& aChannel, TInt aInterfaceId)
       
   101 	{
       
   102 	DI2sChannelBase* chan = new D2sChannelNE1_TB(aInterfaceId);
       
   103 	if (!chan)
       
   104 		{
       
   105 		return KErrNoMemory;
       
   106 		}
       
   107 
       
   108 	aChannel = chan;
       
   109 	
       
   110 	return KErrNone;
       
   111 	}
       
   112 
       
   113 
       
   114 // Default constructor.
       
   115 D2sChannelNE1_TB::D2sChannelNE1_TB(TInt aInterfaceId):
       
   116 	iConfigured(EFalse), 
       
   117 	iLastPhaseInWriteFifo(I2s::ERight), // the first phase in write fifo should be left, so initialize to right 
       
   118 	iLastPhaseInReadFifo(I2s::ERight) // the first phase in read fifo should be left, so initialize to right
       
   119 	{
       
   120 	iInterfaceId=aInterfaceId;
       
   121 	}
       
   122 
       
   123 TInt D2sChannelNE1_TB::ConfigureInterface(TDes8 *aConfig)
       
   124 	{
       
   125 	__KTRACE_OPT(KDLL, Kern::Printf("DI2sChannelNE1_TB::ConfigureInterfaceInterface (Id: %d)", iInterfaceId));
       
   126 
       
   127 	if(AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
       
   128 		{
       
   129 		return KErrInUse;
       
   130 		}
       
   131 	
       
   132 	TI2sConfigBufV01 &conf = ((TI2sConfigBufV01&)*aConfig);
       
   133 
       
   134 	// this interface doesn's support EController mode
       
   135 	if (conf().iType == I2s::EController)
       
   136 		{
       
   137 		return KErrNotSupported;
       
   138 		}
       
   139 	
       
   140 	if(conf().iRole == I2s::EMaster)
       
   141 		{
       
   142 		AsspRegister::Modify32(KHwI2SControl(iInterfaceId), 0, KHtI2SCtrl_MSMODE);
       
   143 		}
       
   144 		
       
   145 	// copy configuration.. it will be used in Start/Stop
       
   146 	iConfig = conf();		// ok, thread context only and one client thread per channel
       
   147 	
       
   148 	 // select I2S format
       
   149 	AsspSetBits(KHwI2SControl(iInterfaceId), 4, KHsI2SCtrl_FORMAT, 3);
       
   150 
       
   151 	iConfigured = ETrue;	// this API can only be called in thread context and we assume that a channel is for use of a single thread
       
   152 	
       
   153 	return KErrNone;
       
   154 	}
       
   155 
       
   156 TInt D2sChannelNE1_TB::GetInterfaceConfiguration(TDes8 &aConfig)
       
   157 	{
       
   158 	if (!iConfigured)	// this API can only be called in thread context and we assume that a channel is for use of a single thread
       
   159 		{
       
   160 		aConfig.SetLength(0); //no configuration  present yet..
       
   161 		}
       
   162 	else
       
   163 		{
       
   164 		TPckgBuf<TI2sConfigV01> conf(iConfig);
       
   165 		aConfig.Copy(conf);
       
   166 		}
       
   167 	return KErrNone;
       
   168 	}
       
   169 
       
   170 TInt D2sChannelNE1_TB::SetSamplingRate(TInt aSamplingRate)
       
   171 	{
       
   172 	if (iConfig.iRole == I2s::ESlave)
       
   173 		{
       
   174 		return KErrNotSupported; 
       
   175 		}
       
   176 	
       
   177 	if (AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
       
   178 		{
       
   179 		return KErrInUse;
       
   180 		}
       
   181 	
       
   182 	TUint32 val = 0, div = 0;
       
   183 	
       
   184 	switch(aSamplingRate)
       
   185 		{
       
   186 		case I2s::E8KHz: 		// 0000: 8 kHz
       
   187 			div = 1; 			// MCLK = 24.5760 MHz(1*)
       
   188 			break;
       
   189 
       
   190 		case I2s::E11_025KHz:	// 1000: 11.025 kHz
       
   191 			val = 8;
       
   192 			div = 4; 			// MCLK = 33.8688 MHz(4*) or 22.5792(5*) or 16.9344 MHz(6)
       
   193 			break;
       
   194 
       
   195 		case I2s::E12KHz:		// 0001: 12 kHz
       
   196 			val = 1;
       
   197 			div = 1; 			// MCLK = 24.5760 MHz(1*) or 18.432MHz(2)
       
   198 			break;
       
   199 
       
   200 		case I2s::E16KHz:		// 0010: 16 kHz
       
   201 			val = 2;
       
   202 			div = 1; 			// MCLK = 24.5760 MHz(1*)
       
   203 			break;
       
   204 
       
   205 		case I2s::E22_05KHz:	// 1001: 22.05 kHz
       
   206 			val = 9;
       
   207 			div = 4; 			// MCLK = 33.8688 MHz(4*) or 22.5792(5*) or 16.9344 MHz(6)  
       
   208 			break;
       
   209 			
       
   210 		case I2s::E24KHz:		// 0011: 24 kHz
       
   211 			val = 3;
       
   212 			div = 1; 			// MCLK = 24.5760 MHz(1*) or 18.432MHz(2)
       
   213 			break;
       
   214 			
       
   215 		case I2s::E32KHz:		// 	0100: 32 kHz
       
   216 			val = 4;
       
   217 			div = 1; 			// MCLK = 24.5760 MHz
       
   218 			break;
       
   219 			
       
   220 		case I2s::E44_1KHz:		// 1010: 44.1 kHz
       
   221 			val = 10;
       
   222 			div = 4;			// MCLK = 33.8688 MHz(4*) or 22.5792(5*) or 16.9344 MHz(6)
       
   223 			break;
       
   224 			
       
   225 		case I2s::E48KHz:		// 0101: 48 kHz
       
   226 			val = 5;
       
   227 			div = 2; 			// MCLK = 24.5760 MHz(1*) or 18.432MHz(2)
       
   228 			break;
       
   229 
       
   230 		default:
       
   231 			return KErrNotSupported;
       
   232 		}
       
   233 
       
   234 	TInt irq=__SPIN_LOCK_IRQSAVE(I2sLock);		// seems that we must guarantee the following sequence is uninterrupted...
       
   235 	// before changing FSCLKSEL and/or FSMODE - mask I2S bit
       
   236 	// MSK_I2Sx (x=0:3): bits 18:21 in MaskCtrl Register of the System Ctrl Unit 
       
   237 	AsspRegister::Modify32(KHwBaseSCU + KHoSCUClockMaskCtrl, 0, (1<<iInterfaceId)<<18);
       
   238 	
       
   239 	// change the divide I2SCLK ctrl value for this channel..
       
   240 	AsspRegister::Modify32(KHwSystemCtrlBase+KHoSCUDivideI2SCLKCtrl, 0xf<<(iInterfaceId<<3), div<<(iInterfaceId<<3));  
       
   241 
       
   242 	// update the KHwI2SControl register
       
   243 	AsspSetBits(KHwI2SControl(iInterfaceId), val, KHsI2SCtrl_FCKLKSEL, 4); 
       
   244 
       
   245 	// after changing FSCLKSEL and FSMODE - clear MSK_I2Sx mask bit
       
   246 	AsspRegister::Modify32(KHwBaseSCU + KHoSCUClockMaskCtrl, (1<<iInterfaceId)<<18, 0);
       
   247 	__SPIN_UNLOCK_IRQRESTORE(I2sLock,irq);
       
   248 
       
   249 	return KErrNone;
       
   250 	}
       
   251 
       
   252 TInt D2sChannelNE1_TB::GetSamplingRate(TInt& aSamplingRate)
       
   253 	{
       
   254 	if (iConfig.iRole == I2s::ESlave)
       
   255 		{
       
   256 		return KErrNotSupported; 
       
   257 		}
       
   258 	
       
   259 	TUint32 val = (AsspRegister::Read32(KHwI2SControl(iInterfaceId))>>KHsI2SCtrl_FCKLKSEL) & 0xf;
       
   260 	
       
   261 	switch(val)
       
   262 		{
       
   263 		case 0:
       
   264 			aSamplingRate = I2s::E8KHz;		// 0000: 8 kHz
       
   265 			break;
       
   266 
       
   267 		case 8: 
       
   268 			aSamplingRate = I2s::E11_025KHz;	// 1000: 11.025 kHz
       
   269 			break;
       
   270 
       
   271 		case 1:
       
   272 			aSamplingRate = I2s::E12KHz;		// 0001: 12 kHz
       
   273 			break;
       
   274 
       
   275 		case 2:
       
   276 			aSamplingRate = I2s::E16KHz;		// 0010: 16 kHz
       
   277 			break;
       
   278 
       
   279 		case 9:
       
   280 			aSamplingRate = I2s::E22_05KHz;		// 1001: 22.05 kHz
       
   281 			break;
       
   282 			
       
   283 		case 3:
       
   284 			aSamplingRate = I2s::E24KHz;		// 0011: 24 kHz
       
   285 			break;
       
   286 			
       
   287 		case 4:
       
   288 			aSamplingRate = I2s::E32KHz;		// 	0100: 32 kHz
       
   289 			break;
       
   290 			
       
   291 		case 10:
       
   292 			aSamplingRate = I2s::E44_1KHz;		// 1010: 44.1 kHz
       
   293 			break;
       
   294 			
       
   295 		case 5:
       
   296 			aSamplingRate = I2s::E48KHz;		// 0101: 48 kHz
       
   297 			break;
       
   298 		}
       
   299 	
       
   300 	return KErrNone;
       
   301 	}
       
   302 
       
   303 TInt D2sChannelNE1_TB::SetFrameLengthAndFormat(TInt aFrameLength, TInt /*aLeftFramePhaseLength*/)
       
   304 	{
       
   305 	if (AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
       
   306 		{
       
   307 		return KErrInUse;
       
   308 		}
       
   309 	
       
   310 	TUint32 val=0;
       
   311 	
       
   312 	switch(aFrameLength)
       
   313 		{
       
   314 		case I2s::EFrame32Bit:
       
   315 			val = 0;
       
   316 			break;
       
   317 		
       
   318 		case I2s::EFrame48Bit: 
       
   319 			val = 1;
       
   320 			break;
       
   321 		
       
   322 		case I2s::EFrame64Bit:
       
   323 			val = 2;
       
   324 			break;
       
   325 
       
   326 		case I2s::EFrame128Bit:
       
   327 			val = 3;
       
   328 			break;
       
   329 
       
   330 		default:
       
   331 			return KErrNotSupported;
       
   332 		};
       
   333 	
       
   334 	TInt irq=__SPIN_LOCK_IRQSAVE(I2sLock);		// seems that we must guarantee the following sequence is uninterrupted
       
   335 	// before changing FSCLKSEL and/or FSMODE - mask I2S bit
       
   336 	// MSK_I2Sx (x=0:3): bits 18:21 in MaskCtrl Register of the System Ctrl Unit 
       
   337 	AsspRegister::Modify32(KHwBaseSCU + KHoSCUClockMaskCtrl, 0, (1<<iInterfaceId)<<18);
       
   338 	
       
   339 	// update the register (3 bits at KHsI2SCtrl_FSMODE)
       
   340 	AsspSetBits(KHwI2SControl(iInterfaceId), val, KHsI2SCtrl_FSMODE, 3);
       
   341 
       
   342 	// after changing FSCLKSEL and FSMODE - clear MSK_I2Sx mask bit
       
   343 	AsspRegister::Modify32(KHwBaseSCU + KHoSCUClockMaskCtrl, (1<<iInterfaceId)<<18, 0);
       
   344 	__SPIN_UNLOCK_IRQRESTORE(I2sLock,irq);
       
   345 	
       
   346 	return KErrNone; 
       
   347 	}
       
   348 
       
   349 TInt D2sChannelNE1_TB::GetFrameFormat(TInt& aLeftFramePhaseLength, TInt& aRightFramePhaseLength)
       
   350 	{
       
   351 	TInt frameLength=0;
       
   352 	switch(AsspGetBits(KHwI2SControl(iInterfaceId), KHsI2SCtrl_FSMODE, 3))
       
   353 		{
       
   354 		case 0:
       
   355 			frameLength = I2s::EFrame32Bit;
       
   356 			break;
       
   357 		
       
   358 		case 1:
       
   359 			frameLength = I2s::EFrame48Bit;
       
   360 			break;
       
   361 		
       
   362 		case 2: 
       
   363 			frameLength = I2s::EFrame64Bit;
       
   364 			break;
       
   365 
       
   366 		case 3:
       
   367 			frameLength = I2s::EFrame128Bit;
       
   368 			break;
       
   369 
       
   370 		default:
       
   371 			return KErrGeneral; //unexpected value??
       
   372 		};
       
   373 
       
   374 	aLeftFramePhaseLength=aRightFramePhaseLength=frameLength/2;	// on NaviEngine frames are symmetrical
       
   375 
       
   376 	return KErrNone; 
       
   377 	}
       
   378 
       
   379 TInt D2sChannelNE1_TB::SetSampleLength(TInt /*aFramePhase*/, TInt aSampleLength)
       
   380 	{
       
   381 	if (AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
       
   382 		{
       
   383 		return KErrInUse;
       
   384 		}
       
   385 
       
   386 	TUint32 val=0;
       
   387 	
       
   388 	switch(aSampleLength)
       
   389 		{
       
   390 		case I2s::ESample8Bit:
       
   391 			val = 0x8;
       
   392 			break;
       
   393 			
       
   394 		case I2s::ESample16Bit:
       
   395 			val = 0x10;
       
   396 			break;
       
   397 		
       
   398 		case I2s::ESample24Bit:
       
   399 			val = 0x18;
       
   400 			break;
       
   401 
       
   402 		case I2s::ESample12Bit:
       
   403 		case I2s::ESample32Bit:
       
   404 			return KErrNotSupported;
       
   405 		}
       
   406 	
       
   407 	// update the register.. 
       
   408 	AsspSetBits(KHwI2SControl(iInterfaceId), val, KHsI2SCtrl_DLENGTH,5); // [4:0] sampling data length);
       
   409 	
       
   410 	return KErrNone; 
       
   411 	}
       
   412 
       
   413 TInt D2sChannelNE1_TB::GetSampleLength(TInt /*aFramePhase*/, TInt& aSampleLength)
       
   414 	{
       
   415 	// sample length can't be configured separately for left/right channels..
       
   416 	// .. in this chip, so aFramePhase is ignored
       
   417 	
       
   418 	TUint32 val=AsspRegister::Read32(KHwI2SControl(iInterfaceId)) & 0x1F;
       
   419 	
       
   420 	switch(val)
       
   421 		{
       
   422 		case 0x8:
       
   423 			aSampleLength = I2s::ESample8Bit;
       
   424 			break;
       
   425 			
       
   426 		case 0x10: 
       
   427 			aSampleLength = I2s::ESample16Bit;
       
   428 			break;
       
   429 		
       
   430 		case 0x18: 
       
   431 			aSampleLength = I2s::ESample24Bit;
       
   432 			break;
       
   433 		}
       
   434 	
       
   435 	return KErrNone; 
       
   436 	}
       
   437 
       
   438 TInt D2sChannelNE1_TB::SetDelayCycles(TInt aFramePhase, TInt aDelayCycles)
       
   439 	{
       
   440 	return KErrNotSupported; 
       
   441 	}
       
   442 
       
   443 TInt D2sChannelNE1_TB::GetDelayCycles(TInt aFramePhase, TInt& aDelayCycles)
       
   444 	{
       
   445 	return KErrNotSupported; 
       
   446 	}
       
   447 
       
   448 TInt D2sChannelNE1_TB::ReadReceiveRegister(TInt aFramePhase, TInt& aData)
       
   449 	{
       
   450 	// should check here, if sample length was configured, 
       
   451 	// but once the interface is properly configured, this check would add unnecessary overhead.
       
   452 	
       
   453 	// since there is only one fifo for both channels in this chip, 
       
   454 	// we need to read Left and then Right channel data in sequence. 
       
   455 
       
   456 	TInt oldFP=__e32_atomic_swp_ord32(&iLastPhaseInReadFifo,aFramePhase);	// atomic as this may be used in ISR too
       
   457 	if(aFramePhase == oldFP)
       
   458 		{
       
   459 		return KErrNotSupported;
       
   460 		}
       
   461 
       
   462 	// and get the current data from the fifo register
       
   463 	aData = AsspRegister::Read32(KHwI2SDataIn(iInterfaceId));
       
   464 	return KErrNone; 	
       
   465 	}
       
   466 
       
   467 TInt D2sChannelNE1_TB::WriteTransmitRegister(TInt aFramePhase, TInt aData)
       
   468 	{
       
   469 	// should check here, if sample length was configured, 
       
   470 	// but once the interface is properly configured, this check would add unnecessary overhead.
       
   471 	
       
   472 	// since there is only one fifo for both channels in this chip, 
       
   473 	// we need to write Left and then right channel data in sequence. 
       
   474 
       
   475 	TInt oldFP=__e32_atomic_swp_ord32(&iLastPhaseInWriteFifo,aFramePhase);	// atomic as this may be used in ISR too
       
   476 	if(aFramePhase == oldFP)
       
   477 		{
       
   478 		return KErrNotSupported;
       
   479 		}
       
   480 
       
   481 	// and update the fifo register
       
   482 	AsspRegister::Write32(KHwI2SDataOut(iInterfaceId), aData);
       
   483 
       
   484 	return KErrNone; 
       
   485 	}
       
   486 
       
   487 TInt D2sChannelNE1_TB::ReadTransmitRegister(TInt aFramePhase, TInt& aData)
       
   488 	{
       
   489 	// since there is only one fifo for both channels in this chip, 
       
   490 	// we can only read the data for the last written phase (either left or right) 
       
   491 
       
   492 	TInt curFp=__e32_atomic_load_acq32(&iLastPhaseInWriteFifo);
       
   493 	if(aFramePhase != curFp)
       
   494 		{
       
   495 		return KErrArgument;
       
   496 		}
       
   497 	
       
   498 	// read the register
       
   499 	aData = AsspRegister::Read32(KHwI2SDataOut(iInterfaceId));
       
   500 	
       
   501 	return KErrNone; 
       
   502 	}
       
   503 
       
   504 TInt D2sChannelNE1_TB::ReadRegisterModeStatus(TInt aFramePhase, TInt& aFlags)
       
   505 	{
       
   506 	return KErrNotSupported; // register PIO mode not supported (FIFO always present)
       
   507 	}
       
   508 
       
   509 TInt D2sChannelNE1_TB::EnableRegisterInterrupts(TInt aFramePhase, TInt aInterrupt)
       
   510 	{
       
   511 	return KErrNotSupported; // register PIO mode not supported (FIFO always present)
       
   512 	}
       
   513 
       
   514 TInt D2sChannelNE1_TB::DisableRegisterInterrupts(TInt aFramePhase, TInt aInterrupt)
       
   515 	{
       
   516 	return KErrNotSupported; // register PIO mode not supported (FIFO always present)
       
   517 	}
       
   518 
       
   519 TInt D2sChannelNE1_TB::IsRegisterInterruptEnabled(TInt aFramePhase, TInt& aEnabled)
       
   520 	{
       
   521 	return KErrNotSupported; // register PIO mode not supported (FIFO always present)
       
   522 	}
       
   523 
       
   524 TInt D2sChannelNE1_TB::EnableFIFO(TInt /*aFramePhase*/, TInt aFifoMask)
       
   525 	{
       
   526 	TInt val=0;
       
   527 	
       
   528 	// Set and clear fifo init bits for transmit/receive
       
   529 	// tere are only two FIFOs - not separated to phases..
       
   530 	if(aFifoMask & I2s::ETx) 
       
   531 		val = KHtI2SFifoCtrl_TFIFOCLR;
       
   532 
       
   533 	if(aFifoMask & I2s::ERx) 
       
   534 		val |= KHtI2SFifoCtrl_RFIFOCLR;
       
   535 			
       
   536 	AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), 0,  val);
       
   537 	AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), val, 0);
       
   538 
       
   539 	return KErrNone; 
       
   540 	}
       
   541 
       
   542 TInt D2sChannelNE1_TB::DisableFIFO(TInt aFramePhase, TInt aFifoMask)
       
   543 	{
       
   544 	// fifo is always enabled in this chip.. 
       
   545 	return KErrNotSupported; 
       
   546 	}
       
   547 
       
   548 TInt D2sChannelNE1_TB::IsFIFOEnabled(TInt /*aFramePhase*/, TInt& aEnabled)
       
   549 	{
       
   550 	// fifo is always enabled in this chip.. 
       
   551 	aEnabled = I2s::ERx|I2s::ETx;
       
   552 	return KErrNone; 
       
   553 	}
       
   554 
       
   555 TInt D2sChannelNE1_TB::SetFIFOThreshold(TInt aFramePhase, TInt aDirection, TInt aThreshold)
       
   556 	{
       
   557 	// supported threshold values for this chip: 
       
   558 	// 011b - 16-word space available
       
   559 	// 010b - 8-word space available
       
   560 	// 001b - 4-word space available
       
   561 	// 000b - 2-word space available
       
   562 	if (aThreshold < 0)
       
   563 		{
       
   564 		return KErrNotSupported;
       
   565 		}
       
   566 
       
   567 	// Determine, what value was specified, and adjust it down to one  
       
   568 	// of the possible values
       
   569 	TInt i=15;
       
   570 	while(i>1)
       
   571 		{
       
   572 		if ( aThreshold!=(aThreshold & i))
       
   573 			break;
       
   574 		i>>=1;
       
   575 		}
       
   576 	aThreshold = i+1; //this will now contain one of possible values (2-16);
       
   577 	
       
   578 	// now any of 16/8/4/2, shifted right until == 0 will give us requested register_value+2
       
   579 	// (instead of using 'switch(aThreshold)') 
       
   580 	i=0;
       
   581 	while(aThreshold)
       
   582 		{
       
   583 		aThreshold>>=1;
       
   584 		++i;
       
   585 		}
       
   586 	aThreshold = i-2 >= 0 ? i-2 : 0; //if i-2 gives <0 (e.g.for aThreshold<4) -adjust to 0;
       
   587 	
       
   588 	if (AsspIsBitSet(KHwI2SControl(iInterfaceId), KHtI2SCtrl_TEN | KHtI2SCtrl_REN))
       
   589 		{
       
   590 		return KErrInUse;
       
   591 		}
       
   592 
       
   593 	TUint32 clr, set;
       
   594 	if(aDirection & I2s::ERx)  // receive fifo..
       
   595 		{
       
   596 		if (aFramePhase == I2s::ELeft)   	
       
   597 			{
       
   598 			clr = CLEARMASK(KHsI2SFifoCtrl_RFIFOLT, 3);
       
   599 			set = (aThreshold << KHsI2SFifoCtrl_RFIFOLT);
       
   600 			}
       
   601 
       
   602 		else //if (aFramePhase == I2s::ERight)
       
   603 			{
       
   604 			clr = CLEARMASK(KHsI2SFifoCtrl_RFIFORT, 3);
       
   605 			set = (aThreshold << KHsI2SFifoCtrl_RFIFORT);
       
   606 			}
       
   607 		}
       
   608 	else 	// transmit fifo..
       
   609 		{
       
   610 		if (aFramePhase == I2s::ELeft)  
       
   611 			{
       
   612 			clr = CLEARMASK(KHsI2SFifoCtrl_TFIFOLT, 3);
       
   613 			set = (aThreshold << KHsI2SFifoCtrl_TFIFOLT);
       
   614 
       
   615 			}
       
   616 		else // if (aFramePhase == I2s::ERight)
       
   617 			{
       
   618 			clr = CLEARMASK(KHsI2SFifoCtrl_TFIFORT, 3);
       
   619 			set = (aThreshold << KHsI2SFifoCtrl_TFIFORT);
       
   620 			}
       
   621 		}
       
   622 	// updating register with value will also clear FIFO initialization bits.. 
       
   623 	AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), clr, set);
       
   624 
       
   625 	return KErrNone; 
       
   626 	}
       
   627 
       
   628 TInt D2sChannelNE1_TB::ReadFIFOModeStatus(TInt aFramePhase, TInt& aFlags)
       
   629 	{
       
   630 	aFlags = 0;
       
   631 
       
   632 	TInt irq=__SPIN_LOCK_IRQSAVE(I2sLock);		// (read and clear), can be used in ISR
       
   633 	TUint32 flags = AsspRegister::Read32(KHwI2SInterruptFlag(iInterfaceId));
       
   634 	AsspRegister::Write32(KHwI2SInterruptFlag(iInterfaceId), flags);	// clear the status flags (after reading)
       
   635 	__SPIN_UNLOCK_IRQRESTORE(I2sLock,irq);
       
   636 	
       
   637 	if (aFramePhase == I2s::ELeft)
       
   638 		{
       
   639 		if(flags & KHtI2SIntFlg_TFLURINT)	// L-ch transmit FIFO underrun
       
   640 			aFlags |= I2s::ETxUnderrun;
       
   641 
       
   642 		if(flags & KHtI2SIntFlg_TFLEINT)	// L-ch transmit FIFO reached the empty trigger level
       
   643 			aFlags |= I2s::ETxEmpty;
       
   644 
       
   645 		if(flags & KHtI2SIntFlg_RFLORINT)	// L-ch receive FIFO overrun
       
   646 			aFlags |= I2s::ERxOverrun;
       
   647 		
       
   648 		if(flags & KHtI2SIntFlg_RFLFINT)	// L-ch receive FIFO reached the full trigger level
       
   649 			aFlags |= I2s::ERxFull;
       
   650 		}
       
   651 	else
       
   652 		{
       
   653 		if(flags & KHtI2SIntFlg_TFRURINT)	// R-ch transmit FIFO underrun
       
   654 			aFlags |= I2s::ETxUnderrun;
       
   655 
       
   656 		if(flags & KHtI2SIntFlg_TFREINT)	// R-ch transmit FIFO reached the empty trigger level
       
   657 			aFlags |= I2s::ETxEmpty;
       
   658 
       
   659 		if(flags & KHtI2SIntFlg_RFRORINT)	// R-ch receive FIFO overrun
       
   660 			aFlags |= I2s::ERxOverrun;
       
   661 		
       
   662 		if(flags & KHtI2SIntFlg_RFRFINT)	// R-ch receive FIFO reached the full trigger level
       
   663 			aFlags |= I2s::ERxFull;
       
   664 		}
       
   665 	
       
   666 	return KErrNone; 
       
   667 	}
       
   668 
       
   669 TInt D2sChannelNE1_TB::EnableFIFOInterrupts(TInt aFramePhase, TInt aInterrupt)
       
   670 	{
       
   671 	TUint32 val=0;
       
   672 	
       
   673 	if(aInterrupt & I2s::ERxFull)
       
   674 		{
       
   675 		if (aFramePhase == I2s::ELeft)
       
   676 			val |= KHtI2SIntMask_RFLFINT;
       
   677 
       
   678 		if (aFramePhase == I2s::ERight)
       
   679 			val |= KHtI2SIntMask_RFRFINT;
       
   680 		}
       
   681 
       
   682 	if(aInterrupt & I2s::ETxEmpty)
       
   683 		{
       
   684 		if (aFramePhase == I2s::ELeft)
       
   685 			val |= KHtI2SIntMask_TFLEINT;
       
   686 
       
   687 		if (aFramePhase == I2s::ERight)
       
   688 			val |= KHtI2SIntMask_TFREINT;
       
   689 		}
       
   690 
       
   691 	if(aInterrupt & I2s::ERxOverrun)
       
   692 		{
       
   693 		if (aFramePhase == I2s::ELeft)
       
   694 			val |= KHtI2SIntMask_RFLORINT;
       
   695 
       
   696 		if (aFramePhase == I2s::ERight)
       
   697 			val |= KHtI2SIntMask_RFRORINT;
       
   698 		}
       
   699 
       
   700 	if(aInterrupt & I2s::ETxUnderrun)
       
   701 		{
       
   702 		if (aFramePhase == I2s::ELeft)
       
   703 			val |= KHtI2SIntMask_TFLURINT;
       
   704 
       
   705 		if (aFramePhase == I2s::ERight)
       
   706 			val |= KHtI2SIntMask_TFRURINT;
       
   707 		}
       
   708 	
       
   709 	if(aInterrupt & I2s::EFramingError)
       
   710 		{
       
   711 		// not supported, do nothing
       
   712 		}
       
   713 
       
   714 	if (val)
       
   715 		{
       
   716 		// update the register
       
   717 		AsspRegister::Write32(KHwI2SInterruptMask(iInterfaceId), val);
       
   718 		}
       
   719 	
       
   720 	return KErrNone;
       
   721 	}
       
   722 
       
   723 TInt D2sChannelNE1_TB::DisableFIFOInterrupts(TInt aFramePhase, TInt aInterrupt)
       
   724 	{
       
   725 	TUint32 val = KHmI2SIntMask_ALL;
       
   726 	
       
   727 	if(aInterrupt & I2s::ERxFull)
       
   728 		{
       
   729 		if (aFramePhase == I2s::ELeft)
       
   730 			val &= ~KHtI2SIntMask_RFLFINT;
       
   731 
       
   732 		if (aFramePhase == I2s::ERight)
       
   733 			val &= ~KHtI2SIntMask_RFRFINT;
       
   734 		}
       
   735 
       
   736 	if(aInterrupt & I2s::ETxEmpty)
       
   737 		{
       
   738 		if (aFramePhase == I2s::ELeft)
       
   739 			val &= ~KHtI2SIntMask_TFLEINT;
       
   740 
       
   741 		if (aFramePhase == I2s::ERight)
       
   742 			val &= ~KHtI2SIntMask_TFREINT;
       
   743 		}
       
   744 
       
   745 	if(aInterrupt & I2s::ERxOverrun)
       
   746 		{
       
   747 		if (aFramePhase == I2s::ELeft)
       
   748 			val &= ~KHtI2SIntMask_RFLORINT;
       
   749 
       
   750 		if (aFramePhase == I2s::ERight)
       
   751 			val &= ~KHtI2SIntMask_RFRORINT;
       
   752 		}
       
   753 
       
   754 	if(aInterrupt & I2s::ETxUnderrun)
       
   755 		{
       
   756 		if (aFramePhase == I2s::ELeft)
       
   757 			val &= ~KHtI2SIntMask_TFLURINT;
       
   758 
       
   759 		if (aFramePhase == I2s::ERight)
       
   760 			val &= ~KHtI2SIntMask_TFRURINT;
       
   761 		}
       
   762 	
       
   763 	if(aInterrupt & I2s::EFramingError)
       
   764 		{
       
   765 		// not supported, do nothing
       
   766 		}
       
   767 
       
   768 	TInt irq=__SPIN_LOCK_IRQSAVE(I2sLock);		// (read and clear), not used from ISR but made safe nevertheless...
       
   769 	TUint32 oldVal = AsspRegister::Read32(KHwI2SInterruptMask(iInterfaceId));
       
   770 	if (val!=oldVal)
       
   771 		{
       
   772 		// update the register
       
   773 		AsspRegister::Write32(KHwI2SInterruptMask(iInterfaceId), val);
       
   774 		}
       
   775 	__SPIN_UNLOCK_IRQRESTORE(I2sLock,irq);
       
   776 	
       
   777 	return KErrNone;
       
   778 	}
       
   779 
       
   780 TInt D2sChannelNE1_TB::IsFIFOInterruptEnabled(TInt aFramePhase, TInt& aEnabled)
       
   781 	{
       
   782 	// check, if any interrupt is enabled.. 
       
   783 	TUint32 val = AsspRegister::Read32(KHwI2SInterruptMask(iInterfaceId));
       
   784 
       
   785 	aEnabled=0;
       
   786 	if(aFramePhase== I2s::ELeft)
       
   787 		{
       
   788 		if(val & KHtI2SIntMask_TFLURINT)// L-ch transmit FIFO underrun int enable
       
   789 			aEnabled |= I2s::ETxUnderrun;
       
   790 		if(val & KHtI2SIntMask_TFLEINT)// L-ch transmit FIFO reached the empty trigger level int enable
       
   791 			aEnabled |= I2s::ETxEmpty;
       
   792 		if(val & KHtI2SIntMask_RFLORINT)// L-ch receive FIFO overrun int enable
       
   793 			aEnabled |= I2s::ERxOverrun;
       
   794 		if(val & KHtI2SIntMask_RFLFINT)// L-ch receive FIFO reached the full trigger level int enable
       
   795 			aEnabled |= I2s::ERxFull;
       
   796 		}
       
   797 	else
       
   798 		{
       
   799 		if(val & KHtI2SIntMask_TFRURINT)// R-ch transmit FIFO underrun int enable
       
   800 			aEnabled |= I2s::ETxUnderrun;
       
   801 		if(val & KHtI2SIntMask_TFREINT)// R-ch transmit FIFO reached the empty trigger level int enable
       
   802 			aEnabled |= I2s::ETxEmpty;
       
   803 		if(val & KHtI2SIntMask_RFRORINT)// R-ch receive FIFO overrun int enable
       
   804 			aEnabled |= I2s::ERxOverrun;
       
   805 		if(val & KHtI2SIntMask_RFRFINT)// R-ch receive FIFO reached the full trigger level int enable
       
   806 			aEnabled |= I2s::ERxFull;
       
   807 		}
       
   808 		
       
   809 	return KErrNone; 
       
   810 	}
       
   811 
       
   812 TInt D2sChannelNE1_TB::ReadFIFOLevel(TInt aFramePhase, TInt aDirection, TInt& aLevel)
       
   813 	{
       
   814 	// This device only allows us to see, if the receive FIFO or transmit FIFO is either 
       
   815 	// empty or full, so return: 
       
   816 	// TX FIFO: 1-FULL,  0-EMPTY, 
       
   817 	// RX FIFO: 1-EMPTY, 0-FULL
       
   818 	
       
   819 	TUint32 val = AsspRegister::Read32(KHwI2SFifoStatus(iInterfaceId));
       
   820 
       
   821 	if(aDirection & I2s::ETx)
       
   822 		{
       
   823 		if (aFramePhase == I2s::ELeft)
       
   824 			{
       
   825 			aLevel = (val & KHtI2SFifoSts_TFL_FULL) >> 17;  // L-ch transmit FIFO full (bit 17)
       
   826 			}
       
   827 		else // I2s::ERight
       
   828 			{
       
   829 			aLevel = (val & KHtI2SFifoSts_TFR_FULL) >> 16;  // R-ch transmit FIFO full (bit 16)
       
   830 			}
       
   831 		}
       
   832 	else  // I2s::ERx
       
   833 		{
       
   834 		if (aFramePhase == I2s::ELeft)
       
   835 			{
       
   836 			aLevel = (val & KHtI2SFifoSts_RFL_EMPTY) >> 1;  // L-ch receive FIFO empty (bit 1)
       
   837 			}
       
   838 		else // I2s::ERight
       
   839 			{
       
   840 			aLevel = val & KHtI2SFifoSts_RFR_EMPTY;  // R-ch receive FIFO empty (bit 0)
       
   841 			}
       
   842 		}
       
   843 	
       
   844 	return KErrNone; 
       
   845 	}
       
   846 
       
   847 TInt D2sChannelNE1_TB::EnableDMA(TInt aFifoMask)
       
   848 	{
       
   849 	TUint32 val=0;
       
   850 
       
   851 	if(aFifoMask & I2s::ETx)
       
   852 		val |= KHtI2SFifoCtrl_TDMAEN;
       
   853 
       
   854 	if(aFifoMask & I2s::ERx)
       
   855 		val |= KHtI2SFifoCtrl_RDMAEN;
       
   856 	
       
   857 	AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), 0, val);
       
   858 
       
   859 	return KErrNone; 
       
   860 	}
       
   861 
       
   862 TInt D2sChannelNE1_TB::DisableDMA(TInt aFifoMask)
       
   863 	{
       
   864 	TUint32 val=0;
       
   865 
       
   866 	if(aFifoMask & I2s::ETx)
       
   867 		val |= KHtI2SFifoCtrl_TDMAEN;
       
   868 
       
   869 	if(aFifoMask & I2s::ERx)
       
   870 		val |= KHtI2SFifoCtrl_RDMAEN;
       
   871 	
       
   872 	AsspRegister::Modify32(KHwI2SFifoControl(iInterfaceId), val, 0);
       
   873 
       
   874 	return KErrNone; 
       
   875 	}
       
   876 
       
   877 TInt D2sChannelNE1_TB::IsDMAEnabled(TInt& aEnabled)
       
   878 	{ 
       
   879 	TUint32 val = AsspRegister::Read32(KHwI2SFifoControl(iInterfaceId));
       
   880 	aEnabled = 0;
       
   881 	
       
   882 	if(val & KHtI2SFifoCtrl_TDMAEN)
       
   883 		aEnabled |= I2s::ETx;
       
   884 
       
   885 	if(val & KHtI2SFifoCtrl_RDMAEN)
       
   886 		aEnabled |= I2s::ERx;
       
   887 	
       
   888 	return KErrNone; 
       
   889 	}
       
   890 
       
   891 TInt D2sChannelNE1_TB::Start(TInt aDirection)
       
   892 	{
       
   893 	TUint32 val=0;
       
   894 	
       
   895 	if(aDirection & I2s::ERx)  
       
   896 		{
       
   897 		// check, if the interface was configured for reception.. 
       
   898 		if (iConfig.iType != I2s::EReceiver && iConfig.iType != I2s::EBidirectional)
       
   899 			{
       
   900 			return KErrNotSupported;
       
   901 			}
       
   902 
       
   903 		__KTRACE_OPT(KDLL, Kern::Printf("I2S channel %d: Start Rx", iInterfaceId));
       
   904 		val |= KHtI2SCtrl_REN;	
       
   905 		}
       
   906 	else
       
   907 		{
       
   908 		// check, if the interface was configured for transmission.. 
       
   909 		if (iConfig.iType != I2s::ETransmitter && iConfig.iType != I2s::EBidirectional)
       
   910 			{
       
   911 			return KErrNotSupported;
       
   912 			}
       
   913 		
       
   914 		__KTRACE_OPT(KDLL, Kern::Printf("I2S channel %d: Start Tx", iInterfaceId));
       
   915 		val |= KHtI2SCtrl_TEN;
       
   916 		}
       
   917 
       
   918 	// update the register
       
   919 	AsspRegister::Modify32(KHwI2SControl(iInterfaceId), 0, val);
       
   920 
       
   921 	return KErrNone; 
       
   922 	}
       
   923 
       
   924 TInt D2sChannelNE1_TB::Stop(TInt aDirection)
       
   925 	{
       
   926 	TUint32 val=0;
       
   927 	
       
   928 	if(aDirection & I2s::ERx)  
       
   929 		{
       
   930 		__KTRACE_OPT(KDLL, Kern::Printf("I2S channel %d: Stop Rx", iInterfaceId));
       
   931 		val = KHtI2SCtrl_REN;	
       
   932 		}
       
   933 	else
       
   934 		{
       
   935 		__KTRACE_OPT(KDLL, Kern::Printf("I2S channel %d: Stop Rx", iInterfaceId));
       
   936 		val = KHtI2SCtrl_TEN;
       
   937 		}
       
   938 
       
   939 	// update the register
       
   940 	AsspRegister::Modify32(KHwI2SControl(iInterfaceId), val, 0);
       
   941 	
       
   942 	return KErrNone; 
       
   943 	}
       
   944 
       
   945 TInt D2sChannelNE1_TB::IsStarted(TInt aDirection, TBool& aStarted)
       
   946 	{
       
   947 	TUint32 val=AsspRegister::Read32(KHwI2SControl(iInterfaceId));
       
   948 	
       
   949 	if(aDirection & I2s::ERx)
       
   950 		{
       
   951 		aStarted = (val & KHtI2SCtrl_REN) >> 24; // bit 24
       
   952 		}
       
   953 	else
       
   954 		{
       
   955 		aStarted = (val & KHtI2SCtrl_TEN) >> 25; // bit 25
       
   956 		}
       
   957 	return KErrNone; 
       
   958 	}
       
   959 
       
   960