221 lines
5.9 KiB
C
221 lines
5.9 KiB
C
/***************************************************************************
|
|
*
|
|
* Copyright 2015-2019 BES.
|
|
* All rights reserved. All unpublished rights reserved.
|
|
*
|
|
* No part of this work may be used or reproduced in any form or by any
|
|
* means, or stored in a database or retrieval system, without prior written
|
|
* permission of BES.
|
|
*
|
|
* Use of this work is governed by a license granted by BES.
|
|
* This work contains confidential and proprietary information of
|
|
* BES. which is protected by copyright, trade secret,
|
|
* trademark and other intellectual property rights.
|
|
*
|
|
****************************************************************************/
|
|
#include "codec_tlv32aic32.h"
|
|
#include "hal_i2c.h"
|
|
#include "hal_i2s.h"
|
|
#include "hal_trace.h"
|
|
#include "hal_uart.h"
|
|
#include "plat_types.h"
|
|
#include "string.h"
|
|
|
|
#define TLV32AIC32_INST HAL_I2S_ID_0
|
|
|
|
static struct HAL_I2C_CONFIG_T _codec_i2c_cfg;
|
|
|
|
static uint8_t sample_rate_div[] = {
|
|
10, /* index is 0 */
|
|
15, 20, 25, 30, 35, 40, 45, 50, 55, 60,
|
|
};
|
|
|
|
/* i2c write */
|
|
static int codec_write(uint8_t reg_addr, uint8_t value) {
|
|
uint8_t buf[2];
|
|
buf[0] = reg_addr;
|
|
buf[1] = value;
|
|
|
|
return hal_i2c_task_send(HAL_I2C_ID_0, TLV32AIC32_I2C_ADDRESS, buf, 1 + 1, 0,
|
|
0);
|
|
}
|
|
|
|
/* i2c read */
|
|
#if 0
|
|
static uint8_t codec_read(uint8_t reg_addr)
|
|
{
|
|
uint8_t buf[2];
|
|
|
|
buf[0] = reg_addr;
|
|
buf[1] = 0;
|
|
|
|
hal_i2c_task_recv(HAL_I2C_ID_0, TLV32AIC32_I2C_ADDRESS, &buf[0], 1, &buf[1], 1, 0, 0);
|
|
|
|
return buf[1];
|
|
}
|
|
#endif
|
|
|
|
uint32_t tlv32aic32_open(void) {
|
|
_codec_i2c_cfg.mode = HAL_I2C_API_MODE_TASK;
|
|
_codec_i2c_cfg.use_dma = 0;
|
|
_codec_i2c_cfg.use_sync = 1;
|
|
_codec_i2c_cfg.speed = 20000;
|
|
_codec_i2c_cfg.as_master = 1;
|
|
hal_i2c_open(HAL_I2C_ID_0, &_codec_i2c_cfg);
|
|
|
|
return 0;
|
|
}
|
|
uint32_t tlv32aic32_stream_open(enum AUD_STREAM_T stream) {
|
|
hal_i2s_open(TLV32AIC32_INST, stream, HAL_I2S_MODE_MASTER);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t tlv32aic32_stream_setup(enum AUD_STREAM_T stream,
|
|
struct tlv32aic32_config_t *cfg) {
|
|
uint32_t param = 0, i = 0;
|
|
|
|
/* select page : 0*/
|
|
codec_write(AIC3X_PAGE_SELECT, PAGE0_SELECT);
|
|
|
|
/* soft reset : 1 */
|
|
codec_write(AIC3X_RESET, SOFT_RESET);
|
|
|
|
/* CLKDIV_IN uses mCLK : 102 , PLLDIV_IN use mCLK */
|
|
codec_write(AIC3X_CLKGEN_CTRL_REG, 0x02);
|
|
|
|
/* CODEC_CLK_IN uses CLKDIV : 101, CODEC_CLK_IN use CLKDIV_IN */
|
|
codec_write(101, 0x00);
|
|
|
|
/* PLL R value : 11, R is 1 */
|
|
codec_write(AIC3X_OVRF_STATUS_AND_PLLR_REG, 0x1);
|
|
|
|
/* PLL J value : 4, J is 8 */
|
|
codec_write(AIC3X_PLL_PROGB_REG, 0x8);
|
|
|
|
/* PLL D value : 5,6, D is 1920 */
|
|
codec_write(AIC3X_PLL_PROGC_REG, 0x780 >> 6);
|
|
|
|
codec_write(AIC3X_PLL_PROGD_REG, (0x780 & 0x3f) << 2);
|
|
|
|
/* PLL disable and select Q value : 3, enable pll, Q is 2 */
|
|
codec_write(AIC3X_PLL_PROGA_REG, 0x81);
|
|
|
|
/* left and right DAC open : 7, open codec dac path and fref */
|
|
if ((cfg->sample_rate % 8000) == 0) {
|
|
/* 48000 */
|
|
codec_write(AIC3X_CODEC_DATAPATH_REG, 0x0a);
|
|
param = 480000 / cfg->sample_rate;
|
|
} else {
|
|
/* 44100 */
|
|
codec_write(AIC3X_CODEC_DATAPATH_REG, 0x8a);
|
|
param = 441000 / cfg->sample_rate;
|
|
}
|
|
|
|
for (i = 0; i < sizeof(sample_rate_div); ++i) {
|
|
if (param == sample_rate_div[i])
|
|
break;
|
|
}
|
|
|
|
if (i == sizeof(sample_rate_div)) {
|
|
i = 0;
|
|
}
|
|
|
|
/* sample_rate divider : 2, default is /1 */
|
|
codec_write(AIC3X_SAMPLE_RATE_SEL_REG, i << 4 | i << 4);
|
|
|
|
/* ctrl mode : 8, bitclock input, word clock input */
|
|
codec_write(AIC3X_ASD_INTF_CTRLA, 0x20);
|
|
|
|
/* Audio Serial Data Interface Control : 9, 16bit i2s mode */
|
|
if (cfg->bits == AUD_BITS_16)
|
|
param = 0;
|
|
else if (cfg->bits == AUD_BITS_20)
|
|
param = 1;
|
|
else if (cfg->bits == AUD_BITS_24)
|
|
param = 2;
|
|
else if (cfg->bits == AUD_BITS_32)
|
|
param = 3;
|
|
else
|
|
param = 0;
|
|
|
|
codec_write(AIC3X_ASD_INTF_CTRLB, 0x00 | param << 4);
|
|
|
|
/* out ac-coupled : 14, headset control */
|
|
codec_write(AIC3X_HEADSET_DETECT_CTRL_B, 0x08);
|
|
|
|
/* left and right DAC power on : 37 */
|
|
// codec_write(DAC_PWR, 0xC0);
|
|
codec_write(DAC_PWR, 0xD0);
|
|
|
|
/* out common-mode voltage : 40 */
|
|
codec_write(HPOUT_SC, 0x00);
|
|
|
|
/* out path select : 41 */
|
|
codec_write(DAC_LINE_MUX, 0xA1);
|
|
|
|
/* left DAC not muted : 43 */
|
|
codec_write(LDAC_VOL, 0x0f);
|
|
|
|
/* right DAC not muted : 44 */
|
|
codec_write(RDAC_VOL, 0x0f);
|
|
|
|
/* HPLOUT is not muted : 51 */
|
|
codec_write(HPLOUT_CTRL, 0x9F);
|
|
|
|
/* HPROUT is not muted : 65 */
|
|
codec_write(HPROUT_CTRL, 0x9F);
|
|
|
|
/* out short circuit protection : 38 */
|
|
// codec_write(HPRCOM_CFG, 0x3A);
|
|
codec_write(HPRCOM_CFG, 0x22);
|
|
|
|
/* input */
|
|
/* mic bias : 25 */
|
|
codec_write(MICBIAS_CTRL, 0x40);
|
|
/* left adc power : 19 */
|
|
codec_write(LINE1L_2_LADC_CTRL, 0x04);
|
|
/* right adc power : 22 */
|
|
codec_write(LINE1R_2_RADC_CTRL, 0x04);
|
|
/* left adc pga mute : 15 */
|
|
codec_write(LADC_VOL, 0x0);
|
|
/* right adc pga mute : 16 */
|
|
codec_write(RADC_VOL, 0x0);
|
|
/* adc flag : 36 */
|
|
// TRACE(1,"tlv adc flag 0x%x", codec_read(ADC_FLAG));
|
|
/* left adc pga mute : 15 */
|
|
// TRACE(1,"tlv left adc pga 0x%x", codec_read(LADC_VOL));
|
|
/* right adc pga mute : 16 */
|
|
// TRACE(1,"tlv right adc pga 0x%x", codec_read(RADC_VOL));
|
|
/* input end */
|
|
|
|
struct HAL_I2S_CONFIG_T i2s_cfg;
|
|
|
|
memset(&i2s_cfg, 0, sizeof(i2s_cfg));
|
|
i2s_cfg.use_dma = cfg->use_dma;
|
|
i2s_cfg.chan_sep_buf = cfg->chan_sep_buf;
|
|
i2s_cfg.sync_start = cfg->sync_start;
|
|
i2s_cfg.cycles = cfg->slot_cycles;
|
|
i2s_cfg.bits = cfg->bits;
|
|
i2s_cfg.channel_num = cfg->channel_num;
|
|
i2s_cfg.channel_map = cfg->channel_map;
|
|
i2s_cfg.sample_rate = cfg->sample_rate;
|
|
hal_i2s_setup_stream(TLV32AIC32_INST, stream, &i2s_cfg);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t tlv32aic32_stream_start(enum AUD_STREAM_T stream) {
|
|
hal_i2s_start_stream(TLV32AIC32_INST, stream);
|
|
return 0;
|
|
}
|
|
uint32_t tlv32aic32_stream_stop(enum AUD_STREAM_T stream) {
|
|
hal_i2s_stop_stream(TLV32AIC32_INST, stream);
|
|
return 0;
|
|
}
|
|
uint32_t tlv32aic32_stream_close(enum AUD_STREAM_T stream) {
|
|
hal_i2s_close(TLV32AIC32_INST, stream);
|
|
return 0;
|
|
}
|
|
uint32_t tlv32aic32_close(void) { return 0; }
|