Skip to content

Commit 3abeb04

Browse files
samples: drivers: i2s: echo: Add MAX9867 codec support
Add MAX9867 codec initialization support to the sample to later use for MAX32655FTHR support Signed-off-by: Anuj Pathak <anuj@croxel.com>
1 parent 09e51c8 commit 3abeb04

File tree

5 files changed

+209
-1
lines changed

5 files changed

+209
-1
lines changed

samples/drivers/i2s/echo/Kconfig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# Copyright (c) 2021 Nordic Semiconductor ASA
2+
# Copyright (c) 2025 Croxel Inc.
23
# SPDX-License-Identifier: Apache-2.0
34

45
source "Kconfig.zephyr"
56

67
config I2C
7-
default $(dt_compat_on_bus,$(DT_COMPAT_WOLFSON_WM8731),i2c)
8+
default $(dt_compat_on_bus,$(DT_COMPAT_WOLFSON_WM8731),i2c) \
9+
|| $(dt_compat_on_bus,$(DT_COMPAT_ADI_MAX9867),i2c)
810

911
config TOGGLE_ECHO_EFFECT_SW0
1012
bool "Toggle echo effect when pressing sw0"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright (c) 2025 Croxel Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# This binding has been added solely for the purpose of the overlay files used
5+
# in the drivers/i2s/output sample. That's why it is located in this sample source
6+
# directory. It can be moved and made available more widely if the need arises.
7+
8+
description: MAX9867 Audio CODEC
9+
10+
compatible: "adi,max9867"
11+
12+
include: i2c-device.yaml

samples/drivers/i2s/echo/src/codec.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2021 Nordic Semiconductor ASA
3+
* Copyright (c) 2021 Croxel Inc
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -123,3 +124,184 @@ bool init_wm8731_i2c(void)
123124
}
124125

125126
#endif /* DT_ON_BUS(WM8731_NODE, i2c) */
127+
128+
#if DT_ON_BUS(MAX9867_NODE, i2c)
129+
130+
#define MAX9867_I2C_NODE DT_BUS(MAX9867_NODE)
131+
#define MAX9867_I2C_ADDR DT_REG_ADDR(MAX9867_NODE)
132+
/* Register addresses */
133+
#define MAX9867_00_STATUS 0x00
134+
#define MAX9867_01_JACKSENSE 0x01
135+
#define MAX9867_02_AUX_HIGH 0x02
136+
#define MAX9867_03_AUX_LOW 0x03
137+
#define MAX9867_04_INT_EN 0x04
138+
#define MAX9867_05_SYS_CLK 0x05
139+
#define MAX9867_06_CLK_HIGH 0x06
140+
#define MAX9867_07_CLK_LOW 0x07
141+
#define MAX9867_08_DAI_FORMAT 0x08
142+
#define MAX9867_09_DAI_CLOCK 0x09
143+
#define MAX9867_0A_DIG_FILTER 0x0A
144+
#define MAX9867_0B_SIDETONE 0x0B
145+
#define MAX9867_0C_LVL_DAC 0x0C
146+
#define MAX9867_0D_LVL_ADC 0x0D
147+
#define MAX9867_0E_LVL_LINE_IN_LEFT 0x0E
148+
#define MAX9867_0F_LVL_LINE_IN_RIGHT 0x0F
149+
#define MAX9867_10_VOL_LEFT 0x10
150+
#define MAX9867_11_VOL_RIGHT 0x11
151+
#define MAX9867_12_MIC_GAIN_LEFT 0x12
152+
#define MAX9867_13_MIC_GAIN_RIGHT 0x13
153+
#define MAX9867_14_ADC_INPUT 0x14
154+
#define MAX9867_15_MIC 0x15
155+
#define MAX9867_16_MODE 0x16
156+
#define MAX9867_17_PWR_SYS 0x17
157+
#define MAX9867_FF_REV_ID 0xFF
158+
159+
/* MAX9867_04_INT_EN */
160+
#define MAX9867_ICLD (1 << 7)
161+
#define MAX9867_SDODLY (1 << 2)
162+
163+
/* MAX9867_05_SYS_CLK */
164+
#define MAX9867_PSCLK_POS 4
165+
166+
/* MAX9867_06_CLK_HIGH */
167+
#define MAX9867_PLL (1 << 7)
168+
#define MAX9867_NI_UPPER_8KHZ 0x10
169+
#define MAX9867_NI_UPPER_16KHZ 0x20
170+
#define MAX9867_NI_UPPER_24KHZ 0x30
171+
#define MAX9867_NI_UPPER_32KHZ 0x40
172+
#define MAX9867_NI_UPPER_44p1KHZ 0x58
173+
#define MAX9867_NI_UPPER_48KHZ 0x60
174+
175+
/* MAX9867_07_CLK_LOW */
176+
#define MAX9867_NI_LOWER_OTHER 0x00
177+
#define MAX9867_NI_LOWER_44p1KHZ 0x33
178+
179+
/* MAX9867_08_DAI_FORMAT */
180+
#define MAX9867_MAS (1 << 7)
181+
#define MAX9867_WCI (1 << 6)
182+
#define MAX9867_BCI (1 << 5)
183+
#define MAX9867_DLY (1 << 4)
184+
#define MAX9867_HIZOFF (1 << 3)
185+
#define MAX9867_TDM (1 << 2)
186+
187+
/* MAX9867_09_DAI_CLOCK */
188+
#define MAX9867_BSEL_PCLK_DIV8 0x06
189+
190+
/* MAX9867_0D_LVL_ADC */
191+
#define MAX9867_AVL_POS 4
192+
#define MAX9867_AVR_POS 0
193+
194+
/* MAX9867_0E_LVL_LINE_IN_LEFT
195+
* MAX9867_0F_LVL_LINE_IN_RIGHT */
196+
#define MAX9867_LI_MUTE (1 << 6)
197+
#define MAX9867_LI_GAIN_POS 0
198+
199+
/* MAX9867_10_VOL_LEFT
200+
* MAX9867_11_VOL_RIGHT */
201+
#define MAX9867_VOL_POS 0
202+
203+
/* MAX9867_14_ADC_INPUT */
204+
#define MAX9867_MXINL_POS 6
205+
#define MAX9867_MXINR_POS 4
206+
#define MAX9867_MXIN_DIS 0
207+
#define MAX9867_MXIN_ANALOG_MIC 1
208+
#define MAX9867_MXIN_LINE 2
209+
210+
/* MAX9867_15_MIC */
211+
#define MAX9867_MICCLK_POS 6
212+
#define MAX9867_DIGMICL_POS 5
213+
#define MAX9867_DIGMICR_POS 4
214+
215+
/* MAX9867_16_MODE */
216+
#define MAX9867_HPMODE_POS 0
217+
#define MAX9867_STEREO_SE_CLICKLESS 4
218+
#define MAX9867_MONO_SE_CLICKLESS 5
219+
220+
/* MAX9867_17_PWR_SYS */
221+
#define MAX9867_SHDN (1 << 7)
222+
#define MAX9867_LNLEN (1 << 6)
223+
#define MAX9867_LNREN (1 << 5)
224+
#define MAX9867_DALEN (1 << 3)
225+
#define MAX9867_DAREN (1 << 2)
226+
#define MAX9867_ADLEN (1 << 1)
227+
#define MAX9867_ADREN (1 << 0)
228+
229+
bool init_max9867_i2c(void)
230+
{
231+
const struct device *const i2c_dev = DEVICE_DT_GET(MAX9867_I2C_NODE);
232+
233+
/* Initialization data for MAX9867 registers. */
234+
static const uint8_t init[][2] = {
235+
/* Shutdown MAX9867 during configuration */
236+
{MAX9867_17_PWR_SYS, 0x00},
237+
/* Clear all regs to POR state. The MAX9867 does not not have an external
238+
* reset signal. So manually writing 0, from (0x04 - 0x17)
239+
*/
240+
{MAX9867_04_INT_EN, 0x00},
241+
{MAX9867_05_SYS_CLK, 0x00},
242+
{MAX9867_06_CLK_HIGH, 0x00},
243+
{MAX9867_07_CLK_LOW, 0x00},
244+
{MAX9867_08_DAI_FORMAT, 0x00},
245+
{MAX9867_09_DAI_CLOCK, 0x00},
246+
{MAX9867_0A_DIG_FILTER, 0x00},
247+
{MAX9867_0B_SIDETONE, 0x00},
248+
{MAX9867_0C_LVL_DAC, 0x00},
249+
{MAX9867_0D_LVL_ADC, 0x00},
250+
{MAX9867_0E_LVL_LINE_IN_LEFT, 0x00},
251+
{MAX9867_0F_LVL_LINE_IN_RIGHT, 0x00},
252+
{MAX9867_10_VOL_LEFT, 0x00},
253+
{MAX9867_11_VOL_RIGHT, 0x00},
254+
{MAX9867_12_MIC_GAIN_LEFT, 0x00},
255+
{MAX9867_13_MIC_GAIN_RIGHT, 0x00},
256+
{MAX9867_14_ADC_INPUT, 0x00},
257+
{MAX9867_15_MIC, 0x00},
258+
{MAX9867_16_MODE, 0x00},
259+
{MAX9867_17_PWR_SYS, 0x00},
260+
/* Select MCLK prescaler. PSCLK divides MCLK to generate a PCLK between 10MHz and
261+
* 20MHz. Set prescaler, FREQ field is 0 for Normal or PLL mode, < 20MHz.
262+
*/
263+
{MAX9867_05_SYS_CLK, 0x01 << MAX9867_PSCLK_POS},
264+
/* Configure codec to generate 48kHz sampling frequency in master mode */
265+
{MAX9867_06_CLK_HIGH, MAX9867_NI_UPPER_44p1KHZ},
266+
{MAX9867_07_CLK_LOW, MAX9867_NI_LOWER_44p1KHZ},
267+
{MAX9867_09_DAI_CLOCK, MAX9867_BSEL_PCLK_DIV8},
268+
/* I2S format */
269+
{MAX9867_08_DAI_FORMAT, MAX9867_MAS | MAX9867_DLY | MAX9867_HIZOFF},
270+
/* */
271+
{MAX9867_0A_DIG_FILTER, 0xA2},
272+
/* Select Digital microphone input */
273+
{MAX9867_15_MIC, ((0x1 << MAX9867_DIGMICR_POS))},
274+
/* ADC level */
275+
{MAX9867_0D_LVL_ADC, (3 << MAX9867_AVL_POS) | (3 << MAX9867_AVR_POS)},
276+
/*Set line-in level, disconnect line input from playback amplifiers */
277+
{MAX9867_0E_LVL_LINE_IN_LEFT, (0x0C << MAX9867_LI_GAIN_POS) | MAX9867_LI_MUTE},
278+
{MAX9867_0F_LVL_LINE_IN_RIGHT, (0x0C << MAX9867_LI_GAIN_POS) | MAX9867_LI_MUTE},
279+
/* Headphone mode */
280+
{MAX9867_16_MODE, MAX9867_STEREO_SE_CLICKLESS << MAX9867_HPMODE_POS},
281+
/* Set playback volume */
282+
{MAX9867_10_VOL_LEFT, 0x04 << MAX9867_VOL_POS},
283+
{MAX9867_11_VOL_RIGHT, 0x04 << MAX9867_VOL_POS},
284+
/* Enable */
285+
{MAX9867_17_PWR_SYS, MAX9867_SHDN | MAX9867_DALEN | MAX9867_DAREN | MAX9867_ADLEN},
286+
};
287+
288+
if (!device_is_ready(i2c_dev)) {
289+
printk("%s is not ready\n", i2c_dev->name);
290+
return false;
291+
}
292+
293+
for (int i = 0; i < ARRAY_SIZE(init); ++i) {
294+
const uint8_t *entry = init[i];
295+
int ret;
296+
297+
ret = i2c_reg_write_byte(i2c_dev, MAX9867_I2C_ADDR, entry[0], entry[1]);
298+
if (ret < 0) {
299+
printk("Initialization step %d failed with %d\n", i, ret);
300+
return false;
301+
}
302+
}
303+
304+
return true;
305+
}
306+
307+
#endif /* DT_ON_BUS(MAX9867_NODE, i2c) */

samples/drivers/i2s/echo/src/codec.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
/*
22
* Copyright (c) 2021 Nordic Semiconductor ASA
3+
* Copyright (c) 2025 Croxel Inc
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
67

78
#define WM8731_NODE DT_NODELABEL(wm8731)
9+
#define MAX9867_NODE DT_NODELABEL(max9867)
810

911
#if DT_ON_BUS(WM8731_NODE, i2c)
1012
bool init_wm8731_i2c(void);
1113
#endif
14+
15+
#if DT_ON_BUS(MAX9867_NODE, i2c)
16+
bool init_max9867_i2c(void);
17+
#endif

samples/drivers/i2s/echo/src/main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,12 @@ int main(void)
258258
}
259259
#endif
260260

261+
#if DT_ON_BUS(MAX9867_NODE, i2c)
262+
if (!init_max9867_i2c()) {
263+
return 0;
264+
}
265+
#endif
266+
261267
if (!init_buttons()) {
262268
return 0;
263269
}

0 commit comments

Comments
 (0)