/*This file is prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
 *
 * \brief TLV320AIC23B stereo audio CODEC driver for AVR32.
 *
 * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32
 * - Supported devices:  All AVR32 devices with SSC, PDCA and TWI or SPI modules
 *                       can be used.
 * - AppNote:
 *
 * \author               Atmel Corporation: http://www.atmel.com \n
 *                       Support and FAQ: http://support.atmel.no/
 *
 ******************************************************************************/

/* Copyright (c) 2009 Atmel Corporation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. The name of Atmel may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an Atmel
 * AVR product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
 *
 */

#ifndef _TLV320AIC23B_H_
#define _TLV320AIC23B_H_

#include <limits.h>
#include <stddef.h>

#include "compiler.h"


/*! \name Control Interface
 */
//! @{

#define AIC23B_CTRL_INTERFACE_TWI   1       //!< Control interface: Two-Wire Interface.
#define AIC23B_CTRL_INTERFACE_SPI   2       //!< Control interface: Serial Peripheral Interface.

//! @}

/*! \name Mode Supported
 */
//! @{

#define AIC23B_MODE_DAC             0       //!< Mode supported: DAC
#define AIC23B_MODE_ADC             1       //!< Mode supported: ADC 
#define AIC23B_MODE_CODEC           3       //!< Mode supported: CODEC

//! @}

/*! \name Input Selected
 */
//! @{

#define AIC23B_INPUT_LINE           0       //!< Input Selected: LINE IN
#define AIC23B_INPUT_MIC            1       //!< Input Selected: MIC

//! @}

#include "conf_tlv320aic23b.h"


/*! \name Control Word
 */
//! @{

#define AIC23B_CTRL_SIZE            (AIC23B_CTRL_ADDR_SIZE + AIC23B_CTRL_DATA_SIZE)
#define AIC23B_CTRL_ADDR_OFFSET     9       //!< Control address bit-field offset.
#define AIC23B_CTRL_ADDR_SIZE       7       //!< Control address bit-field size.
#define AIC23B_CTRL_DATA_OFFSET     0       //!< Control data bit-field offset.
#define AIC23B_CTRL_DATA_SIZE       9       //!< Control data bit-field size.

//! Register structure.
typedef struct
{
  const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
        U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
} aic23b_ctrl_t;

//! @}


/*! \name Left Line Input Channel Volume Control
 */
//! @{

#define AIC23B_LLICVC               0x00    //!< Register index.
#define AIC23B_LLICVC_ADDRESS       0x00    //!< Register address.
#define AIC23B_LLICVC_DEFAULT       0x0097  //!< Register default value.
#define AIC23B_LLICVC_LRS_OFFSET    8       //!< Left/right line simultaneous volume/mute update bit-field offset.
#define AIC23B_LLICVC_LRS_SIZE      1       //!< Left/right line simultaneous volume/mute update bit-field size.
#define AIC23B_LLICVC_LIM_OFFSET    7       //!< Left line input mute bit-field offset.
#define AIC23B_LLICVC_LIM_SIZE      1       //!< Left line input mute bit-field size.
#define AIC23B_LLICVC_LIV_OFFSET    0       //!< Left line input volume control bit-field offset.
#define AIC23B_LLICVC_LIV_SIZE      5       //!< Left line input volume control bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16 lrs     : AIC23B_LLICVC_LRS_SIZE;   //!< Left/right line simultaneous volume/mute update.
          U16 lim     : AIC23B_LLICVC_LIM_SIZE;   //!< Left line input mute.
          U16         : 2;
          U16 liv     : AIC23B_LLICVC_LIV_SIZE;   //!< Left line input volume.
  };
} aic23b_llicvc_t;

//! @}


/*! \name Right Line Input Channel Volume Control
 */
//! @{

#define AIC23B_RLICVC               0x01    //!< Register index.
#define AIC23B_RLICVC_ADDRESS       0x01    //!< Register address.
#define AIC23B_RLICVC_DEFAULT       0x0097  //!< Register default value.
#define AIC23B_RLICVC_RLS_OFFSET    8       //!< Right/left line simultaneous volume/mute update bit-field offset.
#define AIC23B_RLICVC_RLS_SIZE      1       //!< Right/left line simultaneous volume/mute update bit-field size.
#define AIC23B_RLICVC_RIM_OFFSET    7       //!< Right line input mute bit-field offset.
#define AIC23B_RLICVC_RIM_SIZE      1       //!< Right line input mute bit-field size.
#define AIC23B_RLICVC_RIV_OFFSET    0       //!< Right line input volume control bit-field offset.
#define AIC23B_RLICVC_RIV_SIZE      5       //!< Right line input volume control bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16 rls     : AIC23B_RLICVC_RLS_SIZE;   //!< Right/left line simultaneous volume/mute update.
          U16 rim     : AIC23B_RLICVC_RIM_SIZE;   //!< Right line input mute.
          U16         : 2;
          U16 riv     : AIC23B_RLICVC_RIV_SIZE;   //!< Right line input volume.
  };
} aic23b_rlicvc_t;

//! @}


/*! \name Left Channel Headphone Volume Control
 */
//! @{

#define AIC23B_LCHVC                0x02    //!< Register index.
#define AIC23B_LCHVC_ADDRESS        0x02    //!< Register address.
#define AIC23B_LCHVC_DEFAULT        0x00F9  //!< Register default value.
#define AIC23B_LCHVC_LRS_OFFSET     8       //!< Left/right headphone channel simultaneous volume/mute update bit-field offset.
#define AIC23B_LCHVC_LRS_SIZE       1       //!< Left/right headphone channel simultaneous volume/mute update bit-field size.
#define AIC23B_LCHVC_LZC_OFFSET     7       //!< Left-channel zero-cross detect bit-field offset.
#define AIC23B_LCHVC_LZC_SIZE       1       //!< Left-channel zero-cross detect bit-field size.
#define AIC23B_LCHVC_LHV_OFFSET     0       //!< Left headphone volume control bit-field offset.
#define AIC23B_LCHVC_LHV_SIZE       7       //!< Left headphone volume control bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16 lrs     : AIC23B_LCHVC_LRS_SIZE;    //!< Left/right headphone channel simultaneous volume/mute update.
          U16 lzc     : AIC23B_LCHVC_LZC_SIZE;    //!< Left-channel zero-cross detect.
          U16 lhv     : AIC23B_LCHVC_LHV_SIZE;    //!< Left headphone volume control.
  };
} aic23b_lchvc_t;

//! @}


/*! \name Right Channel Headphone Volume Control
 */
//! @{

#define AIC23B_RCHVC                0x03    //!< Register index.
#define AIC23B_RCHVC_ADDRESS        0x03    //!< Register address.
#define AIC23B_RCHVC_DEFAULT        0x00F9  //!< Register default value.
#define AIC23B_RCHVC_RLS_OFFSET     8       //!< Right/left headphone channel simultaneous volume/mute update bit-field offset.
#define AIC23B_RCHVC_RLS_SIZE       1       //!< Right/left headphone channel simultaneous volume/mute update bit-field size.
#define AIC23B_RCHVC_RZC_OFFSET     7       //!< Right-channel zero-cross detect bit-field offset.
#define AIC23B_RCHVC_RZC_SIZE       1       //!< Right-channel zero-cross detect bit-field size.
#define AIC23B_RCHVC_RHV_OFFSET     0       //!< Right headphone volume control bit-field offset.
#define AIC23B_RCHVC_RHV_SIZE       7       //!< Right headphone volume control bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16 rls     : AIC23B_RCHVC_RLS_SIZE;    //!< Right/left headphone channel simultaneous volume/mute update.
          U16 rzc     : AIC23B_RCHVC_RZC_SIZE;    //!< Right-channel zero-cross detect.
          U16 rhv     : AIC23B_RCHVC_RHV_SIZE;    //!< Right headphone volume control.
  };
} aic23b_rchvc_t;

//! @}


/*! \name Analog Audio Path Control
 */
//! @{

#define AIC23B_AAPC                 0x04    //!< Register index.
#define AIC23B_AAPC_ADDRESS         0x04    //!< Register address.
#define AIC23B_AAPC_DEFAULT         0x000A  //!< Register default value.
#define AIC23B_AAPC_STA_OFFSET      6       //!< Sidetone addition bit-field offset.
#define AIC23B_AAPC_STA_SIZE        3       //!< Sidetone addition bit-field size.
#define AIC23B_AAPC_STA_M18DB       0x0003  //!< Added sidetone: -18 dB.
#define AIC23B_AAPC_STA_M12DB       0x0002  //!< Added sidetone: -12 dB.
#define AIC23B_AAPC_STA_M9DB        0x0001  //!< Added sidetone: -9 dB.
#define AIC23B_AAPC_STA_M6DB        0x0000  //!< Added sidetone: -6 dB.
#define AIC23B_AAPC_STA_0DB         0x0004  //!< Added sidetone: 0 dB.
#define AIC23B_AAPC_STE_OFFSET      5       //!< Sidetone enable bit-field offset.
#define AIC23B_AAPC_STE_SIZE        1       //!< Sidetone enable bit-field size.
#define AIC23B_AAPC_DAC_OFFSET      4       //!< DAC select bit-field offset.
#define AIC23B_AAPC_DAC_SIZE        1       //!< DAC select bit-field size.
#define AIC23B_AAPC_BYP_OFFSET      3       //!< Bypass bit-field offset.
#define AIC23B_AAPC_BYP_SIZE        1       //!< Bypass bit-field size.
#define AIC23B_AAPC_INSEL_OFFSET    2       //!< Input select for ADC bit-field offset.
#define AIC23B_AAPC_INSEL_SIZE      1       //!< Input select for ADC bit-field size.
#define AIC23B_AAPC_INSEL_LINE      0x0000  //!< Input selected for ADC: line.
#define AIC23B_AAPC_INSEL_MIC       0x0001  //!< Input selected for ADC: microphone.
#define AIC23B_AAPC_MICM_OFFSET     1       //!< Microphone mute bit-field offset.
#define AIC23B_AAPC_MICM_SIZE       1       //!< Microphone mute bit-field size.
#define AIC23B_AAPC_MICB_OFFSET     0       //!< Microphone boost (+20 dB) bit-field offset.
#define AIC23B_AAPC_MICB_SIZE       1       //!< Microphone boost (+20 dB) bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16 sta     : AIC23B_AAPC_STA_SIZE;     //!< Sidetone addition.
          U16 ste     : AIC23B_AAPC_STE_SIZE;     //!< Sidetone enable.
          U16 dac     : AIC23B_AAPC_DAC_SIZE;     //!< DAC select.
          U16 byp     : AIC23B_AAPC_BYP_SIZE;     //!< Bypass.
          U16 insel   : AIC23B_AAPC_INSEL_SIZE;   //!< Input select for ADC.
          U16 micm    : AIC23B_AAPC_MICM_SIZE;    //!< Microphone mute.
          U16 micb    : AIC23B_AAPC_MICB_SIZE;    //!< Microphone boost.
  };
} aic23b_aapc_t;

//! @}


/*! \name Digital Audio Path Control
 */
//! @{

#define AIC23B_DAPC                 0x05    //!< Register index.
#define AIC23B_DAPC_ADDRESS         0x05    //!< Register address.
#define AIC23B_DAPC_DEFAULT         0x0008  //!< Register default value.
#define AIC23B_DAPC_DACM_OFFSET     3       //!< DAC soft mute bit-field offset.
#define AIC23B_DAPC_DACM_SIZE       1       //!< DAC soft mute bit-field size.
#define AIC23B_DAPC_DEEMP_OFFSET    1       //!< De-emphasis control bit-field offset.
#define AIC23B_DAPC_DEEMP_SIZE      2       //!< De-emphasis control bit-field size.
#define AIC23B_DAPC_DEEMP_NONE      0x0000  //!< De-emphasis: none.
#define AIC23B_DAPC_DEEMP_32KHZ     0x0001  //!< De-emphasis: 32 kHz.
#define AIC23B_DAPC_DEEMP_44_1KHZ   0x0002  //!< De-emphasis: 44.1 kHz.
#define AIC23B_DAPC_DEEMP_48KHZ     0x0003  //!< De-emphasis: 48 kHz.
#define AIC23B_DAPC_ADCHP_OFFSET    0       //!< ADC high-pass filter bit-field offset.
#define AIC23B_DAPC_ADCHP_SIZE      1       //!< ADC high-pass filter bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16         : 5;
          U16 dacm    : AIC23B_DAPC_DACM_SIZE;    //!< DAC soft mute.
          U16 deemp   : AIC23B_DAPC_DEEMP_SIZE;   //!< De-emphasis control.
          U16 adchp   : AIC23B_DAPC_ADCHP_SIZE;   //!< ADC high-pass filter.
  };
} aic23b_dapc_t;

//! @}


/*! \name Power Down Control
 */
//! @{

#define AIC23B_PDC                  0x06    //!< Register index.
#define AIC23B_PDC_ADDRESS          0x06    //!< Register address.
#define AIC23B_PDC_DEFAULT          0x0007  //!< Register default value.
#define AIC23B_PDC_OFF_OFFSET       7       //!< Device power bit-field offset.
#define AIC23B_PDC_OFF_SIZE         1       //!< Device power bit-field size.
#define AIC23B_PDC_CLK_OFFSET       6       //!< Clock bit-field offset.
#define AIC23B_PDC_CLK_SIZE         1       //!< Clock bit-field size.
#define AIC23B_PDC_OSC_OFFSET       5       //!< Oscillator bit-field offset.
#define AIC23B_PDC_OSC_SIZE         1       //!< Oscillator bit-field size.
#define AIC23B_PDC_OUT_OFFSET       4       //!< Outputs bit-field offset.
#define AIC23B_PDC_OUT_SIZE         1       //!< Outputs bit-field size.
#define AIC23B_PDC_DAC_OFFSET       3       //!< DAC bit-field offset.
#define AIC23B_PDC_DAC_SIZE         1       //!< DAC bit-field size.
#define AIC23B_PDC_ADC_OFFSET       2       //!< ADC bit-field offset.
#define AIC23B_PDC_ADC_SIZE         1       //!< ADC bit-field size.
#define AIC23B_PDC_MIC_OFFSET       1       //!< Microphone input bit-field offset.
#define AIC23B_PDC_MIC_SIZE         1       //!< Microphone input bit-field size.
#define AIC23B_PDC_LINE_OFFSET      0       //!< Line input bit-field offset.
#define AIC23B_PDC_LINE_SIZE        1       //!< Line input bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16         : 1;
          U16 off     : AIC23B_PDC_OFF_SIZE;      //!< Device power.
          U16 clk     : AIC23B_PDC_CLK_SIZE;      //!< Clock.
          U16 osc     : AIC23B_PDC_OSC_SIZE;      //!< Oscillator.
          U16 out     : AIC23B_PDC_OUT_SIZE;      //!< Outputs.
          U16 dac     : AIC23B_PDC_DAC_SIZE;      //!< DAC.
          U16 adc     : AIC23B_PDC_ADC_SIZE;      //!< ADC.
          U16 mic     : AIC23B_PDC_MIC_SIZE;      //!< Microphone input.
          U16 line    : AIC23B_PDC_LINE_SIZE;     //!< Line input.
  };
} aic23b_pdc_t;

//! @}


/*! \name Digital Audio Interface Format
 */
//! @{

#define AIC23B_DAIF                 0x07    //!< Register index.
#define AIC23B_DAIF_ADDRESS         0x07    //!< Register address.
#define AIC23B_DAIF_DEFAULT         0x0001  //!< Register default value.
#define AIC23B_DAIF_MS_OFFSET       6       //!< Master/slave mode bit-field offset.
#define AIC23B_DAIF_MS_SIZE         1       //!< Master/slave mode bit-field size.
#define AIC23B_DAIF_MS_SLAVE        0x0000  //!< Slave mode.
#define AIC23B_DAIF_MS_MASTER       0x0001  //!< Master mode.
#define AIC23B_DAIF_LRSWAP_OFFSET   5       //!< DAC left/right swap bit-field offset.
#define AIC23B_DAIF_LRSWAP_SIZE     1       //!< DAC left/right swap bit-field size.
#define AIC23B_DAIF_LRP_OFFSET      4       //!< DAC left/right phase bit-field offset.
#define AIC23B_DAIF_LRP_SIZE        1       //!< DAC left/right phase bit-field size.
#define AIC23B_DAIF_IWL_OFFSET      2       //!< Input bit length bit-field offset.
#define AIC23B_DAIF_IWL_SIZE        2       //!< Input bit length bit-field size.
#define AIC23B_DAIF_IWL_16          0x0000  //!< Input bit length: 16.
#define AIC23B_DAIF_IWL_20          0x0001  //!< Input bit length: 20.
#define AIC23B_DAIF_IWL_24          0x0002  //!< Input bit length: 24.
#define AIC23B_DAIF_IWL_32          0x0003  //!< Input bit length: 32.
#define AIC23B_DAIF_FMT_OFFSET      0       //!< Data format bit-field offset.
#define AIC23B_DAIF_FMT_SIZE        2       //!< Data format bit-field size.
#define AIC23B_DAIF_FMT_RA          0x0000  //!< Data format: MSB first, right aligned.
#define AIC23B_DAIF_FMT_LA          0x0001  //!< Data format: MSB first, left aligned.
#define AIC23B_DAIF_FMT_I2S         0x0002  //!< Data format: I²S format, MSB first, left - 1 aligned.
#define AIC23B_DAIF_FMT_DSP         0x0003  //!< Data format: DSP format, frame sync followed by two data words.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16         : 2;
          U16 ms      : AIC23B_DAIF_MS_SIZE;      //!< Master/slave mode.
          U16 lrswap  : AIC23B_DAIF_LRSWAP_SIZE;  //!< DAC left/right swap.
          U16 lrp     : AIC23B_DAIF_LRP_SIZE;     //!< DAC left/right phase.
          U16 iwl     : AIC23B_DAIF_IWL_SIZE;     //!< Input bit length.
          U16 fmt     : AIC23B_DAIF_FMT_SIZE;     //!< Data format.
  };
} aic23b_daif_t;

//! @}


/*! \name Sample Rate Control
 */
//! @{

#define AIC23B_SRC                  0x08    //!< Register index.
#define AIC23B_SRC_ADDRESS          0x08    //!< Register address.
#define AIC23B_SRC_DEFAULT          0x0020  //!< Register default value.
#define AIC23B_SRC_CLKOUT_OFFSET    7       //!< Clock output divider bit-field offset.
#define AIC23B_SRC_CLKOUT_SIZE      1       //!< Clock output divider bit-field size.
#define AIC23B_SRC_CLKIN_OFFSET     6       //!< Clock input divider bit-field offset.
#define AIC23B_SRC_CLKIN_SIZE       1       //!< Clock input divider bit-field size.
#define AIC23B_SRC_SR_OFFSET        2       //!< Sampling rate control bit-field offset.
#define AIC23B_SRC_SR_SIZE          4       //!< Sampling rate control bit-field size.
#define AIC23B_SRC_BOSR_OFFSET      1       //!< Base oversampling rate bit-field offset.
#define AIC23B_SRC_BOSR_SIZE        1       //!< Base oversampling rate bit-field size.
#define AIC23B_SRC_USB_OFFSET       0       //!< USB clock mode select bit-field offset.
#define AIC23B_SRC_USB_SIZE         1       //!< USB clock mode select bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16         : 1;
          U16 clkout  : AIC23B_SRC_CLKOUT_SIZE;   //!< Clock output divider.
          U16 clkin   : AIC23B_SRC_CLKIN_SIZE;    //!< Clock input divider.
          U16 sr      : AIC23B_SRC_SR_SIZE;       //!< Sampling rate control.
          U16 bosr    : AIC23B_SRC_BOSR_SIZE;     //!< Base oversampling rate.
          U16 usb     : AIC23B_SRC_USB_SIZE;      //!< USB clock mode select.
  };
} aic23b_src_t;

//! @}


/*! \name Digital Interface Activation
 */
//! @{

#define AIC23B_DIA                  0x09    //!< Register index.
#define AIC23B_DIA_ADDRESS          0x09    //!< Register address.
#define AIC23B_DIA_DEFAULT          0x0000  //!< Register default value.
#define AIC23B_DIA_ACT_OFFSET       0       //!< Activate interface bit-field offset.
#define AIC23B_DIA_ACT_SIZE         1       //!< Activate interface bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16         : 8;
          U16 act     : AIC23B_DIA_ACT_SIZE;      //!< Activate interface.
  };
} aic23b_dia_t;

//! @}


/*! \name Reset Register
 */
//! @{

#define AIC23B_RR                   0x0A    //!< Register index.
#define AIC23B_RR_ADDRESS           0x0F    //!< Register address.
#define AIC23B_RR_DEFAULT           0x0000  //!< Register default value.
#define AIC23B_RR_RES_OFFSET        0       //!< Reset bit-field offset.
#define AIC23B_RR_RES_SIZE          9       //!< Reset bit-field size.

//! Register structure.
typedef union
{
  struct
  {
    const U16 addr    : AIC23B_CTRL_ADDR_SIZE;    //!< Control address.
          U16 data    : AIC23B_CTRL_DATA_SIZE;    //!< Control data.
  };
  struct
  {
    const U16         : AIC23B_CTRL_ADDR_SIZE;
          U16 res     : AIC23B_RR_RES_SIZE;       //!< Reset.
  };
} aic23b_rr_t;

//! @}


/*! \name Register Structure
 */
//! @{

//! Returns the address of the \a REG register (e.g. \c AIC23B_LLICVC).
#define AIC23B_ADDRESS(REG)                                                    \
  REG##_ADDRESS

//! Returns the default value of the \a REG register (e.g. \c AIC23B_LLICVC).
#define AIC23B_DEFAULT(REG)                                                    \
  REG##_DEFAULT

//! Returns the offset of the \a BITFIELD bit-field (e.g. LRS) in its \a REG
//! register (e.g. \c AIC23B_LLICVC).
#define AIC23B_OFFSET(REG, BITFIELD)                                           \
  REG##_##BITFIELD##_OFFSET

//! Returns the size of the \a BITFIELD bit-field (e.g. LRS) of the \a REG
//! register (e.g. \c AIC23B_LLICVC).
#define AIC23B_SIZE(REG, BITFIELD)                                             \
  REG##_##BITFIELD##_SIZE

//! Returns the mask of the \a BITFIELD bit-field (e.g. LRS) in its \a REG
//! register (e.g. \c AIC23B_LLICVC).
#define AIC23B_MASK(REG, BITFIELD)                                             \
  (((1 << REG##_##BITFIELD##_SIZE) - 1) << REG##_##BITFIELD##_OFFSET)

//! @}


/*! \name Audio Channels
 */
//! @{

#define AIC23B_LEFT_CHANNEL     0x01
#define AIC23B_RIGHT_CHANNEL    0x02

//! @}


/*! \name Volume Control
 */
//! @{

#define AIC23B_MUTED            SCHAR_MIN
#define AIC23B_LIN_VOL_OFFSET   0x17
#define AIC23B_LIN_VOL_MIN      ((S8)(-34.5 * 2 / 3))
#define AIC23B_LIN_VOL_MAX      ((S8)(+12   * 2 / 3))
#define AIC23B_HP_VOL_OFFSET    0x79
#define AIC23B_HP_VOL_MIN       ((S8)(-72)) // -72dB
#define AIC23B_HP_VOL_MAX       ((S8)(+ 6)) // +6dB

//! @}


/*! \name Low-Level Interface
 */
//! @{

/*! \brief Reads the \a reg register.
 */
extern U16 aic23b_read_reg(U8 reg);

/*! \brief Writes \a val to the \a reg register.
 */
extern void aic23b_write_reg(U8 reg, U16 val);

//! @}


/*! \name Mid-Level Interface
 */
//! @{

/*! \brief Gets the \a ch line input channel volume.
 */
extern S8 aic23b_get_line_in_volume(U8 ch);

/*! \brief Sets the \a ch_mask line input channels volume to \a vol.
 */
extern void aic23b_set_line_in_volume(U8 ch_mask, S8 vol);

/*! \brief Gets the average headphone volume.
 */
extern U8 aic23b_dac_get_average_headphone_volume(void);

/*! \brief Sets the average headphone volume.
 */
extern void aic23b_dac_set_average_headphone_volume(U8 volume);

/*! \brief Returns the state of the mute mode of the DAC.
 */
extern Bool aic23b_dac_is_headphone_volume_muted(void);

/*! \brief Returns the state of the boost mode of the DAC.
 */
extern Bool aic23b_dac_is_headphone_volume_boosted(void);

/*! \brief Gets the \a ch channel headphone volume.
 */
extern S8 aic23b_get_headphone_volume(U8 ch);

/*! \brief Sets the \a ch_mask channels headphone volume to \a vol, with
 *         zero-cross detect if \a z_cross is \c TRUE.
 */
extern void aic23b_set_headphone_volume(U8 ch_mask, S8 vol, Bool z_cross);

/*! \brief Gets the analog audio path.
 */
extern aic23b_aapc_t aic23b_get_analog_audio_path(void);

/*! \brief Sets the analog audio path to \a aapc.
 */
extern void aic23b_set_analog_audio_path(aic23b_aapc_t aapc);

/*! \brief Gets the digital audio path.
 */
extern aic23b_dapc_t aic23b_get_digital_audio_path(void);

/*! \brief Sets the digital audio path to \a dapc.
 */
extern void aic23b_set_digital_audio_path(aic23b_dapc_t dapc);

/*! \brief Gets the power down state.
 */
extern aic23b_pdc_t aic23b_get_power_down_state(void);

/*! \brief Sets the power down state to \a pdc.
 */
extern void aic23b_set_power_down_state(aic23b_pdc_t pdc);

/*! \brief Tells whether the digital audio interface is activated.
 */
extern Bool aic23b_is_dig_audio_activated(void);

/*! \brief Activates or deactivates the digital audio interface according to
 *         \a act.
 */
extern void aic23b_activate_dig_audio(Bool act);

/*! \brief Resets the CODEC.
 */
extern void aic23b_reset(void);

/*! \brief Used to configure the codec frequency
 */
extern void aic23b_configure_freq(int master_clock_hz, int sample_rate_hz);

//! @}


/*! \name High-Level Interface
 */
//! @{

/*! \brief Starts the DAC.
 */
extern void aic23b_dac_start(U32 sample_rate_hz,
                             U8 num_channels,
                             U8 bits_per_sample,
                             Bool swap_channels,
                             void (*callback)(U32 arg),
                             U32 callback_opt,
                             U32 pba_hz);

/*! \brief Sets the DAC up with new settings.
 *
 * \note The DAC must have been started beforehand.
 */
extern void aic23b_dac_setup(U32 sample_rate_hz,
                             U8 num_channels,
                             U8 bits_per_sample,
                             Bool swap_channels,
                             void (*callback)(U32 arg),
                             U32 callback_opt,
                             U32 pba_hz);

/*! \brief Outputs a sample buffer to the DAC.
 *
 * \note The DAC must have been started beforehand.
 */
extern Bool aic23b_dac_output(void *sample_buffer, size_t sample_length);

/*! \brief Increases the output volume of the DAC.
 *
 * \note The DAC must have been started beforehand.
 */
extern void aic23b_dac_increase_volume(void);

/*! \brief Decreases the output volume of the DAC.
 *
 * \note The DAC must have been started beforehand.
 */
extern void aic23b_dac_decrease_volume(void);

/*! \brief Flushes the sample buffer being output to the DAC.
 */
extern void aic23b_dac_flush(void);

/*! \brief Stops the DAC.
 */
extern void aic23b_dac_stop(void);


/*! \brief Starts the ADC.
 */
extern void aic23b_adc_start(U32 sample_rate_hz,
                             U8 num_channels,
                             U8 bits_per_sample,
                             Bool swap_channels,
                             void (*callback)(U32 arg),
                             U32 callback_opt,
                             U32 pba_hz);

/*! \brief Sets the ADC up with new settings.
 *
 * \note The ADC must have been started beforehand.
 */
extern void aic23b_adc_setup(U32 sample_rate_hz,
                             U8 num_channels,
                             U8 bits_per_sample,
                             Bool swap_channels,
                             void (*callback)(U32 arg),
                             U32 callback_opt,
                             U32 pba_hz);

/*! \brief Input a sample buffer from the ADC.
 *
 * \note The ADC must have been started beforehand.
 */
extern Bool aic23b_adc_input(void *sample_buffer, size_t sample_length);

/*! \brief Flushes the sample buffer being input from the ADC.
 */
extern void aic23b_adc_flush(void);

/*! \brief Stops the ADC.
 */
extern void aic23b_adc_stop(void);

/*! \brief Starts the CODEC.
 */
extern void aic23b_codec_start(U32 sample_rate_hz,
                             U8 num_channels,
                             U8 bits_per_sample,
                             Bool swap_channels,
                             void (*callback)(U32 arg),
                             U32 callback_opt,
                             U32 pba_hz);

/*! \brief Sets the CODEC up with new settings.
 *
 * \note The CODEC must have been started beforehand.
 */
extern void aic23b_codec_setup(U32 sample_rate_hz,
                             U8 num_channels,
                             U8 bits_per_sample,
                             Bool swap_channels,
                             void (*callback)(U32 arg),
                             U32 callback_opt,
                             U32 pba_hz);
                             
/*! \brief Flushes the sample buffers being input from the ADC and output to the DAC.
 */
extern void aic23b_codec_flush(void);

/*! \brief Stops the CODEC.
 */
extern void aic23b_codec_stop(void);

/*! \brief Mute audio if mute is set to true.
 */
extern void  aic23b_dac_mute(Bool mute);

//! @}


#endif  // _TLV320AIC23B_H_
