/* * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Date Author Notes * 2019-07-31 Zero-Free first implementation */ #include #include #include "drv_es8388.h" /* ES8388 address */ #define ES8388_ADDR 0x10 /*0x11:CE=1;0x10:CE=0*/ struct es8388_device { struct rt_i2c_bus_device *i2c; rt_uint16_t pin; }; static struct es8388_device es_dev = {0}; static rt_uint16_t reg_read(rt_uint8_t addr) { struct rt_i2c_msg msg[2] = {0}; rt_uint8_t val = 0xff; RT_ASSERT(es_dev.i2c != RT_NULL); msg[0].addr = ES8388_ADDR; msg[0].flags = RT_I2C_WR; msg[0].len = 1; msg[0].buf = &addr; msg[1].addr = ES8388_ADDR; msg[1].flags = RT_I2C_RD; msg[1].len = 1; msg[1].buf = &val; if (rt_i2c_transfer(es_dev.i2c, msg, 2) != 2) { rt_kprintf("I2C read data failed, reg = 0x%02x. \n", addr); return 0xff; } return val; } static void reg_write(rt_uint8_t addr, rt_uint8_t val) { struct rt_i2c_msg msgs[1] = {0}; rt_uint8_t buff[2] = {0}; RT_ASSERT(es_dev.i2c != RT_NULL); buff[0] = addr; buff[1] = val; msgs[0].addr = ES8388_ADDR; msgs[0].flags = RT_I2C_WR; msgs[0].buf = buff; msgs[0].len = 2; if (rt_i2c_transfer(es_dev.i2c, msgs, 1) != 1) { rt_kprintf("I2C write data failed, reg = 0x%2x. \n", addr); return; } } static int es8388_set_adc_dac_volume(int mode, int volume, int dot) { int res = 0; if (volume < -96 || volume > 0) { if (volume < -96) volume = -96; else volume = 0; } dot = (dot >= 5 ? 1 : 0); volume = (-volume << 1) + dot; if (mode == ES_MODE_ADC || mode == ES_MODE_DAC_ADC) { reg_write(ES8388_ADCCONTROL8, volume); reg_write(ES8388_ADCCONTROL9, volume); //ADC Right Volume=0db } if (mode == ES_MODE_DAC || mode == ES_MODE_DAC_ADC) { reg_write(ES8388_DACCONTROL5, volume); reg_write(ES8388_DACCONTROL4, volume); } return res; } void es8388_set_voice_mute(rt_bool_t enable) { rt_uint8_t reg = 0; reg = reg_read(ES8388_DACCONTROL3); reg = reg & 0xFB; reg_write(ES8388_DACCONTROL3, reg | (((int)enable) << 2)); } rt_err_t es8388_init(const char *i2c_name, rt_uint16_t pin) { es_dev.i2c = rt_i2c_bus_device_find(i2c_name); if (es_dev.i2c == RT_NULL) { rt_kprintf("%s bus not found\n", i2c_name); return -RT_ERROR; } es_dev.pin = pin; reg_write(ES8388_DACCONTROL3, 0x04); // 0x04 mute/0x00 unmute&ramp;DAC unmute and disabled digital volume control soft ramp /* Chip Control and Power Management */ reg_write(ES8388_CONTROL2, 0x50); reg_write(ES8388_CHIPPOWER, 0x00); //normal all and power up all reg_write(ES8388_MASTERMODE, 0x00); //TODO:CODEC IN I2S SLAVE MODE /* dac */ reg_write(ES8388_DACPOWER, 0xC0); //disable DAC and disable Lout/Rout/1/2 reg_write(ES8388_CONTROL1, 0x12); //Enfr=0,Play&Record Mode,(0x17-both of mic&paly) // reg_write(ES8388_CONTROL2, 0); //LPVrefBuf=0,Pdn_ana=0 reg_write(ES8388_DACCONTROL1, 0x18);//1a 0x18:16bit iis , 0x00:24 reg_write(ES8388_DACCONTROL2, 0x02); //DACFsMode,SINGLE SPEED; DACFsRatio,256 reg_write(ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1, 0x09 LIN2&RIN2 reg_write(ES8388_DACCONTROL17, 0x9C); // only left DAC to left mixer enable 0db reg_write(ES8388_DACCONTROL20, 0x9C); // only right DAC to right mixer enable 0db reg_write(ES8388_DACCONTROL21, 0x80); //set internal ADC and DAC use the same LRCK clock, ADC LRCK as internal LRCK reg_write(ES8388_DACCONTROL23, 0x00); //vroi=0 es8388_set_adc_dac_volume(ES_MODE_DAC, 0, 0); // 0db reg_write(ES8388_DACPOWER, 0x3c); //0x3c Enable DAC and Enable Lout/Rout/1/2 /* adc */ reg_write(ES8388_ADCPOWER, 0xFF); reg_write(ES8388_ADCCONTROL1, 0xbb); // MIC Left and Right channel PGA gain reg_write(ES8388_ADCCONTROL2, 0x00); //0x00 LINSEL & RINSEL, LIN1/RIN1 as ADC Input; DSSEL,use one DS Reg11; DSR, LINPUT1-RINPUT1 reg_write(ES8388_ADCCONTROL3, 0x02); reg_write(ES8388_ADCCONTROL4, 0x0d); // Left/Right data, Left/Right justified mode, Bits length, I2S format reg_write(ES8388_ADCCONTROL5, 0x02); //ADCFsMode,singel SPEED,RATIO=256 //ALC for Microphone es8388_set_adc_dac_volume(ES_MODE_ADC, 0, 0); // 0db reg_write(ES8388_ADCPOWER, 0x09); //Power on ADC, Enable LIN&RIN, Power off MICBIAS, set int1lp to low power mode /* enable es8388 PA */ es8388_pa_power(RT_TRUE); reg_write(ES8388_DACCONTROL24, 0x1E); // LOUT1VOL balanced noise: 0x18 reg_write(ES8388_DACCONTROL25, 0x1E); // ROUT1VOL balanced noise: 0x18 return RT_EOK; } rt_err_t es8388_start(enum es8388_mode mode) { int res = 0; rt_uint8_t prev_data = 0, data = 0; prev_data = reg_read(ES8388_DACCONTROL21); if (mode == ES_MODE_LINE) { reg_write(ES8388_DACCONTROL16, 0x09); // 0x00 audio on LIN1&RIN1, 0x09 LIN2&RIN2 by pass enable reg_write(ES8388_DACCONTROL17, 0x50); // left DAC to left mixer enable and LIN signal to left mixer enable 0db : bupass enable reg_write(ES8388_DACCONTROL20, 0x50); // right DAC to right mixer enable and LIN signal to right mixer enable 0db : bupass enable reg_write(ES8388_DACCONTROL21, 0xC0); //enable adc } else { reg_write(ES8388_DACCONTROL21, 0x80); //enable dac } data = reg_read(ES8388_DACCONTROL21); if (prev_data != data) { reg_write(ES8388_CHIPPOWER, 0xF0); //start state machine // reg_write(ES8388_ADDR, ES8388_CONTROL1, 0x16); // reg_write(ES8388_ADDR, ES8388_CONTROL2, 0x50); reg_write(ES8388_CHIPPOWER, 0x00); //start state machine } if (mode == ES_MODE_ADC || mode == ES_MODE_DAC_ADC || mode == ES_MODE_LINE) { reg_write(ES8388_ADCPOWER, 0x00); //power up adc and line in } if (mode == ES_MODE_DAC || mode == ES_MODE_DAC_ADC || mode == ES_MODE_LINE) { reg_write(ES8388_DACPOWER, 0x3c); //power up dac and line out es8388_set_voice_mute(RT_FALSE); } return res; } rt_err_t es8388_stop(enum es8388_mode mode) { int res = 0; if (mode == ES_MODE_LINE) { reg_write(ES8388_DACCONTROL21, 0x80); //enable dac reg_write(ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1, 0x09 LIN2&RIN2 reg_write(ES8388_DACCONTROL17, 0x90); // only left DAC to left mixer enable 0db reg_write(ES8388_DACCONTROL20, 0x90); // only right DAC to right mixer enable 0db return res; } if (mode == ES_MODE_DAC || mode == ES_MODE_DAC_ADC) { reg_write(ES8388_DACPOWER, 0x00); es8388_set_voice_mute(RT_TRUE); //res |= Es8388SetAdcDacVolume(ES_MODULE_DAC, -96, 5); // 0db // reg_write(ES8388_ADDR, ES8388_DACPOWER, 0xC0); //power down dac and line out } if (mode == ES_MODE_ADC || mode == ES_MODE_DAC_ADC) { // Es8388SetAdcDacVolume(ES_MODULE_ADC, -96, 5); // 0db reg_write(ES8388_ADCPOWER, 0xFF); //power down adc and line in } if (mode == ES_MODE_DAC_ADC) { reg_write(ES8388_DACCONTROL21, 0x9C); //disable mclk // reg_write(ES8388_CONTROL1, 0x00); // reg_write(ES8388_CONTROL2, 0x58); // reg_write(ES8388_CHIPPOWER, 0xF3); //stop state machine } return RT_EOK; } rt_err_t es8388_fmt_set(enum es8388_mode mode, enum es8388_format fmt) { rt_uint8_t reg = 0; if (mode == ES_MODE_ADC || mode == ES_MODE_DAC_ADC) { reg = reg_read(ES8388_ADCCONTROL4); reg = reg & 0xfc; reg_write(ES8388_ADCCONTROL4, reg | fmt); } if (mode == ES_MODE_DAC || mode == ES_MODE_DAC_ADC) { reg = reg_read(ES8388_DACCONTROL1); reg = reg & 0xf9; reg_write(ES8388_DACCONTROL1, reg | (fmt << 1)); } return RT_EOK; } void es8388_volume_set(rt_uint8_t volume) { uint32_t real_vol = 0; volume = 100 - volume; if (volume > 100) volume = 100; real_vol = 192 * volume / 100; reg_write(ES8388_DACCONTROL4, (rt_uint8_t)real_vol); // DAC L reg_write(ES8388_DACCONTROL5, (rt_uint8_t)real_vol); // DAC R } rt_uint8_t es8388_volume_get(void) { rt_uint8_t volume; volume = reg_read(ES8388_DACCONTROL24); if (volume == 0xff) { volume = 0; } else { volume *= 3; if (volume == 99) volume = 100; } return volume; } void es8388_pa_power(rt_bool_t enable) { rt_pin_mode(es_dev.pin, PIN_MODE_OUTPUT); if (enable) { rt_pin_write(es_dev.pin, PIN_HIGH); } else { rt_pin_write(es_dev.pin, PIN_LOW); } } void estest() { // reg_write(ES8388_DACCONTROL24, volume); reg_write(ES8388_ADCCONTROL1, 0x88); /* R9,左右通道PGA增益设置 */ reg_write(ES8388_ADCCONTROL2, 0x10); // 使用板载麦克风 // reg_write(ES8388_ADCCONTROL2,0x50); // 使用耳机麦克风 // reg_write(ES8388_ADCCONTROL3, 0xC0); reg_write(ES8388_ADCCONTROL8, 0x00); // LADCVOL reg_write(ES8388_ADCCONTROL9, 0x00); // RADCVOL reg_write(ES8388_DACCONTROL16, 0x1B); // LMIXSEL RMIXSEL reg_write(ES8388_DACCONTROL17, 0x40); // LI2LOVOL reg_write(ES8388_DACCONTROL24, 0x21); // LOUT1VOL reg_write(ES8388_DACCONTROL25, 0x21); // ROUT1VOL reg_write(ES8388_DACCONTROL24, 33); // LOUT1VOL balanced noise: 0x18 reg_write(ES8388_DACCONTROL25, 33); // ROUT1VOL balanced noise: 0x18 } MSH_CMD_EXPORT(estest, test mic loop)