]>
Commit | Line | Data |
---|---|---|
e9f66f4f | 1 | // SPDX-License-Identifier: GPL-2.0+ |
5febe8db RS |
2 | /* |
3 | * max98095.c -- MAX98095 ALSA SoC Audio driver | |
4 | * | |
5 | * Copyright 2011 Maxim Integrated Products | |
6 | * | |
e9f66f4f | 7 | * Modified for U-Boot by R. Chandrasekar ([email protected]) |
5febe8db | 8 | */ |
150c5afe | 9 | |
5febe8db | 10 | #include <common.h> |
d6cadd59 SG |
11 | #include <audio_codec.h> |
12 | #include <dm.h> | |
5febe8db RS |
13 | #include <div64.h> |
14 | #include <fdtdec.h> | |
15 | #include <i2c.h> | |
f7ae49fc | 16 | #include <log.h> |
5febe8db | 17 | #include <sound.h> |
a1efd49e | 18 | #include <asm/gpio.h> |
5febe8db RS |
19 | #include "i2s.h" |
20 | #include "max98095.h" | |
21 | ||
5febe8db RS |
22 | /* Index 0 is reserved. */ |
23 | int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, | |
24 | 88200, 96000}; | |
25 | ||
5febe8db RS |
26 | /* |
27 | * codec mclk clock divider coefficients based on sampling rate | |
28 | * | |
29 | * @param rate sampling rate | |
30 | * @param value address of indexvalue to be stored | |
31 | * | |
32 | * @return 0 for success or negative error code. | |
33 | */ | |
34 | static int rate_value(int rate, u8 *value) | |
35 | { | |
36 | int i; | |
37 | ||
38 | for (i = 1; i < ARRAY_SIZE(rate_table); i++) { | |
39 | if (rate_table[i] >= rate) { | |
40 | *value = i; | |
41 | return 0; | |
42 | } | |
43 | } | |
44 | *value = 1; | |
45 | ||
bc58184e | 46 | return -EINVAL; |
5febe8db RS |
47 | } |
48 | ||
49 | /* | |
50 | * Sets hw params for max98095 | |
51 | * | |
a832a3e3 | 52 | * @param priv max98095 information pointer |
5febe8db RS |
53 | * @param rate Sampling rate |
54 | * @param bits_per_sample Bits per sample | |
55 | * | |
bc58184e | 56 | * @return 0 for success or negative error code. |
5febe8db | 57 | */ |
0ab6f0b3 | 58 | static int max98095_hw_params(struct maxim_priv *priv, |
6b40852d DKM |
59 | enum en_max_audio_interface aif_id, |
60 | unsigned int rate, unsigned int bits_per_sample) | |
5febe8db RS |
61 | { |
62 | u8 regval; | |
63 | int error; | |
6b40852d DKM |
64 | unsigned short M98095_DAI_CLKMODE; |
65 | unsigned short M98095_DAI_FORMAT; | |
66 | unsigned short M98095_DAI_FILTERS; | |
67 | ||
68 | if (aif_id == AIF1) { | |
69 | M98095_DAI_CLKMODE = M98095_027_DAI1_CLKMODE; | |
70 | M98095_DAI_FORMAT = M98095_02A_DAI1_FORMAT; | |
71 | M98095_DAI_FILTERS = M98095_02E_DAI1_FILTERS; | |
72 | } else { | |
73 | M98095_DAI_CLKMODE = M98095_031_DAI2_CLKMODE; | |
74 | M98095_DAI_FORMAT = M98095_034_DAI2_FORMAT; | |
75 | M98095_DAI_FILTERS = M98095_038_DAI2_FILTERS; | |
76 | } | |
5febe8db RS |
77 | |
78 | switch (bits_per_sample) { | |
79 | case 16: | |
0ab6f0b3 | 80 | error = maxim_bic_or(priv, M98095_DAI_FORMAT, M98095_DAI_WS, 0); |
5febe8db RS |
81 | break; |
82 | case 24: | |
0ab6f0b3 SG |
83 | error = maxim_bic_or(priv, M98095_DAI_FORMAT, M98095_DAI_WS, |
84 | M98095_DAI_WS); | |
5febe8db RS |
85 | break; |
86 | default: | |
87 | debug("%s: Illegal bits per sample %d.\n", | |
6b40852d | 88 | __func__, bits_per_sample); |
bc58184e | 89 | return -EINVAL; |
5febe8db RS |
90 | } |
91 | ||
92 | if (rate_value(rate, ®val)) { | |
93 | debug("%s: Failed to set sample rate to %d.\n", | |
6b40852d | 94 | __func__, rate); |
bc58184e | 95 | return -EINVAL; |
5febe8db | 96 | } |
a832a3e3 | 97 | priv->rate = rate; |
5febe8db | 98 | |
0ab6f0b3 | 99 | error |= maxim_bic_or(priv, M98095_DAI_CLKMODE, M98095_CLKMODE_MASK, |
a832a3e3 | 100 | regval); |
5febe8db RS |
101 | |
102 | /* Update sample rate mode */ | |
103 | if (rate < 50000) | |
0ab6f0b3 | 104 | error |= maxim_bic_or(priv, M98095_DAI_FILTERS, |
a832a3e3 | 105 | M98095_DAI_DHF, 0); |
5febe8db | 106 | else |
0ab6f0b3 | 107 | error |= maxim_bic_or(priv, M98095_DAI_FILTERS, |
a832a3e3 | 108 | M98095_DAI_DHF, M98095_DAI_DHF); |
5febe8db RS |
109 | |
110 | if (error < 0) { | |
111 | debug("%s: Error setting hardware params.\n", __func__); | |
bc58184e | 112 | return -EIO; |
5febe8db RS |
113 | } |
114 | ||
115 | return 0; | |
116 | } | |
117 | ||
118 | /* | |
119 | * Configures Audio interface system clock for the given frequency | |
120 | * | |
a832a3e3 | 121 | * @param priv max98095 information |
5febe8db RS |
122 | * @param freq Sampling frequency in Hz |
123 | * | |
bc58184e | 124 | * @return 0 for success or negative error code. |
5febe8db | 125 | */ |
0ab6f0b3 | 126 | static int max98095_set_sysclk(struct maxim_priv *priv, unsigned int freq) |
5febe8db RS |
127 | { |
128 | int error = 0; | |
129 | ||
130 | /* Requested clock frequency is already setup */ | |
a832a3e3 | 131 | if (freq == priv->sysclk) |
5febe8db RS |
132 | return 0; |
133 | ||
134 | /* Setup clocks for slave mode, and using the PLL | |
135 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | |
136 | * 0x02 (when master clk is 20MHz to 40MHz).. | |
137 | * 0x03 (when master clk is 40MHz to 60MHz).. | |
138 | */ | |
139 | if ((freq >= 10000000) && (freq < 20000000)) { | |
0ab6f0b3 | 140 | error = maxim_i2c_write(priv, M98095_026_SYS_CLK, 0x10); |
5febe8db | 141 | } else if ((freq >= 20000000) && (freq < 40000000)) { |
0ab6f0b3 | 142 | error = maxim_i2c_write(priv, M98095_026_SYS_CLK, 0x20); |
5febe8db | 143 | } else if ((freq >= 40000000) && (freq < 60000000)) { |
0ab6f0b3 | 144 | error = maxim_i2c_write(priv, M98095_026_SYS_CLK, 0x30); |
5febe8db RS |
145 | } else { |
146 | debug("%s: Invalid master clock frequency\n", __func__); | |
bc58184e | 147 | return -EINVAL; |
5febe8db RS |
148 | } |
149 | ||
150 | debug("%s: Clock at %uHz\n", __func__, freq); | |
151 | ||
152 | if (error < 0) | |
bc58184e | 153 | return -EIO; |
5febe8db | 154 | |
a832a3e3 | 155 | priv->sysclk = freq; |
5febe8db RS |
156 | return 0; |
157 | } | |
158 | ||
159 | /* | |
160 | * Sets Max98095 I2S format | |
161 | * | |
a832a3e3 | 162 | * @param priv max98095 information |
5febe8db RS |
163 | * @param fmt i2S format - supports a subset of the options defined |
164 | * in i2s.h. | |
165 | * | |
bc58184e | 166 | * @return 0 for success or negative error code. |
5febe8db | 167 | */ |
0ab6f0b3 | 168 | static int max98095_set_fmt(struct maxim_priv *priv, int fmt, |
6b40852d | 169 | enum en_max_audio_interface aif_id) |
5febe8db RS |
170 | { |
171 | u8 regval = 0; | |
172 | int error = 0; | |
6b40852d DKM |
173 | unsigned short M98095_DAI_CLKCFG_HI; |
174 | unsigned short M98095_DAI_CLKCFG_LO; | |
175 | unsigned short M98095_DAI_FORMAT; | |
176 | unsigned short M98095_DAI_CLOCK; | |
5febe8db | 177 | |
a832a3e3 | 178 | if (fmt == priv->fmt) |
5febe8db RS |
179 | return 0; |
180 | ||
a832a3e3 | 181 | priv->fmt = fmt; |
5febe8db | 182 | |
6b40852d DKM |
183 | if (aif_id == AIF1) { |
184 | M98095_DAI_CLKCFG_HI = M98095_028_DAI1_CLKCFG_HI; | |
185 | M98095_DAI_CLKCFG_LO = M98095_029_DAI1_CLKCFG_LO; | |
186 | M98095_DAI_FORMAT = M98095_02A_DAI1_FORMAT; | |
187 | M98095_DAI_CLOCK = M98095_02B_DAI1_CLOCK; | |
188 | } else { | |
189 | M98095_DAI_CLKCFG_HI = M98095_032_DAI2_CLKCFG_HI; | |
190 | M98095_DAI_CLKCFG_LO = M98095_033_DAI2_CLKCFG_LO; | |
191 | M98095_DAI_FORMAT = M98095_034_DAI2_FORMAT; | |
192 | M98095_DAI_CLOCK = M98095_035_DAI2_CLOCK; | |
193 | } | |
194 | ||
5febe8db RS |
195 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
196 | case SND_SOC_DAIFMT_CBS_CFS: | |
197 | /* Slave mode PLL */ | |
0ab6f0b3 SG |
198 | error |= maxim_i2c_write(priv, M98095_DAI_CLKCFG_HI, 0x80); |
199 | error |= maxim_i2c_write(priv, M98095_DAI_CLKCFG_LO, 0x00); | |
5febe8db RS |
200 | break; |
201 | case SND_SOC_DAIFMT_CBM_CFM: | |
202 | /* Set to master mode */ | |
203 | regval |= M98095_DAI_MAS; | |
204 | break; | |
205 | case SND_SOC_DAIFMT_CBS_CFM: | |
206 | case SND_SOC_DAIFMT_CBM_CFS: | |
207 | default: | |
208 | debug("%s: Clock mode unsupported\n", __func__); | |
bc58184e | 209 | return -EINVAL; |
5febe8db RS |
210 | } |
211 | ||
212 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | |
213 | case SND_SOC_DAIFMT_I2S: | |
214 | regval |= M98095_DAI_DLY; | |
215 | break; | |
216 | case SND_SOC_DAIFMT_LEFT_J: | |
217 | break; | |
218 | default: | |
219 | debug("%s: Unrecognized format.\n", __func__); | |
bc58184e | 220 | return -EINVAL; |
5febe8db RS |
221 | } |
222 | ||
223 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | |
224 | case SND_SOC_DAIFMT_NB_NF: | |
225 | break; | |
226 | case SND_SOC_DAIFMT_NB_IF: | |
227 | regval |= M98095_DAI_WCI; | |
228 | break; | |
229 | case SND_SOC_DAIFMT_IB_NF: | |
230 | regval |= M98095_DAI_BCI; | |
231 | break; | |
232 | case SND_SOC_DAIFMT_IB_IF: | |
233 | regval |= M98095_DAI_BCI | M98095_DAI_WCI; | |
234 | break; | |
235 | default: | |
236 | debug("%s: Unrecognized inversion settings.\n", __func__); | |
bc58184e | 237 | return -EINVAL; |
5febe8db RS |
238 | } |
239 | ||
0ab6f0b3 | 240 | error |= maxim_bic_or(priv, M98095_DAI_FORMAT, |
a832a3e3 SG |
241 | M98095_DAI_MAS | M98095_DAI_DLY | |
242 | M98095_DAI_BCI | M98095_DAI_WCI, regval); | |
5febe8db | 243 | |
0ab6f0b3 | 244 | error |= maxim_i2c_write(priv, M98095_DAI_CLOCK, M98095_DAI_BSEL64); |
5febe8db RS |
245 | |
246 | if (error < 0) { | |
247 | debug("%s: Error setting i2s format.\n", __func__); | |
bc58184e | 248 | return -EIO; |
5febe8db RS |
249 | } |
250 | ||
251 | return 0; | |
252 | } | |
253 | ||
254 | /* | |
255 | * resets the audio codec | |
256 | * | |
a832a3e3 | 257 | * @param priv Private data for driver |
bc58184e | 258 | * @return 0 for success or negative error code. |
5febe8db | 259 | */ |
0ab6f0b3 | 260 | static int max98095_reset(struct maxim_priv *priv) |
5febe8db RS |
261 | { |
262 | int i, ret; | |
263 | ||
264 | /* | |
265 | * Gracefully reset the DSP core and the codec hardware in a proper | |
266 | * sequence. | |
267 | */ | |
0ab6f0b3 | 268 | ret = maxim_i2c_write(priv, M98095_00F_HOST_CFG, 0); |
5febe8db RS |
269 | if (ret != 0) { |
270 | debug("%s: Failed to reset DSP: %d\n", __func__, ret); | |
271 | return ret; | |
272 | } | |
273 | ||
0ab6f0b3 | 274 | ret = maxim_i2c_write(priv, M98095_097_PWR_SYS, 0); |
5febe8db RS |
275 | if (ret != 0) { |
276 | debug("%s: Failed to reset codec: %d\n", __func__, ret); | |
277 | return ret; | |
278 | } | |
279 | ||
280 | /* | |
281 | * Reset to hardware default for registers, as there is not a soft | |
282 | * reset hardware control register. | |
283 | */ | |
284 | for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) { | |
0ab6f0b3 | 285 | ret = maxim_i2c_write(priv, i, 0); |
5febe8db RS |
286 | if (ret < 0) { |
287 | debug("%s: Failed to reset: %d\n", __func__, ret); | |
288 | return ret; | |
289 | } | |
290 | } | |
291 | ||
292 | return 0; | |
293 | } | |
294 | ||
295 | /* | |
296 | * Intialise max98095 codec device | |
297 | * | |
a832a3e3 | 298 | * @param priv max98095 information |
bc58184e | 299 | * @return 0 for success or negative error code. |
5febe8db | 300 | */ |
0ab6f0b3 | 301 | static int max98095_device_init(struct maxim_priv *priv) |
5febe8db RS |
302 | { |
303 | unsigned char id; | |
bc58184e | 304 | int ret; |
5febe8db RS |
305 | |
306 | /* reset the codec, the DSP core, and disable all interrupts */ | |
bc58184e SG |
307 | ret = max98095_reset(priv); |
308 | if (ret != 0) { | |
5febe8db | 309 | debug("Reset\n"); |
bc58184e | 310 | return ret; |
5febe8db RS |
311 | } |
312 | ||
313 | /* initialize private data */ | |
a832a3e3 SG |
314 | priv->sysclk = -1U; |
315 | priv->rate = -1U; | |
316 | priv->fmt = -1U; | |
5febe8db | 317 | |
bc58184e SG |
318 | ret = maxim_i2c_read(priv, M98095_0FF_REV_ID, &id); |
319 | if (ret < 0) { | |
5febe8db | 320 | debug("%s: Failure reading hardware revision: %d\n", |
6b40852d | 321 | __func__, id); |
bc58184e | 322 | return ret; |
5febe8db RS |
323 | } |
324 | debug("%s: Hardware revision: %c\n", __func__, (id - 0x40) + 'A'); | |
325 | ||
82a27d2c SG |
326 | return 0; |
327 | } | |
328 | ||
0ab6f0b3 | 329 | static int max98095_setup_interface(struct maxim_priv *priv, |
82a27d2c SG |
330 | enum en_max_audio_interface aif_id) |
331 | { | |
332 | int error; | |
333 | ||
0ab6f0b3 | 334 | error = maxim_i2c_write(priv, M98095_097_PWR_SYS, M98095_PWRSV); |
5febe8db RS |
335 | |
336 | /* | |
337 | * initialize registers to hardware default configuring audio | |
338 | * interface2 to DAC | |
339 | */ | |
6b40852d | 340 | if (aif_id == AIF1) |
0ab6f0b3 | 341 | error |= maxim_i2c_write(priv, M98095_048_MIX_DAC_LR, |
6b40852d DKM |
342 | M98095_DAI1L_TO_DACL | |
343 | M98095_DAI1R_TO_DACR); | |
344 | else | |
0ab6f0b3 | 345 | error |= maxim_i2c_write(priv, M98095_048_MIX_DAC_LR, |
6b40852d DKM |
346 | M98095_DAI2M_TO_DACL | |
347 | M98095_DAI2M_TO_DACR); | |
5febe8db | 348 | |
0ab6f0b3 | 349 | error |= maxim_i2c_write(priv, M98095_092_PWR_EN_OUT, |
6b40852d | 350 | M98095_SPK_SPREADSPECTRUM); |
0ab6f0b3 | 351 | error |= maxim_i2c_write(priv, M98095_04E_CFG_HP, M98095_HPNORMAL); |
6b40852d | 352 | if (aif_id == AIF1) |
0ab6f0b3 | 353 | error |= maxim_i2c_write(priv, M98095_02C_DAI1_IOCFG, |
6b40852d DKM |
354 | M98095_S1NORMAL | M98095_SDATA); |
355 | else | |
0ab6f0b3 | 356 | error |= maxim_i2c_write(priv, M98095_036_DAI2_IOCFG, |
6b40852d | 357 | M98095_S2NORMAL | M98095_SDATA); |
5febe8db RS |
358 | |
359 | /* take the codec out of the shut down */ | |
0ab6f0b3 | 360 | error |= maxim_bic_or(priv, M98095_097_PWR_SYS, M98095_SHDNRUN, |
a832a3e3 SG |
361 | M98095_SHDNRUN); |
362 | /* | |
363 | * route DACL and DACR output to HO and Speakers | |
364 | * Ordering: DACL, DACR, DACL, DACR | |
365 | */ | |
0ab6f0b3 SG |
366 | error |= maxim_i2c_write(priv, M98095_050_MIX_SPK_LEFT, 0x01); |
367 | error |= maxim_i2c_write(priv, M98095_051_MIX_SPK_RIGHT, 0x01); | |
368 | error |= maxim_i2c_write(priv, M98095_04C_MIX_HP_LEFT, 0x01); | |
369 | error |= maxim_i2c_write(priv, M98095_04D_MIX_HP_RIGHT, 0x01); | |
5febe8db RS |
370 | |
371 | /* power Enable */ | |
0ab6f0b3 | 372 | error |= maxim_i2c_write(priv, M98095_091_PWR_EN_OUT, 0xF3); |
5febe8db RS |
373 | |
374 | /* set Volume */ | |
0ab6f0b3 SG |
375 | error |= maxim_i2c_write(priv, M98095_064_LVL_HP_L, 15); |
376 | error |= maxim_i2c_write(priv, M98095_065_LVL_HP_R, 15); | |
377 | error |= maxim_i2c_write(priv, M98095_067_LVL_SPK_L, 16); | |
378 | error |= maxim_i2c_write(priv, M98095_068_LVL_SPK_R, 16); | |
5febe8db RS |
379 | |
380 | /* Enable DAIs */ | |
0ab6f0b3 | 381 | error |= maxim_i2c_write(priv, M98095_093_BIAS_CTRL, 0x30); |
6b40852d | 382 | if (aif_id == AIF1) |
0ab6f0b3 | 383 | error |= maxim_i2c_write(priv, M98095_096_PWR_DAC_CK, 0x01); |
6b40852d | 384 | else |
0ab6f0b3 | 385 | error |= maxim_i2c_write(priv, M98095_096_PWR_DAC_CK, 0x07); |
5febe8db | 386 | |
5febe8db | 387 | if (error < 0) |
bc58184e | 388 | return -EIO; |
5febe8db RS |
389 | |
390 | return 0; | |
391 | } | |
392 | ||
0ab6f0b3 | 393 | static int max98095_do_init(struct maxim_priv *priv, |
6b40852d DKM |
394 | enum en_max_audio_interface aif_id, |
395 | int sampling_rate, int mclk_freq, | |
396 | int bits_per_sample) | |
5febe8db RS |
397 | { |
398 | int ret = 0; | |
399 | ||
04660d64 | 400 | ret = max98095_setup_interface(priv, aif_id); |
5febe8db | 401 | if (ret < 0) { |
d6cadd59 | 402 | debug("%s: max98095 setup interface failed\n", __func__); |
5febe8db RS |
403 | return ret; |
404 | } | |
405 | ||
04660d64 | 406 | ret = max98095_set_sysclk(priv, mclk_freq); |
5febe8db RS |
407 | if (ret < 0) { |
408 | debug("%s: max98095 codec set sys clock failed\n", __func__); | |
409 | return ret; | |
410 | } | |
411 | ||
04660d64 | 412 | ret = max98095_hw_params(priv, aif_id, sampling_rate, |
6b40852d | 413 | bits_per_sample); |
5febe8db RS |
414 | |
415 | if (ret == 0) { | |
04660d64 | 416 | ret = max98095_set_fmt(priv, SND_SOC_DAIFMT_I2S | |
6b40852d DKM |
417 | SND_SOC_DAIFMT_NB_NF | |
418 | SND_SOC_DAIFMT_CBS_CFS, | |
419 | aif_id); | |
5febe8db RS |
420 | } |
421 | ||
422 | return ret; | |
423 | } | |
424 | ||
d6cadd59 SG |
425 | static int max98095_set_params(struct udevice *dev, int interface, int rate, |
426 | int mclk_freq, int bits_per_sample, | |
427 | uint channels) | |
428 | { | |
0ab6f0b3 | 429 | struct maxim_priv *priv = dev_get_priv(dev); |
d6cadd59 SG |
430 | |
431 | return max98095_do_init(priv, interface, rate, mclk_freq, | |
432 | bits_per_sample); | |
433 | } | |
434 | ||
435 | static int max98095_probe(struct udevice *dev) | |
436 | { | |
0ab6f0b3 | 437 | struct maxim_priv *priv = dev_get_priv(dev); |
d6cadd59 SG |
438 | int ret; |
439 | ||
440 | priv->dev = dev; | |
441 | ret = max98095_device_init(priv); | |
442 | if (ret < 0) { | |
443 | debug("%s: max98095 codec chip init failed\n", __func__); | |
444 | return ret; | |
445 | } | |
446 | ||
447 | return 0; | |
448 | } | |
449 | ||
450 | static const struct audio_codec_ops max98095_ops = { | |
451 | .set_params = max98095_set_params, | |
452 | }; | |
453 | ||
454 | static const struct udevice_id max98095_ids[] = { | |
455 | { .compatible = "maxim,max98095" }, | |
456 | { } | |
457 | }; | |
458 | ||
459 | U_BOOT_DRIVER(max98095) = { | |
460 | .name = "max98095", | |
461 | .id = UCLASS_AUDIO_CODEC, | |
462 | .of_match = max98095_ids, | |
463 | .probe = max98095_probe, | |
464 | .ops = &max98095_ops, | |
0ab6f0b3 | 465 | .priv_auto_alloc_size = sizeof(struct maxim_priv), |
d6cadd59 | 466 | }; |