1 /*
2  * Copyright (c) 2023 Centralp
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ti_tas6422dac
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/audio/codec.h>
13 
14 #include "tas6422dac.h"
15 
16 #define LOG_LEVEL CONFIG_AUDIO_CODEC_LOG_LEVEL
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(tas6422dac);
19 
20 #define TAS6422DAC_MUTE_GPIO_SUPPORT DT_ANY_INST_HAS_PROP_STATUS_OKAY(mute_gpios)
21 
22 #define CODEC_OUTPUT_VOLUME_MAX (24 * 2)
23 #define CODEC_OUTPUT_VOLUME_MIN (-100 * 2)
24 
25 struct codec_driver_config {
26 	struct i2c_dt_spec bus;
27 #if TAS6422DAC_MUTE_GPIO_SUPPORT
28 	struct gpio_dt_spec mute_gpio;
29 #endif /* TAS6422DAC_MUTE_GPIO_SUPPORT */
30 };
31 
32 struct codec_driver_data {
33 };
34 
35 enum tas6422dac_channel_t {
36 	TAS6422DAC_CHANNEL_1,
37 	TAS6422DAC_CHANNEL_2,
38 	TAS6422DAC_CHANNEL_ALL,
39 	TAS6422DAC_CHANNEL_UNKNOWN,
40 };
41 
42 static enum tas6422dac_channel_t audio_to_tas6422dac_channel[] = {
43 	[AUDIO_CHANNEL_FRONT_LEFT] = TAS6422DAC_CHANNEL_1,
44 	[AUDIO_CHANNEL_FRONT_RIGHT] = TAS6422DAC_CHANNEL_2,
45 	[AUDIO_CHANNEL_LFE] = TAS6422DAC_CHANNEL_UNKNOWN,
46 	[AUDIO_CHANNEL_FRONT_CENTER] = TAS6422DAC_CHANNEL_UNKNOWN,
47 	[AUDIO_CHANNEL_REAR_LEFT] = TAS6422DAC_CHANNEL_1,
48 	[AUDIO_CHANNEL_REAR_RIGHT] = TAS6422DAC_CHANNEL_2,
49 	[AUDIO_CHANNEL_REAR_CENTER] = TAS6422DAC_CHANNEL_UNKNOWN,
50 	[AUDIO_CHANNEL_SIDE_LEFT] = TAS6422DAC_CHANNEL_1,
51 	[AUDIO_CHANNEL_SIDE_RIGHT] = TAS6422DAC_CHANNEL_2,
52 	[AUDIO_CHANNEL_ALL] = TAS6422DAC_CHANNEL_ALL,
53 };
54 
55 static void codec_mute_output(const struct device *dev, enum tas6422dac_channel_t channel);
56 static void codec_unmute_output(const struct device *dev, enum tas6422dac_channel_t channel);
57 static void codec_write_reg(const struct device *dev, uint8_t reg, uint8_t val);
58 static void codec_read_reg(const struct device *dev, uint8_t reg, uint8_t *val);
59 static void codec_soft_reset(const struct device *dev);
60 static int codec_configure_dai(const struct device *dev, audio_dai_cfg_t *cfg);
61 static void codec_configure_output(const struct device *dev);
62 static int codec_set_output_volume(const struct device *dev, enum tas6422dac_channel_t channel,
63 				   int vol);
64 
65 #if (LOG_LEVEL >= LOG_LEVEL_DEBUG)
66 static void codec_read_all_regs(const struct device *dev);
67 #define CODEC_DUMP_REGS(dev) codec_read_all_regs((dev))
68 #else
69 #define CODEC_DUMP_REGS(dev)
70 #endif
71 
codec_initialize(const struct device * dev)72 static int codec_initialize(const struct device *dev)
73 {
74 	const struct codec_driver_config *const dev_cfg = dev->config;
75 
76 	if (!device_is_ready(dev_cfg->bus.bus)) {
77 		LOG_ERR("I2C device not ready");
78 		return -ENODEV;
79 	}
80 
81 #if TAS6422DAC_MUTE_GPIO_SUPPORT
82 	if (!device_is_ready(dev_cfg->mute_gpio.port)) {
83 		LOG_ERR("GPIO device not ready");
84 		return -ENODEV;
85 	}
86 #endif /* TAS6422DAC_MUTE_GPIO_SUPPORT */
87 
88 	return 0;
89 }
90 
codec_configure(const struct device * dev,struct audio_codec_cfg * cfg)91 static int codec_configure(const struct device *dev, struct audio_codec_cfg *cfg)
92 {
93 	int ret;
94 
95 	if (cfg->dai_type != AUDIO_DAI_TYPE_I2S) {
96 		LOG_ERR("dai_type must be AUDIO_DAI_TYPE_I2S");
97 		return -EINVAL;
98 	}
99 
100 	codec_soft_reset(dev);
101 	ret = codec_configure_dai(dev, &cfg->dai_cfg);
102 	codec_configure_output(dev);
103 
104 	return ret;
105 }
106 
codec_start_output(const struct device * dev)107 static void codec_start_output(const struct device *dev)
108 {
109 	codec_unmute_output(dev, TAS6422DAC_CHANNEL_ALL);
110 
111 	CODEC_DUMP_REGS(dev);
112 }
113 
codec_stop_output(const struct device * dev)114 static void codec_stop_output(const struct device *dev)
115 {
116 	codec_mute_output(dev, TAS6422DAC_CHANNEL_ALL);
117 }
118 
codec_mute_output(const struct device * dev,enum tas6422dac_channel_t channel)119 static void codec_mute_output(const struct device *dev, enum tas6422dac_channel_t channel)
120 {
121 	uint8_t val;
122 
123 #if TAS6422DAC_MUTE_GPIO_SUPPORT
124 	const struct codec_driver_config *const dev_cfg = dev->config;
125 
126 	if (channel == TAS6422DAC_CHANNEL_ALL) {
127 		gpio_pin_configure_dt(&dev_cfg->mute_gpio, GPIO_OUTPUT_ACTIVE);
128 	}
129 #endif
130 
131 	codec_read_reg(dev, CH_STATE_CTRL_ADDR, &val);
132 	switch (channel) {
133 	case TAS6422DAC_CHANNEL_1:
134 		val &= ~CH_STATE_CTRL_CH1_STATE_CTRL_MASK;
135 		val |= CH_STATE_CTRL_CH1_STATE_CTRL(CH_STATE_CTRL_MUTE);
136 		break;
137 	case TAS6422DAC_CHANNEL_2:
138 		val &= ~CH_STATE_CTRL_CH2_STATE_CTRL_MASK;
139 		val |= CH_STATE_CTRL_CH2_STATE_CTRL(CH_STATE_CTRL_MUTE);
140 		break;
141 	case TAS6422DAC_CHANNEL_ALL:
142 		val &= ~(CH_STATE_CTRL_CH1_STATE_CTRL_MASK | CH_STATE_CTRL_CH2_STATE_CTRL_MASK);
143 		val |= CH_STATE_CTRL_CH1_STATE_CTRL(CH_STATE_CTRL_MUTE) |
144 		       CH_STATE_CTRL_CH2_STATE_CTRL(CH_STATE_CTRL_MUTE);
145 		break;
146 	case TAS6422DAC_CHANNEL_UNKNOWN:
147 	default:
148 		LOG_ERR("Invalid codec channel %u", channel);
149 		return;
150 	}
151 	codec_write_reg(dev, CH_STATE_CTRL_ADDR, val);
152 }
153 
codec_unmute_output(const struct device * dev,enum tas6422dac_channel_t channel)154 static void codec_unmute_output(const struct device *dev, enum tas6422dac_channel_t channel)
155 {
156 	uint8_t val;
157 
158 #if TAS6422DAC_MUTE_GPIO_SUPPORT
159 	const struct codec_driver_config *const dev_cfg = dev->config;
160 
161 	gpio_pin_configure_dt(&dev_cfg->mute_gpio, GPIO_OUTPUT_INACTIVE);
162 #endif
163 
164 	codec_read_reg(dev, CH_STATE_CTRL_ADDR, &val);
165 	switch (channel) {
166 	case TAS6422DAC_CHANNEL_1:
167 		val &= ~CH_STATE_CTRL_CH1_STATE_CTRL_MASK;
168 		val |= CH_STATE_CTRL_CH1_STATE_CTRL(CH_STATE_CTRL_PLAY);
169 		break;
170 	case TAS6422DAC_CHANNEL_2:
171 		val &= ~CH_STATE_CTRL_CH2_STATE_CTRL_MASK;
172 		val |= CH_STATE_CTRL_CH2_STATE_CTRL(CH_STATE_CTRL_PLAY);
173 		break;
174 	case TAS6422DAC_CHANNEL_ALL:
175 		val &= ~(CH_STATE_CTRL_CH1_STATE_CTRL_MASK | CH_STATE_CTRL_CH2_STATE_CTRL_MASK);
176 		val |= CH_STATE_CTRL_CH1_STATE_CTRL(CH_STATE_CTRL_PLAY) |
177 		       CH_STATE_CTRL_CH2_STATE_CTRL(CH_STATE_CTRL_PLAY);
178 		break;
179 	case TAS6422DAC_CHANNEL_UNKNOWN:
180 	default:
181 		LOG_ERR("Invalid codec channel %u", channel);
182 		return;
183 	}
184 	codec_write_reg(dev, CH_STATE_CTRL_ADDR, val);
185 }
186 
codec_set_property(const struct device * dev,audio_property_t property,audio_channel_t channel,audio_property_value_t val)187 static int codec_set_property(const struct device *dev, audio_property_t property,
188 			      audio_channel_t channel, audio_property_value_t val)
189 {
190 	enum tas6422dac_channel_t codec_channel = audio_to_tas6422dac_channel[channel];
191 
192 	if (codec_channel == TAS6422DAC_CHANNEL_UNKNOWN) {
193 		LOG_ERR("Invalid channel %u", channel);
194 		return -EINVAL;
195 	}
196 
197 	switch (property) {
198 	case AUDIO_PROPERTY_OUTPUT_VOLUME:
199 		return codec_set_output_volume(dev, codec_channel, val.vol);
200 
201 	case AUDIO_PROPERTY_OUTPUT_MUTE:
202 		if (val.mute) {
203 			codec_mute_output(dev, codec_channel);
204 		} else {
205 			codec_unmute_output(dev, codec_channel);
206 		}
207 		return 0;
208 
209 	default:
210 		break;
211 	}
212 
213 	return -EINVAL;
214 }
215 
codec_apply_properties(const struct device * dev)216 static int codec_apply_properties(const struct device *dev)
217 {
218 	/* nothing to do because there is nothing cached */
219 	return 0;
220 }
221 
codec_write_reg(const struct device * dev,uint8_t reg,uint8_t val)222 static void codec_write_reg(const struct device *dev, uint8_t reg, uint8_t val)
223 {
224 	const struct codec_driver_config *const dev_cfg = dev->config;
225 
226 	i2c_reg_write_byte_dt(&dev_cfg->bus, reg, val);
227 	LOG_DBG("%s WR REG:0x%02x VAL:0x%02x", dev->name, reg, val);
228 }
229 
codec_read_reg(const struct device * dev,uint8_t reg,uint8_t * val)230 static void codec_read_reg(const struct device *dev, uint8_t reg, uint8_t *val)
231 {
232 	const struct codec_driver_config *const dev_cfg = dev->config;
233 
234 	i2c_reg_read_byte_dt(&dev_cfg->bus, reg, val);
235 	LOG_DBG("%s RD REG:0x%02x VAL:0x%02x", dev->name, reg, *val);
236 }
237 
codec_soft_reset(const struct device * dev)238 static void codec_soft_reset(const struct device *dev)
239 {
240 	uint8_t val;
241 
242 	codec_read_reg(dev, MODE_CTRL_ADDR, &val);
243 	val |= MODE_CTRL_RESET;
244 	codec_write_reg(dev, MODE_CTRL_ADDR, val);
245 }
246 
codec_configure_dai(const struct device * dev,audio_dai_cfg_t * cfg)247 static int codec_configure_dai(const struct device *dev, audio_dai_cfg_t *cfg)
248 {
249 	uint8_t val;
250 
251 	codec_read_reg(dev, SAP_CTRL_ADDR, &val);
252 
253 	/* I2S mode */
254 	val &= ~SAP_CTRL_INPUT_FORMAT_MASK;
255 	val |= SAP_CTRL_INPUT_FORMAT(SAP_CTRL_INPUT_FORMAT_I2S);
256 
257 	/* Input sampling rate */
258 	val &= ~SAP_CTRL_INPUT_SAMPLING_RATE_MASK;
259 	switch (cfg->i2s.frame_clk_freq) {
260 	case AUDIO_PCM_RATE_44P1K:
261 		val |= SAP_CTRL_INPUT_SAMPLING_RATE(SAP_CTRL_INPUT_SAMPLING_RATE_44_1_KHZ);
262 		break;
263 	case AUDIO_PCM_RATE_48K:
264 		val |= SAP_CTRL_INPUT_SAMPLING_RATE(SAP_CTRL_INPUT_SAMPLING_RATE_48_KHZ);
265 		break;
266 	case AUDIO_PCM_RATE_96K:
267 		val |= SAP_CTRL_INPUT_SAMPLING_RATE(SAP_CTRL_INPUT_SAMPLING_RATE_96_KHZ);
268 		break;
269 	default:
270 		LOG_ERR("Invalid sampling rate %zu", cfg->i2s.frame_clk_freq);
271 		return -EINVAL;
272 	}
273 
274 	codec_write_reg(dev, SAP_CTRL_ADDR, val);
275 
276 	return 0;
277 }
278 
codec_configure_output(const struct device * dev)279 static void codec_configure_output(const struct device *dev)
280 {
281 	uint8_t val;
282 
283 	/* Overcurrent level = 1 */
284 	codec_read_reg(dev, MISC_CTRL_1_ADDR, &val);
285 	val &= ~MISC_CTRL_1_OC_CONTROL_MASK;
286 	codec_write_reg(dev, MISC_CTRL_1_ADDR, val);
287 
288 	/*
289 	 * PWM frequency = 10 fs
290 	 * Reduce PWM frequency to prevent component overtemperature
291 	 */
292 	codec_read_reg(dev, MISC_CTRL_2_ADDR, &val);
293 	val &= ~MISC_CTRL_2_PWM_FREQUENCY_MASK;
294 	val |= MISC_CTRL_2_PWM_FREQUENCY(MISC_CTRL_2_PWM_FREQUENCY_10_FS);
295 	codec_write_reg(dev, MISC_CTRL_2_ADDR, val);
296 }
297 
codec_set_output_volume(const struct device * dev,enum tas6422dac_channel_t channel,int vol)298 static int codec_set_output_volume(const struct device *dev, enum tas6422dac_channel_t channel,
299 				   int vol)
300 {
301 	uint8_t vol_val;
302 
303 	if ((vol > CODEC_OUTPUT_VOLUME_MAX) || (vol < CODEC_OUTPUT_VOLUME_MIN)) {
304 		LOG_ERR("Invalid volume %d.%d dB", vol >> 1, ((uint32_t)vol & 1) ? 5 : 0);
305 		return -EINVAL;
306 	}
307 
308 	vol_val = vol + 0xcf;
309 	switch (channel) {
310 	case TAS6422DAC_CHANNEL_1:
311 		codec_write_reg(dev, CH1_VOLUME_CTRL_ADDR, CH_VOLUME_CTRL_VOLUME(vol_val));
312 		break;
313 	case TAS6422DAC_CHANNEL_2:
314 		codec_write_reg(dev, CH2_VOLUME_CTRL_ADDR, CH_VOLUME_CTRL_VOLUME(vol_val));
315 		break;
316 	case TAS6422DAC_CHANNEL_ALL:
317 		codec_write_reg(dev, CH1_VOLUME_CTRL_ADDR, CH_VOLUME_CTRL_VOLUME(vol_val));
318 		codec_write_reg(dev, CH2_VOLUME_CTRL_ADDR, CH_VOLUME_CTRL_VOLUME(vol_val));
319 		break;
320 	case TAS6422DAC_CHANNEL_UNKNOWN:
321 	default:
322 		LOG_ERR("Invalid codec channel %u", channel);
323 		return -EINVAL;
324 	}
325 
326 	return 0;
327 }
328 
329 #if (LOG_LEVEL >= LOG_LEVEL_DEBUG)
codec_read_all_regs(const struct device * dev)330 static void codec_read_all_regs(const struct device *dev)
331 {
332 	uint8_t val;
333 
334 	codec_read_reg(dev, MODE_CTRL_ADDR, &val);
335 	codec_read_reg(dev, MISC_CTRL_1_ADDR, &val);
336 	codec_read_reg(dev, MISC_CTRL_2_ADDR, &val);
337 	codec_read_reg(dev, SAP_CTRL_ADDR, &val);
338 	codec_read_reg(dev, CH_STATE_CTRL_ADDR, &val);
339 	codec_read_reg(dev, CH1_VOLUME_CTRL_ADDR, &val);
340 	codec_read_reg(dev, CH2_VOLUME_CTRL_ADDR, &val);
341 	codec_read_reg(dev, DC_LDG_CTRL_1_ADDR, &val);
342 	codec_read_reg(dev, DC_LDG_CTRL_2_ADDR, &val);
343 	codec_read_reg(dev, DC_LDG_REPORT_1_ADDR, &val);
344 	codec_read_reg(dev, DC_LDG_REPORT_3_ADDR, &val);
345 	codec_read_reg(dev, CH_FAULTS_ADDR, &val);
346 	codec_read_reg(dev, GLOBAL_FAULTS_1_ADDR, &val);
347 	codec_read_reg(dev, GLOBAL_FAULTS_2_ADDR, &val);
348 	codec_read_reg(dev, WARNINGS_ADDR, &val);
349 	codec_read_reg(dev, PIN_CTRL_ADDR, &val);
350 	codec_read_reg(dev, MISC_CTRL_3_ADDR, &val);
351 	codec_read_reg(dev, ILIMIT_STATUS_ADDR, &val);
352 	codec_read_reg(dev, MISC_CTRL_4_ADDR, &val);
353 	codec_read_reg(dev, MISC_CTRL_5_ADDR, &val);
354 }
355 #endif
356 
357 static const struct audio_codec_api codec_driver_api = {
358 	.configure = codec_configure,
359 	.start_output = codec_start_output,
360 	.stop_output = codec_stop_output,
361 	.set_property = codec_set_property,
362 	.apply_properties = codec_apply_properties,
363 };
364 
365 #if TAS6422DAC_MUTE_GPIO_SUPPORT
366 #define TAS6422DAC_MUTE_GPIO_INIT(n) .mute_gpio = GPIO_DT_SPEC_INST_GET(n, mute_gpios)
367 #else
368 #define TAS6422DAC_MUTE_GPIO_INIT(n)
369 #endif /* TAS6422DAC_MUTE_GPIO_SUPPORT */
370 
371 #define TAS6422DAC_INIT(n)                                                                         \
372 	static struct codec_driver_data codec_device_data_##n;                                     \
373                                                                                                    \
374 	static struct codec_driver_config codec_device_config_##n = {                              \
375 		.bus = I2C_DT_SPEC_INST_GET(n), TAS6422DAC_MUTE_GPIO_INIT(n)};                     \
376                                                                                                    \
377 	DEVICE_DT_INST_DEFINE(n, codec_initialize, NULL, &codec_device_data_##n,                   \
378 			      &codec_device_config_##n, POST_KERNEL,                               \
379 			      CONFIG_AUDIO_CODEC_INIT_PRIORITY, &codec_driver_api);
380 
381 DT_INST_FOREACH_STATUS_OKAY(TAS6422DAC_INIT)
382