1 /*
2 * Aic31.c
3 *
4 * This file contains Driver Layer Interface implementation for Aic3106 codec
5 * Driver. Aic3106 Codec Driver provides Driver Layer Interface to do operations
6 * on the Aic3106 peripheral like device initialization, channel creation,
7 * control commands for peripheral specific operations etc
8 *
9 * Copyright (C) 2009-2019 Texas Instruments Incorporated - http://www.ti.com/
10 *
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the
22 * distribution.
23 *
24 * Neither the name of Texas Instruments Incorporated nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 */
42 /** \file Aic31.c
43 *
44 * \brief Implementation of the IOM for the AIC31 audio codec.
45 *
46 * This file contains the implementation of the AIC31 audio codec driver for
47 * DSP BIOS operating system.
48 *
49 * (C) Copyright 2009, Texas Instruments, Inc
50 */
52 /* ========================================================================== */
53 /* INCLUDE FILES */
54 /* ========================================================================== */
55 #define SW_I2C
56 #include <xdc/std.h>
57 #include <ti/sysbios/io/IOM.h>
58 #include <assert.h>
59 #include <string.h>
60 #include <ti/sysbios/knl/Semaphore.h>
61 #include <ti/sysbios/io/GIO.h>
63 #ifndef SW_I2C
64 #include <i2c/include/I2c.h>
65 #else
66 //#include <include/i2c.h>
67 #endif /* SW_I2C */
70 #include <Aic31.h>
71 #include <ICodec.h>
72 #include <Aic31Local.h>
74 #ifdef SW_I2C
75 #include <ti/csl/cslr_device.h>
76 #include <codec_if.h>
77 #include <mcasp_cfg.h>
78 #include <aic31_if.h>
79 #endif /* SW_I2C */
81 #ifdef SW_I2C
82 extern void I2CCodecIsr(void);
83 #endif /* SW_I2C */
85 /* -------- constants -------- */
86 const Aic31_Params Aic31_PARAMS = {
87 ICodec_CodecType_AIC31, /* acType */
88 ICodec_ControlBusType_I2C, /* acControlBusType */
89 "NONE", /* acCtrlBusName */
90 #if defined (MCASP_MASTER)
91 ICodec_OpMode_SLAVE, /* acOpMode */
92 #else // MCASP is slave
93 ICodec_OpMode_MASTER, /* acOpMode */
94 #endif
95 #if defined DSP_MODE
96 ICodec_DataType_DSP,
97 (uint32_t)ICodec_SlotWidth_16, /* acSlotWidth */
98 #else
99 ICodec_DataType_I2S, /* acSerialDataType */
100 (uint32_t)ICodec_SlotWidth_32, /* acSlotWidth */
101 #endif
102 ICodec_DataPath_TXRX, /* acDataPath */
103 0, /* isRxTxClockIndependent */
104 };
106 /* ========================================================================== */
107 /* GLOBAL MODULE STATE */
108 /* ========================================================================== */
109 /**
110 * \brief Array which is part of Aic31 Module State
111 */
112 static Bool inUse[AIC31_NUM_INSTANCES];
113 /**
114 * \brief Aic31 Module State Object
115 */
116 static Aic31_Module_State Aic31_module = {&inUse[0]};
117 /**
118 * \brief Array of Aic31 instance State objects array
119 */
120 static Aic31_Object Aic31_Instances[AIC31_NUM_INSTANCES];
121 /**
122 * \brief Array for per instance device information
123 */
124 Aic31_HwInfo Aic31_deviceInstInfo[AIC31_NUM_INSTANCES];
126 /* ========================================================================== */
127 /* Aic31 Local Functions Definitions */
128 /* ========================================================================== */
129 /* ========================================================================== */
130 /* LOCAL FUNCTION PROTOTYPES */
131 /* ========================================================================== */
132 Int aic31MdBindDev(Ptr *devp, Int devId, Ptr devParams);
133 Int aic31MdUnBindDev(Ptr devp);
134 Int aic31MdCreateChan(
135 Ptr *chanp,
136 Ptr devp,
137 String name,
138 Int mode,
139 Ptr chanParams,
140 IOM_TiomCallback cbFxn,
141 Ptr cbArg
142 );
143 Int aic31MdDeleteChan(Ptr chanp);
144 Int aic31MdSubmitChan(Ptr chanp, IOM_Packet *ioPacket);
145 Int aic31MdControlChan(Ptr chanp, Uns cmd, Ptr cmdArgs);
148 static Bool aic31I2cWrite(Aic31_Object *instHandle,
149 uint32_t deviceId,
150 ICodec_RegData *wrRegData);
152 static Bool aic31RegWrite(Aic31_Object *instHandle,
153 uint8_t regAddr,
154 uint8_t regData);
156 static Bool aic31I2cRead(Aic31_Object *instHandle,
157 uint32_t deviceId,
158 ICodec_RegData *rdRegData);
160 static Bool aic31RegRead(Aic31_Object *instHandle,
161 uint8_t regAddr,
162 uint8_t *regData);
164 static Bool aic31CtrlBusWrite(Aic31_Object *instHandle,
165 ICodec_RegData *wrRegData);
167 static Bool aic31CtrlBusRead(Aic31_Object *instHandle,
168 ICodec_RegData *rdRegData);
170 static int32_t aic31MuteConfig(Aic31_Object *instHandle,
171 ICodec_Channel acChannel,
172 Bool muteConfig);
174 static int32_t aic31SetSamplingRate(Aic31_Object *instHandle,
175 ICodec_Channel acChannel,
176 uint32_t sampleRate);
178 #ifndef SW_I2C
179 static int32_t aic31InitAdc (Aic31_Object *instHandle);
181 static int32_t aic31InitDac (Aic31_Object *instHandle);
183 static int32_t aic31DeinitAdc(Aic31_Object *instHandle);
185 static int32_t aic31DeinitDac(Aic31_Object *instHandle);
187 static Void aic31CallBack (Ptr semHandle, IOM_Packet * ioPacket);
188 #endif /* SW_I2C */
190 static Bool aic31RegWriteBf(Aic31_Object *instHandle,
191 uint8_t regAddr,
192 uint8_t bfPosition,
193 uint8_t bfSize,
194 uint8_t bfData);
196 static int32_t aic31SelectInputSource(Aic31_Object *instHandle,
197 Ptr srcOption);
199 static int32_t aic31SelectOutputDest(Aic31_Object *instHandle,
200 Ptr destOption);
203 /**
204 * \brief IOM function pointer table.
205 *
206 * This variables is the array of function pointers of all the IOM
207 * functions implemented by the codec driver.
208 *
209 */
211 const IOM_Fxns Aic31_IOMFXNS =
212 {
213 &aic31MdBindDev,
214 &aic31MdUnBindDev,
215 &aic31MdControlChan,
216 &aic31MdCreateChan,
217 &aic31MdDeleteChan,
218 &aic31MdSubmitChan,
219 };
223 /* ========================================================================== */
224 /* FUNCTION DEFINTIONS */
225 /* ========================================================================== */
226 /**
227 * \brief Function called by Bios during instance initialisation
228 *
229 */
230 Void Aic31_init(Void)
231 {
232 Int i;
234 for (i = 0; i < AIC31_NUM_INSTANCES; i++)
235 {
236 /* have to initialize statically */
237 Aic31_module.inUse[i] = FALSE;
238 memset((Void *)&Aic31_Instances[i], 0x0, sizeof(Aic31_Object));
239 }
241 Aic31_deviceInstInfo[0].deviceAddress = (uint32_t)AIC31_INST0_ADDRESS;
243 }
245 /**
246 * \brief Function called by Bios during instance initialisation
247 *
248 * \param devp [OUT] Pointer to the codec driver object
249 * \param devId [IN] instance number of the codec
250 * \param devParams [IN] Device parameters passed by the user
251 *
252 * \return IOM_COMPLETED if success
253 * Error ID in case of error
254 */
255 Int aic31MdBindDev(Ptr *devp, Int devId, Ptr devParams)
256 {
257 int32_t retVal = IOM_COMPLETED;
258 Aic31_Params *params = NULL;
259 uint32_t count = 0;
260 Aic31_Object *instHandle = NULL;
262 /* Begin parameter checking */
263 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
264 if ((NULL == devp) ||
265 (AIC31_NUM_INSTANCES <= devId) ||
266 (TRUE == Aic31_module.inUse[devId]))
267 {
268 retVal = IOM_EBADARGS;
269 }
270 #endif /* PSP_DISABLE_INPUT_PARAMETER_CHECK */
271 /* End parameter checking */
273 if (IOM_COMPLETED == retVal)
274 {
275 instHandle = &Aic31_Instances[devId];
277 if (devParams == NULL)
278 {
279 params = (Aic31_Params*)&Aic31_PARAMS;
280 }
281 else
282 {
283 params = (Aic31_Params*) devParams;
284 }
286 Aic31_module.inUse[devId] = TRUE;
288 /* copy the initialization parameters */
289 instHandle->acType = params->acType;
290 instHandle->instNum = (uint8_t)devId;
291 instHandle->acControlBusType = params->acControlBusType;
292 instHandle->acCtrlBusName = params->acCtrlBusName;
293 instHandle->acOpMode = params->acOpMode;
294 instHandle->acSerialDataType = params->acSerialDataType;
295 instHandle->acSlotWidth = params->acSlotWidth;
296 instHandle->acDataPath = params->acDataPath;
297 instHandle->isRxTxClockIndependent = params->isRxTxClockIndependent;
298 instHandle->acCodecId = Aic31_deviceInstInfo[devId].deviceAddress;
300 #ifdef SW_I2C
301 instHandle->acCtrlBusInstNum = params->acCtrlBusInstNum;
303 if (instHandle->acControlBusType == ICodec_ControlBusType_I2C)
304 {
305 if (instHandle->acCtrlBusInstNum == 0)
306 {
307 instHandle->acBaseAddress = SOC_I2C_1_REGS;
308 }
309 else
310 {
311 retVal = IOM_EBADARGS;
312 }
313 }
314 else
315 {
316 /* Only 'ICodec_ControlBusType_I2C' suppoted currently */
317 retVal = IOM_EBADARGS;
318 }
319 #endif /* SW_I2C */
321 for (count = 0; count < ICodec_Channel_MAX; count++)
322 {
323 /* Set the state of both the channels as closed */
324 instHandle->ChanObj[count].chanStatus = ICodec_DriverState_CLOSED;
325 instHandle->ChanObj[count].channelMode = ICodec_Channel_MAX;
326 instHandle->ChanObj[count].samplingRate = 0;
327 instHandle->ChanObj[count].chanGain = 0;
328 instHandle->ChanObj[count].devHandle = NULL;
329 }
331 instHandle->hCtrlBus = NULL;
332 instHandle->acCtrlBusHandle = NULL;
334 /* set the state of the driver as created */
335 instHandle->devState = ICodec_DriverState_CREATED;
336 *devp = instHandle;
337 }
338 else
339 {
340 retVal = IOM_EBADIO;
342 if (NULL != devp)
343 {
344 *devp = NULL;
345 }
346 }
348 return (retVal);
349 }
351 /**
352 * \brief Function called by Bios during closing of the instance
353 *
354 * \param devp [IN] Pointer to the driver instance object.
355 *
356 * \return None
357 */
359 Int aic31MdUnBindDev(Ptr devp)
360 {
361 Aic31_Object *instHandle = NULL;
362 int32_t retVal = IOM_COMPLETED;
364 /* Begin parameter checking */
365 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
366 if (NULL == devp)
367 {
368 retVal = IOM_EBADARGS;
369 }
370 else
371 {
372 #endif
373 instHandle = (Aic31_Object *)devp;
374 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
375 if ((NULL == instHandle) ||
376 (AIC31_NUM_INSTANCES <= instHandle->instNum) ||
377 (ICodec_DriverState_CREATED != instHandle->devState) ||
378 (instHandle->ChanObj[0].chanStatus != ICodec_DriverState_CLOSED) ||
379 (instHandle->ChanObj[1].chanStatus != ICodec_DriverState_CLOSED))
380 {
381 retVal = IOM_EBADARGS;
382 }
383 }
384 #endif /* PSP_DISABLE_INPUT_PARAMETER_CHECK */
385 /* End parameter checking */
387 if (IOM_COMPLETED == retVal)
388 {
389 instHandle->devState = ICodec_DriverState_DELETED;
390 Aic31_module.inUse[instHandle->instNum] = FALSE;
391 }
393 return (retVal);
394 }
396 /* ========================================================================== */
397 /* IOM FUNCTIONS */
398 /* ========================================================================== */
400 /**
401 * \brief This function configures the RX or TX portion of the Aic31 codec
402 *
403 * This function internally uses a control bus to configure the codec. The
404 * control bus could be either SPI or I2c etc.The open function configures the
405 * DAC and ADC sections of the codec accordingly
406 *
407 * \param chanp [OUT] pointer to Aic31 driver channel handle
408 * \param devp [IN] pointer to Aic31 driver object
409 * \param name [IN] Aic31 Instance name
410 * \param mode [IN] channel mode -> input or output
411 * \param chanParams [IN] channel parameters from user
412 * \param cbFxn [IN] callback function pointer
413 * \param cbArg [IN] callback function Arguments
414 *
415 * \return Channel handle if successful
416 * NULL in case of error
417 */
418 Int aic31MdCreateChan(Ptr *chanp,
419 Ptr devp,
420 String name,
421 Int mode,
422 Ptr chanParams,
423 IOM_TiomCallback cbFxn,
424 Ptr cbArg)
425 {
426 Aic31_Object *instHandle = NULL;
427 ICodec_ChannelConfig *acChanConfig = NULL;
428 Aic31_Channel_Object *chanHandle = NULL;
429 int32_t result = IOM_COMPLETED;
430 #ifndef SW_I2C
431 String remName = NULL;
432 uint8_t tempData = 0;
433 I2c_ChanParams i2cChanPrms = {0};
434 Bool retVal = (Bool)Aic31_REG_WRITE_FAIL;
435 IOM_Fxns *iomFxns;
436 Ptr devicepointer;
437 #endif /* SW_I2C */
440 /* Begin parameter checking */
441 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
442 if ((NULL == devp) ||
443 (NULL == chanParams) ||
444 ((IOM_INPUT != mode) && (IOM_OUTPUT != mode)))
445 {
446 result = IOM_EBADARGS;
447 }
448 else
449 {
450 #endif
451 instHandle = (Aic31_Object *)devp;
452 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
453 if ((NULL == instHandle) ||
454 (ICodec_DriverState_CREATED != instHandle->devState) ||
455 (ICodec_DriverState_CLOSED != instHandle->ChanObj[mode-1].chanStatus))
456 {
457 result = IOM_EBADARGS;
458 }
459 }
460 #endif /* PSP_DISABLE_INPUT_PARAMETER_CHECK */
461 /* End parameter checking */
463 /* mode is mode-1 because IOM.h defines input=1; output=2 */
464 mode = mode -1;
466 /* validate the input parameters and return in case of error */
467 if (IOM_COMPLETED == result)
468 {
469 #ifdef SW_I2C
471 acChanConfig = (ICodec_ChannelConfig *)chanParams;
473 /* To remove the compiler warning */
474 if ((NULL != cbFxn) && (NULL != cbArg))
475 {
476 cbFxn = cbFxn;
477 cbArg = cbArg;
478 }
480 /* copy the initial parameters to the channel */
481 instHandle->ChanObj[mode].samplingRate = acChanConfig->samplingRate;
482 instHandle->ChanObj[mode].chanGain = acChanConfig->chanGain;
484 /* Configure I2C interface for CODEC */
485 I2CCodecIfInit (instHandle->acBaseAddress, 2, instHandle->acCodecId);
487 /* Configure the Codec for I2S mode */
488 AIC31Reset(instHandle->acBaseAddress);
490 /* Configure the data format and sampling rate */
491 AIC31DataConfig(instHandle->acBaseAddress,
492 instHandle->acSerialDataType,
493 instHandle->acSlotWidth,
494 0);
496 if (instHandle->acDataPath == ICodec_DataPath_TX)
497 {
498 if (ICodec_OpMode_MASTER == instHandle->acOpMode)
499 {
500 AIC31SampleRateConfig(instHandle->acBaseAddress,
501 AIC31_MODE_DAC,
502 acChanConfig->samplingRate);
503 }
505 /* Initialize DAC */
506 AIC31DACInit(instHandle->acBaseAddress);
507 }
508 else if (instHandle->acDataPath == ICodec_DataPath_RX)
509 {
510 if (ICodec_OpMode_MASTER == instHandle->acOpMode)
511 {
512 AIC31SampleRateConfig(instHandle->acBaseAddress,
513 AIC31_MODE_ADC,
514 acChanConfig->samplingRate);
515 }
517 /* Initialize ADC */
518 AIC31ADCInit(instHandle->acBaseAddress);
519 }
520 else
521 {
522 if (ICodec_OpMode_MASTER == instHandle->acOpMode)
523 {
524 AIC31SampleRateConfig(instHandle->acBaseAddress,
525 AIC31_MODE_BOTH,
526 acChanConfig->samplingRate);
527 }
529 /* Do the default configuration for ADC section */
530 AIC31ADCInit(instHandle->acBaseAddress);
531 /* Do the default initialization for DAC section */
532 AIC31DACInit(instHandle->acBaseAddress);
533 }
534 #else
535 acChanConfig = (ICodec_ChannelConfig *)chanParams;
537 /* To remove the compiler warning */
538 if ((NULL != cbFxn) && (NULL != cbArg))
539 {
540 cbFxn = cbFxn;
541 cbArg = cbArg;
542 }
544 /* copy the initial parameters to the channel */
545 instHandle->ChanObj[mode].samplingRate = acChanConfig->samplingRate;
546 instHandle->ChanObj[mode].chanGain = acChanConfig->chanGain;
548 /* If either of the Tx or Rx channel is already open, then in this*
549 * function call, there is no need to do any configuration. */
550 if ((instHandle->ChanObj[0].chanStatus == ICodec_DriverState_CLOSED)
551 &&(instHandle->ChanObj[1].chanStatus == ICodec_DriverState_CLOSED))
552 {
554 Semaphore_construct(&(instHandle->semObj), 0, NULL);
556 /* These variables are not used as no callback is required by *
557 * the codec since it does not support the submit call.hence *
558 * to remove the warning by compiler of unused variables we *
559 * do a dummy assign */
560 if (NULL != name)
561 {
562 name = name;
563 }
565 /* we have to open the control bus to the codec so that we can*
566 * use the handle and configure the codec */
567 remName = DEV_match(
568 instHandle->acCtrlBusName,
569 &instHandle->acCtrlBusHandle);
571 if ((NULL == instHandle->acCtrlBusHandle) ||
572 (NULL == remName))
573 {
574 result = IOM_EBADARGS;
575 }
576 else
577 {
578 iomFxns = DEV_getFxns(instHandle->acCtrlBusHandle);
579 devicepointer = DEV_getDevp(instHandle->acCtrlBusHandle);
581 if (ICodec_ControlBusType_I2C == instHandle->acControlBusType)
582 {
583 i2cChanPrms.hEdma = NULL;
584 i2cChanPrms.masterOrSlave = I2c_CommMode_MASTER;
586 /* driver handle obtained from the name of the device */
587 result = ((IOM_Fxns*)iomFxns)-> \
588 mdCreateChan(
589 &instHandle->hCtrlBus,
590 devicepointer,
591 remName,
592 IOM_INOUT,
593 &i2cChanPrms,
594 &aic31CallBack,
595 (Ptr)(&instHandle->semObj));
596 }
597 else
598 {
599 result = IOM_EBADMODE;
600 }
602 if (NULL == instHandle->hCtrlBus)
603 {
604 result = IOM_EBADARGS;
605 }
607 }
609 /* if the control bus was opened sucesfully then we will *
610 * start the configuration of the codec */
611 if (IOM_COMPLETED == result)
612 {
613 /* Select Register Page 0 of Aic31 */
614 retVal = aic31RegWrite(
615 instHandle,
616 Aic31_PAGE_SELECT_ADDR,
617 Aic31_PAGE_0);
619 /* Reset the Aic31 */
620 retVal |= aic31RegWrite(
621 instHandle,
622 Aic31_P0_REG1,
623 (uint8_t)0x80);
625 /* If Aic31 is master mode then set the direction of *
626 * the bit clock and word clock as output */
627 if (ICodec_OpMode_MASTER == instHandle->acOpMode)
628 {
629 retVal |= aic31RegWriteBf(
630 instHandle,
631 Aic31_SERIAL_INTERFACEA_ADDR,
632 (uint8_t)6,
633 (uint8_t)2,
634 (uint8_t)3);
635 }
637 /* Configure the audio serial data interface mode */
638 switch (instHandle->acSerialDataType)
639 {
640 case ICodec_DataType_I2S: tempData = (0u << 6u); break;
641 case ICodec_DataType_DSP: tempData = (1u << 6u); break;
642 case ICodec_DataType_RIGHTJ: tempData = (2u << 6u); break;
643 case ICodec_DataType_LEFTJ: tempData = (3u << 6u); break;
644 default: tempData = (0u << 6u); break;
645 }
647 /* configure the slot width */
648 switch (instHandle->acSlotWidth)
649 {
650 case ICodec_SlotWidth_16: tempData |= (0u << 4u); break;
651 case ICodec_SlotWidth_20: tempData |= (1u << 4u); break;
652 case ICodec_SlotWidth_24: tempData |= (2u << 4u); break;
653 case ICodec_SlotWidth_32: tempData |= (3u << 4u); break;
654 default: tempData |= (0x00 << 4); break;
655 }
657 retVal |= aic31RegWrite(
658 instHandle,
659 Aic31_SERIAL_INTERFACEB_ADDR,
660 tempData);
662 if (Aic31_REG_WRITE_FAIL == retVal)
663 {
664 result = IOM_EBADARGS;
665 }
666 }
667 }
669 if (IOM_COMPLETED == result)
670 {
671 /* Configure the sampling rate of the audio codec */
672 result = aic31SetSamplingRate(
673 instHandle,
674 (ICodec_Channel)(mode),
675 acChanConfig->samplingRate);
677 /* Complete the default initialization for Tx and RX channels */
678 if (IOM_COMPLETED == result)
679 {
680 if (ICodec_Channel_INPUT == mode)
681 {
682 /* Do the default configuration for ADC section */
683 result = aic31InitAdc(instHandle);
684 }
685 else
686 {
687 /* Do the default initialization for DAC section */
688 result = aic31InitDac(instHandle);
689 }
690 }
691 }
692 #endif /* SW_I2C */
693 }
695 /* Return the result of opening the audio codec */
696 if (IOM_COMPLETED == result )
697 {
698 /* The channel creation is successful hence update the handle */
699 instHandle->ChanObj[mode].chanStatus = ICodec_DriverState_OPENED;
700 instHandle->ChanObj[mode].channelMode = (ICodec_Channel)(mode);
701 instHandle->ChanObj[mode].devHandle = instHandle;
703 chanHandle = &instHandle->ChanObj[mode];
704 *chanp = chanHandle;
705 }
706 else
707 {
708 chanHandle = NULL;
709 *chanp = NULL;
710 }
712 /* Return the channel handle */
713 return (result);
714 }
717 /**
718 * This function executes a control command specified by the application. The
719 * channel handle obtained after the channel open call should be passed as the
720 * parameter.
721 *
722 * \param instHandle [IN] Pointer to the Aic31 driver instance object
723 * \param chanp [IN] Handle to the channel
724 * \param cmd [IN] command to be executed
725 * \param cmdArgs [IN] Arguments for the command(if required)
726 * \param eb [OUT] error block
727 *
728 * \return None
729 */
730 Int aic31MdControlChan(Ptr chanp, Uns cmd, Ptr cmdArgs)
731 {
732 Aic31_Object *instHandle = NULL;
733 Aic31_Channel_Object *chanHandle = NULL;
734 ICodec_RegData *wRegPtr = NULL;
735 Int status = IOM_COMPLETED;
736 uint32_t tempVal = 0;
737 ICodec_CodecData *codecData = NULL;
738 Bool retVal = Aic31_REG_WRITE_FAIL;
740 /* Begin parameter checking */
741 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
742 if (NULL == chanp)
743 {
744 status = IOM_EBADARGS;
745 }
746 else
747 {
748 #endif /* PSP_DISABLE_INPUT_PARAMETER_CHECK */
749 chanHandle = (Aic31_Channel_Object*)chanp;
750 instHandle = (Aic31_Object *)chanHandle->devHandle;
751 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
752 if (NULL == instHandle)
753 {
754 status = IOM_EBADARGS;
755 }
756 }
757 #endif /* PSP_DISABLE_INPUT_PARAMETER_CHECK */
758 /* End parameter checking */
760 if (IOM_COMPLETED == status)
761 {
762 /* Interpret the control command and execute the comnand */
763 if (Aic31_AC_IOCTL_MUTE_ON == cmd)
764 {
765 status = aic31MuteConfig(instHandle,chanHandle->channelMode,TRUE);
766 }
768 else if (Aic31_AC_IOCTL_MUTE_OFF == cmd)
769 {
770 status = aic31MuteConfig(instHandle,chanHandle->channelMode,FALSE);
771 }
773 else if (Aic31_AC_IOCTL_SET_VOLUME == cmd)
774 {
775 if (NULL != cmdArgs)
776 {
777 if (ICodec_Channel_OUTPUT == chanHandle->channelMode)
778 {
779 /* calculate the actual values to be set depending on the *
780 * percentage of the values requested */
781 tempVal =
782 ((*(uint32_t*)cmdArgs) * Aic31_MAX_DAC_GAIN_VALUE)/100u;
784 tempVal = Aic31_MAX_DAC_GAIN_VALUE - tempVal;
786 retVal = aic31RegWriteBf(
787 instHandle,
788 Aic31_P0_REG43,
789 (uint8_t)0,
790 (uint8_t)7,
791 (uint8_t)tempVal);
793 retVal |= aic31RegWriteBf(
794 instHandle,
795 Aic31_P0_REG44,
796 (uint8_t)0,
797 (uint8_t)7,
798 (uint8_t)tempVal);
799 }
800 else if (ICodec_Channel_INPUT == chanHandle->channelMode)
801 {
802 /* calculate the actual values to be set depending on the *
803 * percentage of the values requested */
804 tempVal =
805 ((*(uint32_t*)cmdArgs) * Aic31_MAX_AGC_GAIN_VALUE)/100u;
807 /* modify the ADC volume */
808 retVal = aic31RegWriteBf(
809 instHandle,
810 Aic31_P0_REG27,
811 (uint8_t)1,
812 (uint8_t)7,
813 (uint8_t)tempVal);
815 retVal |= aic31RegWriteBf(
816 instHandle,
817 Aic31_P0_REG30,
818 (uint8_t)1,
819 (uint8_t)7,
820 (uint8_t)tempVal);
821 }
822 else
823 {
824 status = IOM_EBADARGS;
825 }
827 if (Aic31_REG_WRITE_PASS != retVal)
828 {
829 status = IOM_EBADARGS;
830 }
831 }
832 else
833 {
834 status = IOM_EBADARGS;
835 }
836 }
837 else if (Aic31_AC_IOCTL_SET_LOOPBACK == cmd)
838 {
839 /* Loopback not supported in Aic31 */
840 status = IOM_ENOTIMPL;
841 }
843 else if (Aic31_AC_IOCTL_SET_SAMPLERATE == cmd)
844 {
845 /* set the sample rate for the codec */
846 if (NULL != cmdArgs)
847 {
848 status = aic31SetSamplingRate(
849 instHandle,chanHandle->channelMode,
850 *(uint32_t *)cmdArgs);
851 }
852 else
853 {
854 status = IOM_EBADARGS;
855 }
856 }
858 else if (Aic31_AC_IOCTL_REG_WRITE == cmd)
859 {
860 /* cmdArgs should be pointer to type ICodec_RegData */
861 if (NULL != cmdArgs)
862 {
863 /* Write a single Aic31 registe */
864 wRegPtr = (ICodec_RegData*)cmdArgs;
865 retVal = aic31RegWrite(
866 instHandle,
867 (uint8_t)wRegPtr->regIndex,
868 *(uint8_t*)(wRegPtr->regData));
869 }
870 else
871 {
872 status = IOM_EBADARGS;
873 }
875 if (Aic31_REG_WRITE_PASS != retVal)
876 {
877 status = IOM_EBADARGS;
878 }
879 }
881 else if (Aic31_AC_IOCTL_REG_WRITE_MULTIPLE == cmd)
882 {
883 /* Write multiple Aic31 register. */
884 /* cmdArgs should be pointer to type ICodec_RegData */
885 if (NULL != cmdArgs)
886 {
887 /* Write multiple Aic31 registers */
888 retVal = aic31CtrlBusWrite(
889 instHandle->hCtrlBus,
890 (ICodec_RegData *)cmdArgs);
891 }
892 else
893 {
894 status = IOM_EBADARGS;
895 }
897 if (Aic31_REG_WRITE_PASS != retVal)
898 {
899 status = IOM_EBADARGS;
900 }
901 }
903 else if (Aic31_AC_IOCTL_REG_READ == cmd)
904 {
905 /* cmdArgs should be pointer to type ICodec_RegData */
906 if (NULL != cmdArgs)
907 {
908 /* Write a single Aic31 registe */
909 wRegPtr = (ICodec_RegData*)cmdArgs;
910 retVal = aic31RegRead(
911 instHandle,
912 (uint8_t)wRegPtr->regIndex,
913 (uint8_t*)(wRegPtr->regData));
914 }
915 else
916 {
917 status = IOM_EBADARGS;
918 }
920 if (Aic31_REG_WRITE_PASS != retVal)
921 {
922 status = IOM_EBADARGS;
923 }
924 }
925 else if (Aic31_AC_IOCTL_REG_READ_MULTIPLE == cmd)
926 {
927 /* Read multiple Aic31 register. */
928 /* cmdArgs should be pointer to type ICodec_RegData */
929 if (NULL != cmdArgs)
930 {
931 /* Read multiple Aic31 registers */
932 retVal = aic31CtrlBusRead(
933 instHandle,
934 (ICodec_RegData *)cmdArgs);
935 }
936 else
937 {
938 status = IOM_EBADARGS;
939 }
940 if (Aic31_REG_WRITE_PASS != retVal)
941 {
942 status = IOM_EBADARGS;
943 }
944 }
945 else if (Aic31_AC_IOCTL_SELECT_OUTPUT_SOURCE == cmd)
946 {
947 aic31SelectOutputDest(instHandle,cmdArgs);
948 }
949 else if (Aic31_AC_IOCTL_SELECT_INPUT_SOURCE == cmd)
950 {
951 aic31SelectInputSource(instHandle,cmdArgs);
952 }
953 else if (Aic31_AC_IOCTL_GET_CODEC_INFO == cmd)
954 {
955 /* command is the request for the codec information */
956 if (NULL != cmdArgs)
957 {
958 codecData = (ICodec_CodecData *)cmdArgs;
960 /* update the required information to the provided pointer */
961 codecData->acOpMode = instHandle->acOpMode;
962 }
963 else
964 {
965 status = IOM_EBADARGS;
966 }
967 }
968 else
969 {
970 /* The IOCTL is unrecognised or not implemented */
971 status = IOM_ENOTIMPL;
972 }
973 if (IOM_COMPLETED != status)
974 {
975 status = IOM_EBADARGS;
976 }
977 else
978 {
979 /* DO NOTHING */
980 }
981 }
983 /* return the status of the IOCTL executed */
984 return (status);
985 }
988 /**
989 * \brief This function is not implemented as codec does not perform any read
990 * or write operations
991 *
992 * \param instHandle [IN] Aic31 driver object
993 * \param chanp [IN] handle to the channel
994 * \param packet [IN] driver packet
995 * \param eb [OUT] error block
996 *
997 * \return IOM_ERROR - error as not implemeted.
998 */
999 Int aic31MdSubmitChan(Ptr chanp, IOM_Packet *ioPacket)
1000 {
1001 /* to remove compiler warning */
1002 if (NULL != chanp)
1003 {
1004 chanp = chanp;
1005 }
1007 if (NULL != ioPacket)
1008 {
1009 ioPacket = ioPacket;
1010 }
1012 /* not implemented */
1013 return IOM_EBADIO;
1014 }
1017 /**
1018 * \brief aic31MdDeleteChan
1019 *
1020 * This function closes an specified Audio Codec Channel. The audio codec
1021 * is moved into programming mode and then reset when both the channels
1022 * are closed. It deinitalizes the control bus instance.
1023 *
1024 * \param instHandle [IN] Aic31 driver object
1025 * \param chanp [IN] handle to the channel
1026 * \param eb [OUT] error block
1027 *
1028 * \return None
1029 */
1030 Int aic31MdDeleteChan(Ptr chanp)
1031 {
1032 Aic31_Object *instHandle = NULL;
1033 Aic31_Channel_Object *chanHandle = NULL;
1034 Int retVal = IOM_COMPLETED;
1035 #ifndef SW_I2C
1036 Bool status = Aic31_REG_WRITE_FAIL;
1037 IOM_Fxns *iomFxns;
1038 #endif /* SW_I2C */
1040 /* Begin parameter checking */
1041 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
1042 if (NULL == chanp)
1043 {
1044 retVal = IOM_EBADARGS;
1045 }
1046 else
1047 {
1048 #endif /* PSP_DISABLE_INPUT_PARAMETER_CHECK */
1049 chanHandle = (Aic31_Channel_Object*)chanp;
1050 instHandle = chanHandle->devHandle;
1051 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
1052 if ((NULL == instHandle) ||
1053 (ICodec_DriverState_CLOSED == chanHandle->chanStatus))
1054 {
1055 retVal = IOM_EBADARGS;
1056 }
1057 }
1058 #endif /* PSP_DISABLE_INPUT_PARAMETER_CHECK */
1059 /* End parameter checking */
1061 if (IOM_COMPLETED == retVal)
1062 {
1063 /* Write the reset value of Aic31 channel registers */
1064 if (chanHandle->channelMode == ICodec_Channel_INPUT )
1065 {
1066 /* Reset the ADC registers */
1067 #ifndef SW_I2C
1068 retVal = aic31DeinitAdc(instHandle);
1069 #else
1070 AIC31ADCDeInit (instHandle->acBaseAddress);
1071 #endif /* SW_I2C */
1072 }
1073 else
1074 {
1075 /* Reset the DAC registers */
1076 #ifndef SW_I2C
1077 retVal = aic31DeinitDac(instHandle);
1078 #else
1079 AIC31DACDeInit (instHandle->acBaseAddress);
1080 #endif /* SW_I2C */
1081 }
1082 }
1085 if (IOM_COMPLETED == retVal)
1086 {
1087 /* Set the state of the channel as closed */
1088 chanHandle->chanStatus = ICodec_DriverState_CLOSED;
1090 /* Reset Aic31 only if both the channels are closed. */
1091 if ((ICodec_DriverState_CLOSED == instHandle->ChanObj[0].chanStatus)
1092 && (ICodec_DriverState_CLOSED == instHandle->ChanObj[1].chanStatus))
1093 {
1094 #ifndef SW_I2C
1095 /* Select Register Page 0 of Aic31 */
1096 status = aic31RegWrite(
1097 instHandle,
1098 Aic31_PAGE_SELECT_ADDR,
1099 Aic31_PAGE_0);
1101 /* Reset the Aic31 */
1102 status |= aic31RegWrite(
1103 instHandle,
1104 Aic31_RESET_ADDR,
1105 (uint8_t)0x80);
1107 if (Aic31_REG_WRITE_FAIL == status)
1108 {
1109 retVal = IOM_EBADARGS;
1110 }
1112 iomFxns = DEV_getFxns(instHandle->acCtrlBusHandle);
1113 ((IOM_Fxns*)iomFxns)->mdDeleteChan(
1114 instHandle->hCtrlBus);
1115 #else
1116 /* Configure the Codec for I2S mode */
1117 AIC31Reset(instHandle->acBaseAddress);
1118 #endif /* SW_I2C */
1120 /* The control bus handle is not valid anymore */
1121 instHandle->hCtrlBus = NULL;
1122 }
1123 }
1125 return (retVal);
1126 }
1128 /**
1129 * \brief This function change the gain setting of DAC Aic31 codec
1130 *
1131 * This function internally sets the gain setting of the DAC to adjust or
1132 * changes the volume of AIC31 codec.
1133 *
1134 * \param devp [IN] pointer to Aic31 driver object
1135 * \param volume [IN] Volume change in percentage
1136 *
1137 * \return NULL in case of error
1138 */
1139 Int aic31SetVolume(Ptr devp, uint8_t volume)
1140 {
1141 Aic31_Object *instHandle = NULL;
1142 int32_t result = IOM_COMPLETED;
1144 /* Begin parameter checking */
1145 #ifndef PSP_DISABLE_INPUT_PARAMETER_CHECK
1146 if (NULL == devp)
1147 {
1148 result = IOM_EBADARGS;
1149 }
1150 #endif
1151 instHandle = (Aic31_Object *)devp;
1153 /* Configure the data format and sampling rate */
1154 AIC31DACSetVolume(instHandle->acBaseAddress,
1155 volume);
1156 return result;
1157 }
1159 /* ========================================================================== */
1160 /* Local Interface for Aic31 audio codec driver */
1161 /* ========================================================================== */
1164 /**
1165 * \brief This function sets the sampling rate for the ADC and DAC. The ADC
1166 * sampling rate is configured when called for input channel. The DAC
1167 * sampling rate is configured when called for ouput channel.
1168 *
1169 * \param instHandle [IN] pointer to the aci31 instance handle
1170 * \param acChannel [IN] operational mode of the channel
1171 * \param sampleRate [IN] sample rate to be configured
1172 * \param eb [OUT] Error block
1173 */
1174 static int32_t aic31SetSamplingRate(Aic31_Object *instHandle,
1175 ICodec_Channel acChannel,
1176 uint32_t sampleRate)
1177 {
1178 uint8_t pllPValue = 0;
1179 uint8_t pllRValue = 0;
1180 uint8_t pllJValue = 0;
1181 uint8_t pllDLowValue = 0;
1182 uint8_t pllDHighValue = 0;
1183 uint8_t dualRate = 0x00;
1184 uint8_t sampleRateDiv = 0;
1185 uint8_t fsRef = 0;
1186 int32_t status = IOM_COMPLETED;
1187 Bool retVal = Aic31_REG_WRITE_FAIL;
1189 assert(NULL != instHandle);
1191 if ((ICodec_Channel_INPUT == acChannel) ||
1192 (ICodec_Channel_OUTPUT == acChannel))
1193 {
1195 switch (sampleRate)
1196 {
1197 case 8000:
1198 /* Set sampling rate to 8000Hz */
1199 pllPValue = 4u;
1200 pllRValue = 1u;
1201 pllJValue = 16u;
1202 pllDLowValue = 0u;
1203 pllDHighValue = 0u;
1204 dualRate = 0u;
1205 fsRef = 0u;
1206 sampleRateDiv = 10u;
1207 break;
1209 case 11025:
1210 /* Set sampling rate to 11025Hz */
1211 pllPValue = 2u;
1212 pllRValue = 1u;
1213 pllJValue = 7u;
1214 pllDLowValue = 44u;
1215 pllDHighValue = 54u;
1216 dualRate = 0u;
1217 fsRef = 1u;
1218 sampleRateDiv = 6u;
1219 break;
1221 case 16000:
1222 /* Set sampling rate to 16000Hz */
1223 pllPValue = 4u;
1224 pllRValue = 1u;
1225 pllJValue = 16u;
1226 pllDLowValue = 0u;
1227 pllDHighValue = 0u;
1228 dualRate = 0u;
1229 fsRef = 0u;
1230 sampleRateDiv = 4u;
1231 break;
1233 case 22050:
1234 /* Set sampling rate to 22050Hz */
1235 pllPValue = 2u;
1236 pllRValue = 1u;
1237 pllJValue = 7u;
1238 pllDLowValue = 44u;
1239 pllDHighValue = 54u;
1240 dualRate = 0u;
1241 fsRef = 1u;
1242 sampleRateDiv = 2u;
1243 break;
1245 case 24000:
1246 /* Set sampling rate to 24000Hz */
1247 pllPValue = 4u;
1248 pllRValue = 1u;
1249 pllJValue = 16u;
1250 pllDLowValue = 0u;
1251 pllDHighValue = 0u;
1252 dualRate = 0u;
1253 fsRef = 0u;
1254 sampleRateDiv = 2u;
1255 break;
1257 case 32000:
1258 /* Set sampling rate to 32000Hz */
1259 pllPValue = 4u;
1260 pllRValue = 1u;
1261 pllJValue = 16u;
1262 pllDLowValue = 0u;
1263 pllDHighValue = 0u;
1264 dualRate = 0u;
1265 fsRef = 0u;
1266 sampleRateDiv = 1u;
1267 break;
1269 case 44100:
1270 /* Set sampling rate to 44100Hz */
1271 pllPValue = 2u;
1272 pllRValue = 1u;
1273 pllJValue = 7u;
1274 pllDLowValue = 44u;
1275 pllDHighValue = 54u;
1276 dualRate = 0u;
1277 fsRef = 1u;
1278 sampleRateDiv = 0u;
1279 break;
1281 case 48000:
1282 /* Set sampling rate to 48000Hz */
1283 pllPValue = 4u;
1284 pllRValue = 1u;
1285 pllJValue = 16u;
1286 pllDLowValue = 0u;
1287 pllDHighValue = 0u;
1288 dualRate = 0u;
1289 fsRef = 0u;
1290 sampleRateDiv = 0u;
1291 break;
1293 case 96000:
1294 /* Set sampling rate to 96000Hz */
1295 pllPValue = 4u;
1296 pllRValue = 1u;
1297 pllJValue = 16u;
1298 pllDLowValue = 0u;
1299 pllDHighValue = 0u;
1300 dualRate = 1u;
1301 fsRef = 0u;
1302 sampleRateDiv = 0u;
1303 break;
1304 default:
1305 /* Sampling rate is not supported */
1306 status = IOM_EBADARGS;
1307 break;
1308 }
1310 if (IOM_COMPLETED == status)
1311 {
1312 if (ICodec_Channel_INPUT == acChannel)
1313 {
1314 /* Write the ADC sample rate divisor value in Reg2 */
1315 retVal= aic31RegWriteBf(
1316 instHandle,
1317 Aic31_P0_REG2,
1318 (uint8_t)4,
1319 (uint8_t)4,
1320 sampleRateDiv);
1322 retVal |= aic31RegWriteBf(
1323 instHandle,
1324 Aic31_P0_REG7,
1325 (uint8_t)6,
1326 (uint8_t)1,
1327 dualRate);
1328 }
1329 else
1330 {
1331 /* Write the DAC sample rate divisor value in Reg2 */
1332 retVal = aic31RegWriteBf(
1333 instHandle,Aic31_P0_REG2,
1334 (uint8_t)0,
1335 (uint8_t)4,
1336 sampleRateDiv);
1338 retVal |= aic31RegWriteBf(
1339 instHandle,
1340 Aic31_P0_REG7,
1341 (uint8_t)5,
1342 (uint8_t)1,
1343 dualRate);
1344 }
1346 /* enable the PLL */
1347 retVal |= aic31RegWriteBf(
1348 instHandle,
1349 Aic31_P0_REG3,
1350 (uint8_t)7,
1351 (uint8_t)1,
1352 (uint8_t)1);
1354 /* select the MCLK as the input for the PLL and CLKDIV(N = 16)*/
1355 retVal |= aic31RegWriteBf(
1356 instHandle,
1357 Aic31_P0_REG102,
1358 (uint8_t)4,
1359 (uint8_t)2,
1360 (uint8_t)0x00);
1361 /* select the PLL_IN as codec input */
1362 retVal |= aic31RegWriteBf(
1363 instHandle,
1364 Aic31_P0_REG101,
1365 (uint8_t)0,
1366 (uint8_t)1,
1367 (uint8_t)0x00);
1370 /* selec the GPIO to output the divided PLL_IN clock(test purpose)*/
1371 retVal |= aic31RegWrite(instHandle,
1372 Aic31_P0_REG98,
1373 (uint8_t)0x20);
1375 /* Write to PLL programming register A */
1376 retVal |= aic31RegWriteBf(
1377 instHandle,
1378 Aic31_P0_REG3,
1379 (uint8_t)0,
1380 (uint8_t)3,
1381 pllPValue);
1383 /* Write to PLL programming register B */
1384 retVal |= aic31RegWriteBf(
1385 instHandle,
1386 Aic31_P0_REG4,
1387 (uint8_t)2,
1388 (uint8_t)6,
1389 pllJValue);
1391 /* write the high and low bits of the D value */
1392 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG5,pllDHighValue);
1393 retVal |= aic31RegWrite(
1394 instHandle,
1395 Aic31_P0_REG6,
1396 (uint8_t)(pllDLowValue << 2));
1398 retVal |= aic31RegWriteBf(
1399 instHandle,
1400 Aic31_P0_REG11,
1401 (uint8_t)0,
1402 (uint8_t)4,
1403 pllRValue);
1405 /* Write to codec datapath setup register */
1406 retVal |= aic31RegWriteBf(
1407 instHandle,
1408 Aic31_P0_REG7,
1409 (uint8_t)7,
1410 (uint8_t)1,
1411 fsRef);
1412 }
1413 }
1416 if (Aic31_REG_WRITE_PASS == retVal)
1417 {
1418 status = IOM_COMPLETED;
1419 }
1420 else
1421 {
1422 status = IOM_EBADARGS;
1423 }
1425 /* Return the result of setting the sampling rate */
1426 return (status);
1427 }
1429 /**
1430 * This function perfroms a register write(s) to the audio codec. The control
1431 * bus is selected based on the parameter value selected.
1432 *
1433 * \param instHandle [IN] pointer to the aci31 instance handle
1434 * \param wrRegData [OUT] data to be written to codec
1435 *
1436 * \return Aic31_REG_WRITE_PASS in case of success
1437 * Aic31_REG_WRITE_FAIL in case of error
1438 */
1439 static Bool aic31CtrlBusWrite(Aic31_Object *instHandle,
1440 ICodec_RegData *wrRegData)
1441 {
1442 ICodec_ControlBusType acCtrlBusType;
1443 uint32_t deviceId;
1444 Bool retVal = Aic31_REG_WRITE_FAIL;
1446 assert((NULL != instHandle) && (NULL != wrRegData));
1448 /* Initialize the local variables */
1449 acCtrlBusType = instHandle->acControlBusType;
1450 deviceId = instHandle->acCodecId;
1452 if (ICodec_ControlBusType_I2C == acCtrlBusType)
1453 {
1454 retVal = aic31I2cWrite(instHandle,deviceId,wrRegData);
1455 }
1456 else if (ICodec_ControlBusType_SPI == acCtrlBusType)
1457 {
1458 /* Add SPI call here */
1459 retVal = Aic31_REG_WRITE_FAIL;
1460 }
1461 else
1462 {
1463 retVal = Aic31_REG_WRITE_FAIL;
1464 }
1465 return (retVal);
1466 }
1468 /**
1469 * \brief This function perfroms a register write(s) to the audio codec using
1470 * the I2C control bus.
1471 *
1472 * \param instHandle [IN] pointer to the device instance object
1473 * \param deviceId [IN] slave device address
1474 * \param wrRegData [IN] data to write to slave
1475 *
1476 * \return Aic31_REG_WRITE_PASS in case of success
1477 * Aic31_REG_WRITE_FAIL in case of error
1478 */
1479 static Bool aic31I2cWrite(Aic31_Object *instHandle,
1480 uint32_t deviceId,
1481 ICodec_RegData *wrRegData)
1482 {
1483 uint8_t count; /* Local count variable */
1484 uint32_t regIndex; /* Register indec to be written */
1485 uint8_t *regData; /* Pointer to array of register write data */
1486 #ifndef SW_I2C
1487 uint8_t data[2]; /* Temporary data */
1488 IOM_Packet ioPacket;
1489 I2c_DataParam dataBuffer;
1490 int32_t result = IOM_EBADARGS; /* Result */
1491 IOM_Fxns *iomFxns;
1492 #endif /* SW_I2C */
1493 Bool retVal = Aic31_REG_WRITE_FAIL;
1495 assert((NULL != instHandle) && (NULL != wrRegData));
1497 /* Initialize the local variables */
1498 regIndex = wrRegData->regIndex;
1499 regData = (uint8_t*)wrRegData->regData;
1501 assert(NULL != regData);
1503 /* Write all the registers */
1504 for (count = 0; count < wrRegData->regCount; count++)
1505 {
1506 #ifndef SW_I2C
1507 /* Prepare the data to be written to the audio codec */
1508 data[0] = regIndex;
1509 data[1] = ((*regData) & 0xFF);
1511 dataBuffer.slaveAddr = deviceId;
1512 dataBuffer.buffer = &data[0];
1513 dataBuffer.bufLen = 2u;
1514 dataBuffer.flags = I2c_DEFAULT_WRITE;
1516 memset(&ioPacket,0x00,sizeof(IOM_Packet));
1518 ioPacket.addr = &dataBuffer;
1519 ioPacket.size = 2u;
1520 ioPacket.cmd = (Uns)IOM_WRITE;
1521 ioPacket.status = IOM_COMPLETED;
1523 /* Write the data to Aic31 register */
1524 iomFxns = DEV_getFxns(instHandle->acCtrlBusHandle);
1525 result = ((IOM_Fxns*)iomFxns)-> \
1526 mdSubmitChan(
1527 instHandle->hCtrlBus,
1528 &ioPacket);
1530 if (IOM_PENDING == result)
1531 {
1532 Semaphore_pend(Semaphore_handle(&(instHandle->semObj)), Aic31_I2CTIMEOUT);
1533 }
1535 /* Validate the number of words written to Aic31 codec. */
1536 if ((IOM_COMPLETED == ioPacket.status) ||
1537 (IOM_PENDING == ioPacket.status))
1538 {
1539 retVal = Aic31_REG_WRITE_PASS;
1540 }
1541 else
1542 {
1543 break;
1544 }
1545 #else
1546 CodecRegWrite(instHandle->acBaseAddress, regIndex, ((*regData) & 0xFF));
1547 retVal = Aic31_REG_WRITE_PASS;
1548 #endif /* SW_I2C */
1549 /* Maintain the register data pointer and register index */
1550 regIndex++;
1551 regData++;
1552 }
1554 /* Return the result of writting to Aic31 registers */
1555 return (retVal);
1556 }
1559 /**
1560 * \brief This function writes a value to a single Aic31 register. This
1561 * function is a wrapper for faclitating single register writes in the
1562 * Aic31 codec driver. It internally calls aic31CtrlBusWrite function.
1563 *
1564 * \param instHandle [IN] pointer to the device driver instance object
1565 * \param regAddr [IN] register address
1566 * \param regData [IN] register data to be written
1567 *
1568 * \return FALSE in case of success
1569 * Error code in case of error
1570 */
1571 static Bool aic31RegWrite(Aic31_Object *instHandle,
1572 uint8_t regAddr,
1573 uint8_t regData)
1574 {
1575 ICodec_RegData acRegData; /* Register data structure */
1576 Bool retVal = Aic31_REG_WRITE_FAIL;/* Result of write */
1578 assert(NULL != instHandle);
1580 /* Write the data from the Aic31 register */
1581 acRegData.regCount = 1u;
1582 acRegData.regIndex = regAddr;
1583 acRegData.regData = (Ptr)®Data;
1585 retVal = aic31CtrlBusWrite(instHandle,&acRegData);
1587 /* Return the result of reading the register */
1588 return (retVal);
1589 }
1592 /**
1593 * \brief This function perfroms a register read(s) to the audio codec.
1594 * The control bus is selected based on the parameter value selected.
1595 *
1596 * \param instHandle [IN] pointer to the device driver instance object
1597 * \param rdRegData [OUT] pointer to the register data read structure
1598 *
1599 * \return Aic31_REG_READ_PASS in case of success
1600 * Aic31_REG_READ_FAIL in case of error
1601 */
1602 static Bool aic31CtrlBusRead(Aic31_Object *instHandle,
1603 ICodec_RegData *rdRegData)
1604 {
1605 Bool retVal = Aic31_REG_READ_FAIL;
1606 ICodec_ControlBusType acCtrlBusType;
1607 uint32_t deviceId;
1609 assert(NULL != instHandle);
1611 /* Initialize the local variables */
1612 acCtrlBusType = instHandle->acControlBusType;
1613 deviceId = instHandle->acCodecId;
1615 /* Determine the control bus and invoke the corresponding read function */
1616 if (ICodec_ControlBusType_I2C == acCtrlBusType)
1617 {
1618 /* Control bus is I2C. Read from I2c bus. */
1619 retVal = aic31I2cRead(instHandle,deviceId,rdRegData);
1620 }
1621 else if (ICodec_ControlBusType_SPI == acCtrlBusType)
1622 {
1623 /* Add SPI call here */
1624 retVal = Aic31_REG_READ_FAIL;
1625 }
1626 else
1627 {
1628 retVal = Aic31_REG_READ_FAIL;
1629 }
1630 /* Return the result of reading register data */
1631 return (retVal);
1632 }
1634 /**
1635 * \brief This function perfroms a register reads(s) from the audio codec
1636 * using the I2C control bus. This function first writes the address
1637 * of the register address without issuing a I2C stop. It then issues
1638 * a I2C restart and reads the value of the register.
1639 *
1640 * \param instHandle [IN] pointer to the driver instance object
1641 * \param deviceId [IN] I2c slave device address
1642 * \param rdRegData [OUT] register data read
1643 *
1644 * \return Aic31_REG_READ_PASS in case of success
1645 * Aic31_REG_READ_FAIL in case of error
1646 */
1647 static Bool aic31I2cRead(Aic31_Object *instHandle,
1648 uint32_t deviceId,
1649 ICodec_RegData *rdRegData)
1650 {
1651 uint8_t count; /* Local count variable */
1652 uint32_t regIndex; /* Register index to be written */
1653 uint8_t *regData; /* Pointer to array of register write data */
1654 #ifndef SW_I2C
1655 uint8_t data[10]; /* Temporary data */
1656 I2c_DataParam dataBuffer;
1657 IOM_Packet ioPacket;
1658 int32_t status = IOM_COMPLETED;
1659 IOM_Fxns *iomFxns;
1660 #endif /* SW_I2C */
1661 Bool retVal = Aic31_REG_READ_FAIL;
1663 assert(NULL != rdRegData);
1665 /* Initialize the local variables */
1666 regIndex = rdRegData->regIndex;
1667 regData = (uint8_t*)rdRegData->regData;
1669 assert(NULL != regData);
1671 assert(NULL != instHandle);
1673 /* Read all the registers */
1674 for (count = 0; count < rdRegData->regCount; count++)
1675 {
1676 #ifndef SW_I2C
1677 /* The following the procedure to read data from Aic31 codec
1679 Step A: Write the address of the register to be read.
1680 Note: The I2C stop should not be issued.
1681 Step B: Issue I2C restart.
1682 Step C: Read the value of the register. */
1683 data[0] = regIndex;
1685 /* Prepare the data to be written to the audio codec */
1686 dataBuffer.slaveAddr = deviceId;
1687 dataBuffer.buffer = &data[0];
1688 dataBuffer.bufLen = 1u;
1689 dataBuffer.flags = I2c_WRITE | I2c_MASTER | I2c_START;
1691 memset(&ioPacket,0x00,sizeof(IOM_Packet));
1693 ioPacket.addr = &dataBuffer;
1694 ioPacket.size = 2u;
1695 ioPacket.cmd = (Uns)IOM_WRITE;
1696 ioPacket.status = IOM_COMPLETED;
1699 iomFxns = DEV_getFxns(instHandle->acCtrlBusHandle);
1700 status = ((IOM_Fxns*)iomFxns)->mdSubmitChan(
1701 instHandle->hCtrlBus,
1702 &ioPacket);
1704 if (IOM_PENDING == status)
1705 {
1706 Semaphore_pend(Semaphore_handle(&(instHandle->semObj)), Aic31_I2CTIMEOUT);
1707 }
1709 /* If the write command is complete, read the registers of Aic31 */
1710 if ((IOM_COMPLETED == ioPacket.status )||
1711 (IOM_PENDING == ioPacket.status))
1712 {
1713 ioPacket.cmd = IOM_READ;
1715 dataBuffer.flags = I2c_READ
1716 | I2c_MASTER
1717 | I2c_STOP
1718 | I2c_RESTART;
1720 status = ((IOM_Fxns *)iomFxns)-> \
1721 mdSubmitChan(instHandle->hCtrlBus,&ioPacket);
1722 }
1724 if (IOM_PENDING == status)
1725 {
1726 Semaphore_pend(Semaphore_handle(&(instHandle->semObj)), Aic31_I2CTIMEOUT);
1727 }
1729 /* If read is complete, then copy the required register values*/
1730 if ((IOM_COMPLETED == ioPacket.status )||
1731 (IOM_PENDING == ioPacket.status))
1732 {
1733 *regData = data[0];
1734 regData++;
1735 regIndex++;
1736 retVal= Aic31_REG_READ_PASS;
1737 }
1738 else
1739 {
1740 break;
1741 }
1742 #else
1743 CodecRegRead(instHandle->acBaseAddress, regIndex);
1744 retVal= Aic31_REG_READ_PASS;
1745 #endif /* SW_I2C */
1746 }
1748 /* Return the result of reading the Aic31 registers */
1749 return (retVal);
1750 }
1752 /**
1753 * This function reads the value of a single Aic31 register. This function
1754 * is a wrapper for faclitating single register reads in the Aic31 codec
1755 * driver. It internally calls aic31CtrlBusRead function.
1756 *
1757 * \param instHandle [IN] pointer to the driver instance object
1758 * \param regAddr [IN] register address
1759 * \param regData [OUT] register data read
1760 *
1761 * \return Aic31_REG_READ_PASS in case of success
1762 * Aic31_REG_READ_FAIL in case of error
1763 */
1764 static Bool aic31RegRead(Aic31_Object *instHandle,
1765 uint8_t regAddr,
1766 uint8_t *regData)
1767 {
1768 ICodec_RegData acRegData; /* Register data structure */
1769 Bool retVal = IOM_COMPLETED; /* Result of read */
1771 assert((NULL != instHandle) && (NULL != regData));
1773 /* Read the data from the Aic31 register */
1774 acRegData.regCount = 1u;
1775 acRegData.regIndex = regAddr;
1776 acRegData.regData = (Ptr)regData;
1778 retVal = aic31CtrlBusRead(instHandle, &acRegData);
1780 /* Return the result of reading the register */
1781 return (retVal);
1782 }
1785 /**
1786 * \brief This function writes data into a bit field of Aic31 register. This
1787 * function reads the value of the register, modifies the value of the
1788 * specified register and writes the value back to the register.
1789 *
1790 * \param instHandle [IN] pointer to the driver instance object
1791 * \param regAddr [IN] register address
1792 * \param bfPosition [IN] bit field position
1793 * \param bfSize [IN] bit field size
1794 * \param bfData [IN] data to be written to the bit field
1795 *
1796 * \return Aic31_REG_WRITE_PASS in case of success
1797 * Aic31_REG_WRITE_FAIL in case of error
1799 */
1800 static Bool aic31RegWriteBf(Aic31_Object *instHandle,
1801 uint8_t regAddr,
1802 uint8_t bfPosition,
1803 uint8_t bfSize,
1804 uint8_t bfData)
1805 {
1806 uint8_t regData = 0; /* Temporary Register data */
1807 uint8_t mask = 0; /* Bit field mask */
1808 Bool bFalseWhile = TRUE;
1809 Bool retVal = Aic31_REG_WRITE_FAIL;
1811 assert(NULL != instHandle);
1813 do
1814 {
1815 bFalseWhile = FALSE;
1817 /* Read the current value of the register */
1818 retVal = aic31RegRead( instHandle , regAddr , ®Data );
1820 if (Aic31_REG_WRITE_PASS != retVal)
1821 {
1822 break;
1823 }
1825 /* Update the value of the bit field */
1826 mask = ((1 << bfSize) - 1) << bfPosition;
1827 regData = (regData & (uint8_t)(~(mask)));
1828 regData = (regData | (uint8_t)( bfData << bfPosition));
1830 /* Write the data back into the register */
1831 retVal= aic31RegWrite(instHandle,regAddr,regData);
1833 }while (bFalseWhile);
1835 /* Return the result of writing data into the bit field */
1836 return (retVal);
1837 }
1839 #ifndef SW_I2C
1841 /**
1842 * \brief This function writes the initialization values for Aic31 ADC
1843 * registers. This function should be called to initialize the registers
1844 * of the ADC.
1845 *
1846 * \param instHandle [IN] Pointer to the driver instance object
1847 *
1848 * \return IOM_COMPLETED
1849 */
1850 static int32_t aic31InitAdc(Aic31_Object *instHandle)
1851 {
1852 int32_t status = IOM_EBADARGS;
1853 Bool retVal = Aic31_REG_WRITE_FAIL;
1854 uint8_t gain = 0;
1856 assert(NULL != instHandle);
1858 /* Write the initialization values for the ADC registers */
1859 retVal = aic31RegWriteBf(
1860 instHandle,
1861 Aic31_P0_REG7,
1862 (uint8_t)1,
1863 (uint8_t)4,
1864 (uint8_t)5);
1866 /* enable the programmable PGA for left and right ADC */
1867 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG15, (uint8_t)0x00);
1868 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG16, (uint8_t)0x00);
1870 /* MIC3L/R is not connected to the left ADC PGA */
1871 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG17,(uint8_t)0xFF);
1873 /* MIC3L/R is not connected to the right ADC PGA */
1874 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG18,(uint8_t)0xFF);
1876 /* power on the Line L1R */
1877 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG19,(uint8_t)0x04);
1879 /* REG20 (not required) */
1880 /* REG21 (not required) */
1882 /* power on the Line LIL */
1883 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG22,(uint8_t)0x04);
1885 /* check if the user requested gain in less than 100 % */
1886 if (instHandle ->ChanObj[0].chanGain <= Aic31_MAX_GAIN_PERCENT)
1887 {
1888 gain = (uint8_t)((instHandle ->ChanObj[0].chanGain *
1889 Aic31_MAX_PGA_GAIN_VALUE)/ Aic31_MAX_GAIN_PERCENT);
1891 /* Left AGC control */
1892 retVal |= aic31RegWrite(
1893 instHandle,
1894 Aic31_LEFT_AGC_CTRLA_ADDR,
1895 (uint8_t)0x80);
1896 retVal |= aic31RegWrite(
1897 instHandle,
1898 Aic31_LEFT_AGC_CTRLB_ADDR,
1899 (uint8_t)(gain << 1));
1900 retVal |= aic31RegWrite(
1901 instHandle,
1902 Aic31_LEFT_AGC_CTRLC_ADDR,
1903 (uint8_t)0x00);
1905 /* Right AGC control */
1906 retVal |= aic31RegWrite(
1907 instHandle,
1908 Aic31_RIGHT_AGC_CTRLA_ADDR,
1909 (uint8_t)0x80);
1910 retVal |= aic31RegWrite(
1911 instHandle,
1912 Aic31_RIGHT_AGC_CTRLB_ADDR,
1913 (uint8_t)(gain << 1));
1914 retVal |= aic31RegWrite(
1915 instHandle,
1916 Aic31_RIGHT_AGC_CTRLC_ADDR,
1917 (uint8_t)0x00);
1918 }
1919 else
1920 {
1921 status = IOM_EBADARGS;
1922 }
1924 if (Aic31_REG_WRITE_PASS == retVal)
1925 {
1926 status = IOM_COMPLETED;
1927 }
1929 return (status);
1930 }
1932 /**
1933 *
1934 * \brief This function writes the initialization values for Aic31 DAC
1935 * registers. This function should be called to initialize the
1936 * registers of the DAC.
1937 *
1938 * \param instHandle [IN] Pointer to the driver instance object
1939 *
1940 * \return IOM_COMPLETED
1941 */
1942 static int32_t aic31InitDac(Aic31_Object *instHandle)
1943 {
1944 int32_t status = IOM_EBADARGS;
1945 Bool retVal = Aic31_REG_WRITE_FAIL;
1946 uint8_t gain = 0;
1948 assert(NULL != instHandle);
1950 /* Write the initialization values for the DAC registers */
1951 retVal = aic31RegWriteBf(
1952 instHandle,
1953 Aic31_P0_REG7,
1954 (uint8_t)1,
1955 (uint8_t)4,
1956 (uint8_t)5);
1958 /* power up the left and right DACs */
1959 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG37, (uint8_t)0xE0);
1961 /* select the DAC L1 R1 Paths */
1962 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG41, (uint8_t)0x02);
1964 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG42, (uint8_t)0x6C);
1966 /* unmute the DAC */
1967 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG43, (uint8_t)0x00);
1968 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG44, (uint8_t)0x00);
1970 /* DAC L to HPL OUT Is connected */
1971 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG47, (uint8_t)0x80);
1972 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG51, (uint8_t)0x09);
1974 /* DAC R to HPROUT is connected */
1975 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG64, (uint8_t)0x80);
1976 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG65, (uint8_t)0x09);
1978 /* DACL1 connected to LINE1 LOUT */
1979 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG82, (uint8_t)0x80);
1980 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG86, (uint8_t)0x09);
1982 /* DACR1 connected to LINE1 ROUT */
1983 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG92, (uint8_t)0x80);
1984 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG93, (uint8_t)0x09);
1986 /* check if the user requested gain in less than 100 % */
1987 if (instHandle ->ChanObj[1].chanGain <= Aic31_MAX_GAIN_PERCENT)
1988 {
1989 gain = (uint8_t)((instHandle->ChanObj[1].chanGain *
1990 Aic31_MAX_PGA_GAIN_VALUE) / Aic31_MAX_GAIN_PERCENT);
1992 gain = Aic31_MAX_PGA_GAIN_VALUE - gain;
1994 /* Left/Right DAC digital volume gain */
1995 retVal |= aic31RegWrite(instHandle,Aic31_LEFT_DAC_VOL_CTRL_ADDR, gain);
1996 retVal |= aic31RegWrite(instHandle,Aic31_RIGHT_DAC_VOL_CTRL_ADDR, gain);
1997 }
1998 else
1999 {
2000 status = IOM_EBADARGS;
2001 }
2003 if (Aic31_REG_WRITE_PASS == retVal)
2004 {
2005 status = IOM_COMPLETED;
2006 }
2008 return (status);
2009 }
2011 /**
2012 * \brief This function writes the reset values for Aic31 ADC registers.
2013 * This function should be called to reset the registers of the ADC.
2014 * It is recommended to write reset values explicitly.
2015 *
2016 * \param instHandle [IN] Pointer to the driver instance object
2017 *
2018 * \return IOM_COMPLETED
2019 */
2020 static int32_t aic31DeinitAdc(Aic31_Object *instHandle)
2021 {
2022 int32_t status = IOM_EBADARGS;
2023 Bool retVal = Aic31_REG_WRITE_FAIL;
2025 assert(NULL != instHandle);
2027 /* Write the reset values to ADC registers */
2028 retVal = aic31RegWrite(instHandle, Aic31_P0_REG15, (uint8_t)0x00);
2029 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG16, (uint8_t)0x00);
2030 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG17, (uint8_t)0xFF);
2031 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG18, (uint8_t)0xFF);
2032 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG19, (uint8_t)0x78);
2033 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG22, (uint8_t)0x78);
2034 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG26, (uint8_t)0x00);
2035 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG27, (uint8_t)0xFE);
2036 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG28, (uint8_t)0x00);
2037 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG29, (uint8_t)0x00);
2038 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG30, (uint8_t)0xFE);
2039 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG31, (uint8_t)0x00);
2041 if (Aic31_REG_WRITE_PASS == retVal)
2042 {
2043 status = IOM_COMPLETED;
2044 }
2046 return (status);
2047 }
2049 /**
2050 * \brief This function writes the reset values for Aic31 DAC registers.
2051 * This function should be called to reset the registers of the DAC.
2052 * It is recommended to write reset values explicitly.
2053 *
2054 * \param instHandle [IN] Pointer to the driver instance object
2055 *
2056 * \return IOM_COMPLETED
2057 */
2058 static int32_t aic31DeinitDac(Aic31_Object *instHandle)
2059 {
2060 int32_t status = IOM_EBADARGS;
2061 Bool retVal = Aic31_REG_WRITE_FAIL;
2063 assert(NULL != instHandle);
2065 /* Write the reset values to DAC registers */
2066 retVal = aic31RegWriteBf(
2067 instHandle,
2068 Aic31_P0_REG7,
2069 (uint8_t)1,
2070 (uint8_t)4,
2071 (uint8_t)0);
2072 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG37, (uint8_t)0x00);
2073 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG38, (uint8_t)0x00);
2074 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG41, (uint8_t)0x00);
2075 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG42, (uint8_t)0x00);
2076 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG43, (uint8_t)0x80);
2077 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG44, (uint8_t)0x80);
2078 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG51, (uint8_t)0x04);
2079 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG64, (uint8_t)0x00);
2080 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG65, (uint8_t)0x04);
2081 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG82, (uint8_t)0x00);
2082 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG86, (uint8_t)0x00);
2083 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG92, (uint8_t)0x00);
2084 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG93, (uint8_t)0x00);
2086 if (Aic31_REG_WRITE_PASS == retVal)
2087 {
2088 status = IOM_COMPLETED;
2089 }
2091 return (status);
2092 }
2094 #endif /* SW_I2C */
2096 /**
2097 *
2098 * \brief This function configures the mute for ADC and DAC. The mute
2099 * functionality can be enabled or disabled for input (ADC) or output
2100 * (DAC) channels.
2101 *
2102 * \param instHandle [IN] pointer to the driver instance object
2103 * \param acChannel [IN] channel type input or output
2104 * \param muteconfig [IN] mute configuration value TRUE or FALSE
2105 *
2106 * \return IOM_COMPLETED if success
2107 * IOM_EBADARGS in case of error
2108 */
2109 static int32_t aic31MuteConfig(Aic31_Object *instHandle,
2110 ICodec_Channel acChannel,
2111 Bool muteConfig)
2112 {
2113 /* Intialize the local variables */
2114 int32_t status = IOM_COMPLETED;
2115 Bool notMuteConfig = FALSE;
2116 Bool retVal = Aic31_REG_WRITE_FAIL;
2118 assert(NULL != instHandle);
2120 if (ICodec_Channel_INPUT == acChannel)
2121 {
2122 if (TRUE == muteConfig)
2123 {
2124 notMuteConfig = FALSE;
2125 }
2126 else
2127 {
2128 notMuteConfig = TRUE;
2129 }
2131 /* Mute the left and right input channels */
2132 retVal = aic31RegWriteBf(
2133 instHandle,
2134 Aic31_P0_REG26,
2135 (uint8_t)7,
2136 (uint8_t)1,
2137 (uint8_t)(notMuteConfig));
2138 retVal |= aic31RegWriteBf(
2139 instHandle,
2140 Aic31_P0_REG15,
2141 (uint8_t)7,
2142 (uint8_t)1,
2143 (uint8_t)muteConfig);
2144 retVal |= aic31RegWriteBf(
2145 instHandle,
2146 Aic31_P0_REG29,
2147 (uint8_t)7,
2148 (uint8_t)1,
2149 (uint8_t)(notMuteConfig));
2150 retVal |= aic31RegWriteBf(
2151 instHandle,
2152 Aic31_P0_REG16,
2153 (uint8_t)7,
2154 (uint8_t)1,
2155 (uint8_t)muteConfig);
2156 }
2157 else if (ICodec_Channel_OUTPUT == acChannel)
2158 {
2159 /* Mute the left and right output channels */
2160 retVal = aic31RegWriteBf(
2161 instHandle,
2162 Aic31_P0_REG43,
2163 (uint8_t)7,
2164 (uint8_t)1,
2165 (uint8_t)muteConfig);
2166 retVal |= aic31RegWriteBf(
2167 instHandle,
2168 Aic31_P0_REG44,
2169 (uint8_t)7,
2170 (uint8_t)1,
2171 (uint8_t)muteConfig);
2172 }
2173 else
2174 {
2175 /* Invalid parameter */
2176 status = IOM_EBADARGS;
2177 }
2179 if (Aic31_REG_WRITE_PASS == retVal)
2180 {
2181 status = IOM_COMPLETED;
2182 }
2184 /* Return the result of the mute operation */
2185 return (status);
2186 }
2188 #ifndef SW_I2C
2190 /**
2192 *
2193 * \brief This function is the codec call back function invoked from the I2c
2194 * driver on transfer completion.
2195 *
2196 * \param semHandle [IN] pointer to the Semaphore Handle
2197 * \param ioPacket [IN] pointer to the completed ioPacket
2198 *
2199 * \return none
2200 *
2201 */
2202 static Void aic31CallBack (Ptr semHandle, IOM_Packet * ioPacket)
2203 {
2204 assert((NULL != semHandle) && (NULL != ioPacket));
2206 if (NULL != ioPacket)
2207 {
2208 ioPacket = ioPacket;
2209 }
2211 Semaphore_post(Semaphore_handle(semHandle));
2212 return;
2213 }
2215 #endif /* #ifndef SW_I2C */
2217 /**
2218 *
2219 * \brief This function selects the output source of the audio data among the
2220 * line out,hp out or both options
2221 *
2222 * \param instHandle [IN] pointer to the driver object
2223 * \param destOption [IN] pointer to Enum specifying the output destination
2224 *
2225 * \return IOM_COMPLETED in case of success.
2226 * IOM_EBADARGS in case of error.
2227 */
2228 static int32_t aic31SelectOutputDest(Aic31_Object *instHandle,
2229 Ptr destOption)
2230 {
2231 Int *dest = 0;
2232 int32_t status = IOM_EBADARGS;
2233 Bool retVal = Aic31_REG_WRITE_FAIL;
2235 assert((NULL != instHandle) && (NULL != destOption));
2237 dest = (Int *)destOption;
2239 switch (*dest)
2240 {
2241 case ICodec_OutputDest_LINEOUT:
2242 /* disconnect the HPOUT and conect the lINE OUT */
2244 /* disconnect and power down the HPOUT L */
2245 retVal = aic31RegWrite(instHandle, Aic31_P0_REG47, (uint8_t)0x00);
2246 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG51, (uint8_t)0x06);
2248 /* disconnect and powerdown HPOUT R */
2249 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG64, (uint8_t)0x00);
2250 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG65, (uint8_t)0x06);
2252 /* DACL1 connected to LINE1 LOUT */
2253 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG82, (uint8_t)0x80);
2254 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG86, (uint8_t)0x09);
2256 /* DACR1 connected to LINE1 ROUT */
2257 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG92, (uint8_t)0x80);
2258 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG93, (uint8_t)0x09);
2259 break;
2261 case ICodec_OutputDest_HPOUT:
2262 /* DACL1 disconnected from LINE1 LOUT */
2263 retVal = aic31RegWrite(instHandle, Aic31_P0_REG82, (uint8_t)0x00);
2264 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG86, (uint8_t)0x06);
2266 /* DACR1 disconnected from LINE1 ROUT */
2267 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG92, (uint8_t)0x00);
2268 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG93, (uint8_t)0x06);
2270 /* DAC L to HPL OUT Is connected */
2271 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG47, (uint8_t)0x80);
2272 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG51, (uint8_t)0x09);
2274 /* DAC R to HPROUT is connected */
2275 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG64, (uint8_t)0x80);
2276 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG65, (uint8_t)0x09);
2277 break;
2278 case ICodec_OutputDest_BOTH:
2279 /* DAC L to HPL OUT Is connected */
2280 retVal = aic31RegWrite(instHandle, Aic31_P0_REG47, (uint8_t)0x80);
2281 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG51, (uint8_t)0x09);
2283 /* DAC R to HPROUT is connected */
2284 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG64, (uint8_t)0x80);
2285 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG65, (uint8_t)0x09);
2287 /* DACL1 connected to LINE1 LOUT */
2288 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG82, (uint8_t)0x80);
2289 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG86, (uint8_t)0x09);
2291 /* DACR1 connected to LINE1 ROUT */
2292 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG92, (uint8_t)0x80);
2293 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG93, (uint8_t)0x09);
2294 break;
2295 default:
2296 status = IOM_EBADARGS;
2297 break;
2298 }
2300 if (Aic31_REG_WRITE_PASS == retVal)
2301 {
2302 status = IOM_COMPLETED;
2303 }
2305 return (status);
2306 }
2308 /**
2309 *
2310 * \brief This function selects the input source of the audio data among the
2311 * available sources of Mic in and line in
2312 *
2313 * \param instHandle [IN] pointer to the driver object
2314 * \param srcOption [IN] Enum specifying the output destination
2315 *
2316 * \return IOM_COMPLETED in case of success.
2317 * IOM_EBADARGS in case of error.(write failed)
2318 *
2319 */
2320 static int32_t aic31SelectInputSource(Aic31_Object *instHandle,
2321 Ptr srcOption)
2322 {
2323 Int *src = 0;
2324 Bool retVal = Aic31_REG_WRITE_FAIL;
2325 int32_t status = IOM_EBADARGS;
2327 assert((NULL != instHandle) && (NULL != srcOption));
2329 src = (Int *)srcOption;
2331 if (ICodec_InputDest_MICIN == (*src))
2332 {
2333 /* disable the LINE IN connected to the ADC */
2334 retVal = aic31RegWrite(instHandle, Aic31_P0_REG19, (uint8_t)0x7C);
2335 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG22, (uint8_t)0x7C);
2337 /* connect the MIC IN to the ADC */
2338 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG17, (uint8_t)0x0F);
2339 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG18, (uint8_t)0xF0);
2340 }
2341 else if (ICodec_InputDest_LINEIN == (*src))
2342 {
2343 /* disable the MIC IN connected to the ADC */
2344 retVal = aic31RegWrite(instHandle, Aic31_P0_REG17, (uint8_t)0xFF);
2345 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG18, (uint8_t)0xFF);
2347 /* connect the LINE IN to the ADC */
2348 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG19, (uint8_t)0x04);
2349 retVal |= aic31RegWrite(instHandle, Aic31_P0_REG22, (uint8_t)0x04);
2350 }
2351 else
2352 {
2353 /* Invalid parameter */
2354 status = IOM_EBADARGS;
2355 }
2357 /* if all the reg writes have passed we will send the status as completed */
2358 if (Aic31_REG_WRITE_PASS == retVal)
2359 {
2360 status = IOM_COMPLETED;
2361 }
2363 return (status);
2364 }
2365 /* ========================================================================== */
2366 /* END OF FILE */
2367 /* ========================================================================== */