1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include "codec.h"
9 #include <zephyr/sys/printk.h>
10 #include <zephyr/drivers/i2c.h>
11 
12 #if DT_ON_BUS(WM8731_NODE, i2c)
13 
14 #define WM8731_I2C_NODE DT_BUS(WM8731_NODE)
15 #define WM8731_I2C_ADDR DT_REG_ADDR(WM8731_NODE)
16 
init_wm8731_i2c(void)17 bool init_wm8731_i2c(void)
18 {
19 	const struct device *const i2c_dev = DEVICE_DT_GET(WM8731_I2C_NODE);
20 
21 	/* Initialization data for WM8731 registers. */
22 	static const uint8_t init[][2] = {
23 		/*
24 		 * Reset Register:
25 		 * [8:0] RESET = 0 (reset device)
26 		 */
27 		{ 0x1E, 0x00 },
28 		/*
29 		 * Power Down Control:
30 		 *   [7] POWEROFF = 0 (Disable POWEROFF)
31 		 *   [6] CLKOUTPD = 1 (Enable Power Down)
32 		 *   [5] OSCPDD = 0 (Disable Power Down)
33 		 *   [4] OUTPD = 1 (Enable Power Down)
34 		 *   [3] DACPD = 0 (Disable Power Down)
35 		 *   [2] ADCPD = 0 (Disable Power Down)
36 		 *   [1] MICPD = 1 (Enable Power Down)
37 		 *   [0] LINEINPD = 0 (Disable Power Down)
38 		 */
39 		{ 0x0C, 0x52 },
40 		/*
41 		 * Left Line In:
42 		 *   [8] LRINBOTH = 1 (Enable Simultaneous Load)
43 		 *   [7] LINMUTE = 0 (Disable Mute)
44 		 * [4:0] LINVOL = 0x07 (-24 dB)
45 		 */
46 		{ 0x01, 0x07 },
47 		/*
48 		 * Left Headphone Out:
49 		 *   [8] LRHPBOTH = 1 (Enable Simultaneous Load)
50 		 *   [7] LZCEN = 0 (Disable)
51 		 * [6:0] LHPVOL = 0x79 (0 dB)
52 		 */
53 		{ 0x05, 0x79 },
54 		/*
55 		 * Analogue Audio Path Control:
56 		 * [7:6] SIDEATT = 0 (-6 dB)
57 		 *   [5] SIDETONE = 0 (Disable Side Tone)
58 		 *   [4] DACSEL = 1 (Select DAC)
59 		 *   [3] BYPASS = 0 (Disable Bypass)
60 		 *   [2] INSEL = 0 (Line Input Select to ADC)
61 		 *   [1] MUTEMIC = 1 (Enable Mute)
62 		 *   [0] MICBOOST = 0 (Disable Boost)
63 		 */
64 		{ 0x08, 0x12 },
65 		/*
66 		 * Digital Audio Path Control:
67 		 *   [4] HPOR = 0 (clear offset)
68 		 *   [3] DACMU = 0 (Disable soft mute)
69 		 * [2:1] DEEMP = 0 (Disable)
70 		 *   [0] ADCHPD = 1 (Disable High Pass Filter)
71 		 */
72 		{ 0x0A, 0x01 },
73 		/*
74 		 * Digital Audio Interface Format:
75 		 *   [7] BCLKINV = 0 (Don't invert BCLK)
76 		 *   [6] MS = 0 (Enable Slave Mode)
77 		 *   [5] LRSWAP = 0 (Right Channel DAC Data Right)
78 		 *   [4] LRP = 1 (Right Channel DAC data when DACLRC high)
79 		 * [3:2] IWL = 0 (16 bits)
80 		 * [1:0] FORMAT = 2 (I2S Format)
81 		 */
82 		{ 0x0E, 0x12 },
83 		/*
84 		 * Sampling Control:
85 		 *   [7] CLKODIV2 = 0 (CLOCKOUT is Core Clock)
86 		 *   [6] CLKIDIV2 = 0 (Core Clock is MCLK)
87 		 * [5:2] SR = 0x8 (44.1 kHz)
88 		 *   [1] BOSR = 0 (256fs)
89 		 *   [0] USB/NORMAL = 0 (Normal mode)
90 		 */
91 		{ 0x10, 0x20 },
92 		/*
93 		 * Active Control:
94 		 * [0] ACTIVE = 1 (Active)
95 		 */
96 		{ 0x12, 0x01 },
97 		/*
98 		 * As recommended in WAN_0111, set the OUTPD bit in the Power
99 		 * Down Control register to 0 at the very end of the power-on
100 		 * sequence.
101 		 */
102 		{ 0x0C, 0x42 }
103 	};
104 
105 	if (!device_is_ready(i2c_dev)) {
106 		printk("%s is not ready\n", i2c_dev->name);
107 		return false;
108 	}
109 
110 	for (int i = 0; i < ARRAY_SIZE(init); ++i) {
111 		const uint8_t *entry = init[i];
112 		int ret;
113 
114 		ret = i2c_reg_write_byte(i2c_dev, WM8731_I2C_ADDR,
115 					 entry[0], entry[1]);
116 		if (ret < 0) {
117 			printk("Initialization step %d failed\n", i);
118 			return false;
119 		}
120 	}
121 
122 	return true;
123 }
124 
125 #endif /* DT_ON_BUS(WM8731_NODE, i2c) */
126