1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Date           Author       Notes
7  * 2019-07-31     Zero-Free    first implementation
8  */
9 
10 #include <rtthread.h>
11 #include <rtdevice.h>
12 #include "drv_es8388.h"
13 
14 /* ES8388 address */
15 #define ES8388_ADDR 0x10  /*0x11:CE=1;0x10:CE=0*/
16 
17 struct es8388_device
18 {
19     struct rt_i2c_bus_device *i2c;
20     rt_uint16_t pin;
21 };
22 
23 static struct es8388_device es_dev = {0};
24 
reg_read(rt_uint8_t addr)25 static rt_uint16_t reg_read(rt_uint8_t addr)
26 {
27     struct rt_i2c_msg msg[2] = {0};
28     rt_uint8_t val = 0xff;
29 
30     RT_ASSERT(es_dev.i2c != RT_NULL);
31 
32     msg[0].addr  = ES8388_ADDR;
33     msg[0].flags = RT_I2C_WR;
34     msg[0].len   = 1;
35     msg[0].buf   = &addr;
36 
37     msg[1].addr  = ES8388_ADDR;
38     msg[1].flags = RT_I2C_RD;
39     msg[1].len   = 1;
40     msg[1].buf   = &val;
41 
42     if (rt_i2c_transfer(es_dev.i2c, msg, 2) != 2)
43     {
44         rt_kprintf("I2C read data failed, reg = 0x%02x. \n", addr);
45         return 0xff;
46     }
47 
48     return val;
49 }
50 
reg_write(rt_uint8_t addr,rt_uint8_t val)51 static void reg_write(rt_uint8_t addr, rt_uint8_t val)
52 {
53     struct rt_i2c_msg msgs[1] = {0};
54     rt_uint8_t buff[2] = {0};
55 
56     RT_ASSERT(es_dev.i2c != RT_NULL);
57 
58     buff[0] = addr;
59     buff[1] = val;
60 
61     msgs[0].addr  = ES8388_ADDR;
62     msgs[0].flags = RT_I2C_WR;
63     msgs[0].buf   = buff;
64     msgs[0].len   = 2;
65 
66     if (rt_i2c_transfer(es_dev.i2c, msgs, 1) != 1)
67     {
68         rt_kprintf("I2C write data failed, reg = 0x%2x. \n", addr);
69         return;
70     }
71 }
72 
es8388_set_adc_dac_volume(int mode,int volume,int dot)73 static int es8388_set_adc_dac_volume(int mode, int volume, int dot)
74 {
75     int res = 0;
76     if (volume < -96 || volume > 0)
77     {
78         if (volume < -96)
79             volume = -96;
80         else
81             volume = 0;
82     }
83     dot = (dot >= 5 ? 1 : 0);
84     volume = (-volume << 1) + dot;
85     if (mode == ES_MODE_ADC || mode == ES_MODE_DAC_ADC)
86     {
87         reg_write(ES8388_ADCCONTROL8, volume);
88         reg_write(ES8388_ADCCONTROL9, volume);  //ADC Right Volume=0db
89     }
90     if (mode == ES_MODE_DAC || mode == ES_MODE_DAC_ADC)
91     {
92         reg_write(ES8388_DACCONTROL5, volume);
93         reg_write(ES8388_DACCONTROL4, volume);
94     }
95     return res;
96 }
97 
es8388_set_voice_mute(rt_bool_t enable)98 void es8388_set_voice_mute(rt_bool_t enable)
99 {
100     rt_uint8_t reg = 0;
101 
102     reg = reg_read(ES8388_DACCONTROL3);
103     reg = reg & 0xFB;
104     reg_write(ES8388_DACCONTROL3, reg | (((int)enable) << 2));
105 }
106 
es8388_init(const char * i2c_name,rt_uint16_t pin)107 rt_err_t es8388_init(const char *i2c_name, rt_uint16_t pin)
108 {
109     es_dev.i2c = rt_i2c_bus_device_find(i2c_name);
110     if (es_dev.i2c == RT_NULL)
111     {
112         rt_kprintf("%s bus not found\n", i2c_name);
113         return -RT_ERROR;
114     }
115 
116     es_dev.pin = pin;
117 
118     reg_write(ES8388_DACCONTROL3, 0x04);  // 0x04 mute/0x00 unmute&ramp;DAC unmute and  disabled digital volume control soft ramp
119     /* Chip Control and Power Management */
120     reg_write(ES8388_CONTROL2, 0x50);
121     reg_write(ES8388_CHIPPOWER, 0x00); //normal all and power up all
122     reg_write(ES8388_MASTERMODE, 0x00); //TODO:CODEC IN I2S SLAVE MODE
123 
124     /* dac */
125     reg_write(ES8388_DACPOWER, 0xC0);  //disable DAC and disable Lout/Rout/1/2
126     reg_write(ES8388_CONTROL1, 0x12);  //Enfr=0,Play&Record Mode,(0x17-both of mic&paly)
127     // reg_write(ES8388_CONTROL2, 0);  //LPVrefBuf=0,Pdn_ana=0
128     reg_write(ES8388_DACCONTROL1, 0x18);//1a 0x18:16bit iis , 0x00:24
129     reg_write(ES8388_DACCONTROL2, 0x02);  //DACFsMode,SINGLE SPEED; DACFsRatio,256
130     reg_write(ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2
131     reg_write(ES8388_DACCONTROL17, 0x9C); // only left DAC to left mixer enable 0db
132     reg_write(ES8388_DACCONTROL20, 0x9C); // only right DAC to right mixer enable 0db
133     reg_write(ES8388_DACCONTROL21, 0x80); //set internal ADC and DAC use the same LRCK clock, ADC LRCK as internal LRCK
134     reg_write(ES8388_DACCONTROL23, 0x00);   //vroi=0
135     es8388_set_adc_dac_volume(ES_MODE_DAC, 0, 0);          // 0db
136 
137     reg_write(ES8388_DACPOWER, 0x3c);  //0x3c Enable DAC and Enable Lout/Rout/1/2
138     /* adc */
139     reg_write(ES8388_ADCPOWER, 0xFF);
140     reg_write(ES8388_ADCCONTROL1, 0xbb); // MIC Left and Right channel PGA gain
141     reg_write(ES8388_ADCCONTROL2, 0x00);  //0x00 LINSEL & RINSEL, LIN1/RIN1 as ADC Input; DSSEL,use one DS Reg11; DSR, LINPUT1-RINPUT1
142     reg_write(ES8388_ADCCONTROL3, 0x02);
143     reg_write(ES8388_ADCCONTROL4, 0x0d); // Left/Right data, Left/Right justified mode, Bits length, I2S format
144     reg_write(ES8388_ADCCONTROL5, 0x02);  //ADCFsMode,singel SPEED,RATIO=256
145     //ALC for Microphone
146     es8388_set_adc_dac_volume(ES_MODE_ADC, 0, 0);      // 0db
147     reg_write(ES8388_ADCPOWER, 0x09); //Power on ADC, Enable LIN&RIN, Power off MICBIAS, set int1lp to low power mode
148     /* enable es8388 PA */
149     es8388_pa_power(RT_TRUE);
150 
151     reg_write(ES8388_DACCONTROL24, 0x1E); // LOUT1VOL balanced noise: 0x18
152     reg_write(ES8388_DACCONTROL25, 0x1E); // ROUT1VOL balanced noise: 0x18
153 
154     return RT_EOK;
155 }
156 
es8388_start(enum es8388_mode mode)157 rt_err_t es8388_start(enum es8388_mode mode)
158 {
159     int res = 0;
160     rt_uint8_t prev_data = 0, data = 0;
161 
162     prev_data = reg_read(ES8388_DACCONTROL21);
163     if (mode == ES_MODE_LINE)
164     {
165         reg_write(ES8388_DACCONTROL16, 0x09); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2 by pass enable
166         reg_write(ES8388_DACCONTROL17, 0x50); // left DAC to left mixer enable  and  LIN signal to left mixer enable 0db  : bupass enable
167         reg_write(ES8388_DACCONTROL20, 0x50); // right DAC to right mixer enable  and  LIN signal to right mixer enable 0db : bupass enable
168         reg_write(ES8388_DACCONTROL21, 0xC0); //enable adc
169     }
170     else
171     {
172         reg_write(ES8388_DACCONTROL21, 0x80);   //enable dac
173     }
174     data = reg_read(ES8388_DACCONTROL21);
175 
176     if (prev_data != data)
177     {
178         reg_write(ES8388_CHIPPOWER, 0xF0);   //start state machine
179         // reg_write(ES8388_ADDR, ES8388_CONTROL1, 0x16);
180         // reg_write(ES8388_ADDR, ES8388_CONTROL2, 0x50);
181         reg_write(ES8388_CHIPPOWER, 0x00);   //start state machine
182     }
183     if (mode == ES_MODE_ADC || mode == ES_MODE_DAC_ADC || mode == ES_MODE_LINE)
184     {
185         reg_write(ES8388_ADCPOWER, 0x00);   //power up adc and line in
186     }
187     if (mode == ES_MODE_DAC || mode == ES_MODE_DAC_ADC || mode == ES_MODE_LINE)
188     {
189         reg_write(ES8388_DACPOWER, 0x3c);   //power up dac and line out
190         es8388_set_voice_mute(RT_FALSE);
191     }
192 
193     return res;
194 }
195 
es8388_stop(enum es8388_mode mode)196 rt_err_t es8388_stop(enum es8388_mode mode)
197 {
198     int res = 0;
199     if (mode == ES_MODE_LINE)
200     {
201         reg_write(ES8388_DACCONTROL21, 0x80); //enable dac
202         reg_write(ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2
203         reg_write(ES8388_DACCONTROL17, 0x90); // only left DAC to left mixer enable 0db
204         reg_write(ES8388_DACCONTROL20, 0x90); // only right DAC to right mixer enable 0db
205         return res;
206     }
207     if (mode == ES_MODE_DAC || mode == ES_MODE_DAC_ADC)
208     {
209         reg_write(ES8388_DACPOWER, 0x00);
210         es8388_set_voice_mute(RT_TRUE); //res |= Es8388SetAdcDacVolume(ES_MODULE_DAC, -96, 5);      // 0db
211         // reg_write(ES8388_ADDR, ES8388_DACPOWER, 0xC0);  //power down dac and line out
212     }
213     if (mode == ES_MODE_ADC || mode == ES_MODE_DAC_ADC)
214     {
215         // Es8388SetAdcDacVolume(ES_MODULE_ADC, -96, 5);      // 0db
216         reg_write(ES8388_ADCPOWER, 0xFF);  //power down adc and line in
217     }
218     if (mode == ES_MODE_DAC_ADC)
219     {
220         reg_write(ES8388_DACCONTROL21, 0x9C);   //disable mclk
221         // reg_write(ES8388_CONTROL1, 0x00);
222         // reg_write(ES8388_CONTROL2, 0x58);
223         // reg_write(ES8388_CHIPPOWER, 0xF3);  //stop state machine
224     }
225 
226     return RT_EOK;
227 }
228 
es8388_fmt_set(enum es8388_mode mode,enum es8388_format fmt)229 rt_err_t es8388_fmt_set(enum es8388_mode mode, enum es8388_format fmt)
230 {
231     rt_uint8_t reg = 0;
232 
233     if (mode == ES_MODE_ADC || mode == ES_MODE_DAC_ADC)
234     {
235         reg = reg_read(ES8388_ADCCONTROL4);
236         reg = reg & 0xfc;
237         reg_write(ES8388_ADCCONTROL4, reg | fmt);
238     }
239     if (mode == ES_MODE_DAC || mode == ES_MODE_DAC_ADC)
240     {
241         reg = reg_read(ES8388_DACCONTROL1);
242         reg = reg & 0xf9;
243         reg_write(ES8388_DACCONTROL1, reg | (fmt << 1));
244     }
245 
246     return RT_EOK;
247 }
248 
es8388_volume_set(rt_uint8_t volume)249 void es8388_volume_set(rt_uint8_t volume)
250 {
251     uint32_t real_vol = 0;
252     volume = 100 - volume;
253     if (volume > 100)
254         volume = 100;
255 
256     real_vol = 192 * volume / 100;
257 
258     reg_write(ES8388_DACCONTROL4, (rt_uint8_t)real_vol);  // DAC L
259     reg_write(ES8388_DACCONTROL5, (rt_uint8_t)real_vol);  // DAC R
260 }
261 
es8388_volume_get(void)262 rt_uint8_t es8388_volume_get(void)
263 {
264     rt_uint8_t volume;
265 
266     volume = reg_read(ES8388_DACCONTROL24);
267     if (volume == 0xff)
268     {
269         volume = 0;
270     }
271     else
272     {
273         volume *= 3;
274         if (volume == 99)
275             volume = 100;
276     }
277 
278     return volume;
279 }
280 
es8388_pa_power(rt_bool_t enable)281 void es8388_pa_power(rt_bool_t enable)
282 {
283     rt_pin_mode(es_dev.pin, PIN_MODE_OUTPUT);
284 
285     if (enable)
286     {
287         rt_pin_write(es_dev.pin, PIN_HIGH);
288     }
289     else
290     {
291         rt_pin_write(es_dev.pin, PIN_LOW);
292     }
293 }
294 
estest()295 void estest()
296 {
297 
298     // reg_write(ES8388_DACCONTROL24, volume);
299     reg_write(ES8388_ADCCONTROL1, 0x88);       /* R9,左右通道PGA增益设置 */
300     reg_write(ES8388_ADCCONTROL2, 0x10);  // 使用板载麦克风
301     // reg_write(ES8388_ADCCONTROL2,0x50);   // 使用耳机麦克风
302     // reg_write(ES8388_ADCCONTROL3, 0xC0);
303     reg_write(ES8388_ADCCONTROL8, 0x00);   // LADCVOL
304     reg_write(ES8388_ADCCONTROL9, 0x00);   // RADCVOL
305     reg_write(ES8388_DACCONTROL16, 0x1B);   // LMIXSEL RMIXSEL
306     reg_write(ES8388_DACCONTROL17, 0x40);   // LI2LOVOL
307 
308     reg_write(ES8388_DACCONTROL24, 0x21);   // LOUT1VOL
309     reg_write(ES8388_DACCONTROL25, 0x21);   // ROUT1VOL
310 
311     reg_write(ES8388_DACCONTROL24, 33); // LOUT1VOL balanced noise: 0x18
312     reg_write(ES8388_DACCONTROL25, 33); // ROUT1VOL balanced noise: 0x18
313 
314 
315 }
316 MSH_CMD_EXPORT(estest, test mic loop)
317