|  | 
| 1 | 1 | /* | 
| 2 | 2 |  * Copyright (c) 2021 Nordic Semiconductor ASA | 
|  | 3 | + * Copyright (c) 2025 Croxel Inc | 
| 3 | 4 |  * | 
| 4 | 5 |  * SPDX-License-Identifier: Apache-2.0 | 
| 5 | 6 |  */ | 
| @@ -123,3 +124,190 @@ bool init_wm8731_i2c(void) | 
| 123 | 124 | } | 
| 124 | 125 | 
 | 
| 125 | 126 | #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 | +/* | 
|  | 195 | + * MAX9867_0E_LVL_LINE_IN_LEFT | 
|  | 196 | + * MAX9867_0F_LVL_LINE_IN_RIGHT | 
|  | 197 | + */ | 
|  | 198 | +#define MAX9867_LI_MUTE     (1 << 6) | 
|  | 199 | +#define MAX9867_LI_GAIN_POS 0 | 
|  | 200 | + | 
|  | 201 | +/* | 
|  | 202 | + * MAX9867_10_VOL_LEFT | 
|  | 203 | + * MAX9867_11_VOL_RIGHT | 
|  | 204 | + */ | 
|  | 205 | +#define MAX9867_VOL_POS 0 | 
|  | 206 | + | 
|  | 207 | +/* MAX9867_14_ADC_INPUT */ | 
|  | 208 | +#define MAX9867_MXINL_POS       6 | 
|  | 209 | +#define MAX9867_MXINR_POS       4 | 
|  | 210 | +#define MAX9867_MXIN_DIS        0 | 
|  | 211 | +#define MAX9867_MXIN_ANALOG_MIC 1 | 
|  | 212 | +#define MAX9867_MXIN_LINE       2 | 
|  | 213 | + | 
|  | 214 | +/* MAX9867_15_MIC */ | 
|  | 215 | +#define MAX9867_MICCLK_POS  6 | 
|  | 216 | +#define MAX9867_DIGMICL_POS 5 | 
|  | 217 | +#define MAX9867_DIGMICR_POS 4 | 
|  | 218 | + | 
|  | 219 | +/* MAX9867_16_MODE */ | 
|  | 220 | +#define MAX9867_HPMODE_POS          0 | 
|  | 221 | +#define MAX9867_STEREO_SE_CLICKLESS 4 | 
|  | 222 | +#define MAX9867_MONO_SE_CLICKLESS   5 | 
|  | 223 | + | 
|  | 224 | +/* MAX9867_17_PWR_SYS */ | 
|  | 225 | +#define MAX9867_SHDN  (1 << 7) | 
|  | 226 | +#define MAX9867_LNLEN (1 << 6) | 
|  | 227 | +#define MAX9867_LNREN (1 << 5) | 
|  | 228 | +#define MAX9867_DALEN (1 << 3) | 
|  | 229 | +#define MAX9867_DAREN (1 << 2) | 
|  | 230 | +#define MAX9867_ADLEN (1 << 1) | 
|  | 231 | +#define MAX9867_ADREN (1 << 0) | 
|  | 232 | + | 
|  | 233 | +bool init_max9867_i2c(void) | 
|  | 234 | +{ | 
|  | 235 | +	const struct device *const i2c_dev = DEVICE_DT_GET(MAX9867_I2C_NODE); | 
|  | 236 | + | 
|  | 237 | +	/* Initialization data for MAX9867 registers. */ | 
|  | 238 | +	static const uint8_t init[][2] = { | 
|  | 239 | +		/* Shutdown MAX9867 during configuration */ | 
|  | 240 | +		{MAX9867_17_PWR_SYS, 0x00}, | 
|  | 241 | +		/* | 
|  | 242 | +		 * Clear all regs to POR state. The MAX9867 does not not have an external | 
|  | 243 | +		 * reset signal. So manually writing 0, from (0x04 - 0x17) | 
|  | 244 | +		 */ | 
|  | 245 | +		{MAX9867_04_INT_EN, 0x00}, | 
|  | 246 | +		{MAX9867_05_SYS_CLK, 0x00}, | 
|  | 247 | +		{MAX9867_06_CLK_HIGH, 0x00}, | 
|  | 248 | +		{MAX9867_07_CLK_LOW, 0x00}, | 
|  | 249 | +		{MAX9867_08_DAI_FORMAT, 0x00}, | 
|  | 250 | +		{MAX9867_09_DAI_CLOCK, 0x00}, | 
|  | 251 | +		{MAX9867_0A_DIG_FILTER, 0x00}, | 
|  | 252 | +		{MAX9867_0B_SIDETONE, 0x00}, | 
|  | 253 | +		{MAX9867_0C_LVL_DAC, 0x00}, | 
|  | 254 | +		{MAX9867_0D_LVL_ADC, 0x00}, | 
|  | 255 | +		{MAX9867_0E_LVL_LINE_IN_LEFT, 0x00}, | 
|  | 256 | +		{MAX9867_0F_LVL_LINE_IN_RIGHT, 0x00}, | 
|  | 257 | +		{MAX9867_10_VOL_LEFT, 0x00}, | 
|  | 258 | +		{MAX9867_11_VOL_RIGHT, 0x00}, | 
|  | 259 | +		{MAX9867_12_MIC_GAIN_LEFT, 0x00}, | 
|  | 260 | +		{MAX9867_13_MIC_GAIN_RIGHT, 0x00}, | 
|  | 261 | +		{MAX9867_14_ADC_INPUT, 0x00}, | 
|  | 262 | +		{MAX9867_15_MIC, 0x00}, | 
|  | 263 | +		{MAX9867_16_MODE, 0x00}, | 
|  | 264 | +		{MAX9867_17_PWR_SYS, 0x00}, | 
|  | 265 | +		/* | 
|  | 266 | +		 * Select MCLK prescaler. PSCLK divides MCLK to generate a PCLK between 10MHz and | 
|  | 267 | +		 * 20MHz. Set prescaler, FREQ field is 0 for Normal or PLL mode, < 20MHz. | 
|  | 268 | +		 */ | 
|  | 269 | +		{MAX9867_05_SYS_CLK, 0x01 << MAX9867_PSCLK_POS}, | 
|  | 270 | +		/* Configure codec to generate 48kHz sampling frequency in master mode */ | 
|  | 271 | +		{MAX9867_06_CLK_HIGH, MAX9867_NI_UPPER_44p1KHZ}, | 
|  | 272 | +		{MAX9867_07_CLK_LOW, MAX9867_NI_LOWER_44p1KHZ}, | 
|  | 273 | +		{MAX9867_09_DAI_CLOCK, MAX9867_BSEL_PCLK_DIV8}, | 
|  | 274 | +		/* I2S format */ | 
|  | 275 | +		{MAX9867_08_DAI_FORMAT, MAX9867_MAS | MAX9867_DLY | MAX9867_HIZOFF}, | 
|  | 276 | +		/* */ | 
|  | 277 | +		{MAX9867_0A_DIG_FILTER, 0xA2}, | 
|  | 278 | +		/* Select Digital microphone input */ | 
|  | 279 | +		{MAX9867_15_MIC, ((0x1 << MAX9867_DIGMICR_POS))}, | 
|  | 280 | +		/* ADC level */ | 
|  | 281 | +		{MAX9867_0D_LVL_ADC, (3 << MAX9867_AVL_POS) | (3 << MAX9867_AVR_POS)}, | 
|  | 282 | +		/*Set line-in level, disconnect line input from playback amplifiers */ | 
|  | 283 | +		{MAX9867_0E_LVL_LINE_IN_LEFT, (0x0C << MAX9867_LI_GAIN_POS) | MAX9867_LI_MUTE}, | 
|  | 284 | +		{MAX9867_0F_LVL_LINE_IN_RIGHT, (0x0C << MAX9867_LI_GAIN_POS) | MAX9867_LI_MUTE}, | 
|  | 285 | +		/* Headphone mode */ | 
|  | 286 | +		{MAX9867_16_MODE, MAX9867_STEREO_SE_CLICKLESS << MAX9867_HPMODE_POS}, | 
|  | 287 | +		/* Set playback volume */ | 
|  | 288 | +		{MAX9867_10_VOL_LEFT, 0x04 << MAX9867_VOL_POS}, | 
|  | 289 | +		{MAX9867_11_VOL_RIGHT, 0x04 << MAX9867_VOL_POS}, | 
|  | 290 | +		/* Enable */ | 
|  | 291 | +		{MAX9867_17_PWR_SYS, MAX9867_SHDN | MAX9867_DALEN | MAX9867_DAREN | MAX9867_ADLEN}, | 
|  | 292 | +	}; | 
|  | 293 | + | 
|  | 294 | +	if (!device_is_ready(i2c_dev)) { | 
|  | 295 | +		printk("%s is not ready\n", i2c_dev->name); | 
|  | 296 | +		return false; | 
|  | 297 | +	} | 
|  | 298 | + | 
|  | 299 | +	for (int i = 0; i < ARRAY_SIZE(init); ++i) { | 
|  | 300 | +		const uint8_t *entry = init[i]; | 
|  | 301 | +		int ret; | 
|  | 302 | + | 
|  | 303 | +		ret = i2c_reg_write_byte(i2c_dev, MAX9867_I2C_ADDR, entry[0], entry[1]); | 
|  | 304 | +		if (ret < 0) { | 
|  | 305 | +			printk("Initialization step %d failed with %d\n", i, ret); | 
|  | 306 | +			return false; | 
|  | 307 | +		} | 
|  | 308 | +	} | 
|  | 309 | + | 
|  | 310 | +	return true; | 
|  | 311 | +} | 
|  | 312 | + | 
|  | 313 | +#endif /* DT_ON_BUS(MAX9867_NODE, i2c) */ | 
0 commit comments