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