]>
Commit | Line | Data |
---|---|---|
9a7210f6 SG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * max98088.c -- MAX98088 ALSA SoC Audio driver | |
4 | * | |
5 | * Copyright 2010 Maxim Integrated Products | |
6 | * | |
7 | * Modified for U-Boot by Chih-Chung Chang (chihchung@chromium.org), | |
8 | * following the changes made in max98095.c | |
9 | */ | |
10 | ||
d678a59d | 11 | #include <common.h> |
9a7210f6 SG |
12 | #include <audio_codec.h> |
13 | #include <div64.h> | |
14 | #include <dm.h> | |
15 | #include <i2c.h> | |
16 | #include <i2s.h> | |
f7ae49fc | 17 | #include <log.h> |
9a7210f6 SG |
18 | #include <sound.h> |
19 | #include <asm/gpio.h> | |
9a7210f6 SG |
20 | #include "maxim_codec.h" |
21 | #include "max98088.h" | |
22 | ||
23 | /* codec mclk clock divider coefficients. Index 0 is reserved. */ | |
24 | static const int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, | |
25 | 44100, 48000, 88200, 96000}; | |
26 | ||
27 | /* | |
28 | * codec mclk clock divider coefficients based on sampling rate | |
29 | * | |
30 | * @param rate sampling rate | |
31 | * @param value address of indexvalue to be stored | |
32 | * | |
185f812c | 33 | * Return: 0 for success or negative error code. |
9a7210f6 SG |
34 | */ |
35 | static int rate_value(int rate, u8 *value) | |
36 | { | |
37 | int i; | |
38 | ||
39 | for (i = 1; i < ARRAY_SIZE(rate_table); i++) { | |
40 | if (rate_table[i] >= rate) { | |
41 | *value = i; | |
42 | return 0; | |
43 | } | |
44 | } | |
45 | *value = 1; | |
46 | ||
47 | return -EINVAL; | |
48 | } | |
49 | ||
50 | /* | |
51 | * Sets hw params for max98088 | |
52 | * | |
53 | * @priv: max98088 information pointer | |
54 | * @rate: Sampling rate | |
55 | * @bits_per_sample: Bits per sample | |
56 | * | |
185f812c | 57 | * Return: -EIO for error, 0 for success. |
9a7210f6 SG |
58 | */ |
59 | int max98088_hw_params(struct maxim_priv *priv, unsigned int rate, | |
60 | unsigned int bits_per_sample) | |
61 | { | |
62 | int error; | |
63 | u8 regval; | |
64 | ||
65 | switch (bits_per_sample) { | |
66 | case 16: | |
67 | error = maxim_bic_or(priv, M98088_REG_DAI1_FORMAT, | |
68 | M98088_DAI_WS, 0); | |
69 | break; | |
70 | case 24: | |
71 | error = maxim_bic_or(priv, M98088_REG_DAI1_FORMAT, | |
72 | M98088_DAI_WS, M98088_DAI_WS); | |
73 | break; | |
74 | default: | |
75 | debug("%s: Illegal bits per sample %d.\n", | |
76 | __func__, bits_per_sample); | |
77 | return -EINVAL; | |
78 | } | |
79 | ||
80 | error |= maxim_bic_or(priv, M98088_REG_PWR_SYS, M98088_SHDNRUN, 0); | |
81 | ||
82 | if (rate_value(rate, ®val)) { | |
83 | debug("%s: Failed to set sample rate to %d.\n", | |
84 | __func__, rate); | |
85 | return -EIO; | |
86 | } | |
87 | ||
88 | error |= maxim_bic_or(priv, M98088_REG_DAI1_CLKMODE, | |
89 | M98088_CLKMODE_MASK, regval << 4); | |
90 | priv->rate = rate; | |
91 | ||
92 | /* Update sample rate mode */ | |
93 | if (rate < 50000) | |
94 | error |= maxim_bic_or(priv, M98088_REG_DAI1_FILTERS, | |
95 | M98088_DAI_DHF, 0); | |
96 | else | |
97 | error |= maxim_bic_or(priv, M98088_REG_DAI1_FILTERS, | |
98 | M98088_DAI_DHF, M98088_DAI_DHF); | |
99 | ||
100 | error |= maxim_bic_or(priv, M98088_REG_PWR_SYS, M98088_SHDNRUN, | |
101 | M98088_SHDNRUN); | |
102 | ||
103 | if (error < 0) { | |
104 | debug("%s: Error setting hardware params.\n", __func__); | |
105 | return -EIO; | |
106 | } | |
107 | priv->rate = rate; | |
108 | ||
109 | return 0; | |
110 | } | |
111 | ||
112 | /* | |
113 | * Configures Audio interface system clock for the given frequency | |
114 | * | |
115 | * @priv: max98088 information | |
116 | * @freq: Sampling frequency in Hz | |
117 | * | |
185f812c | 118 | * Return: -EIO for error, 0 for success. |
9a7210f6 SG |
119 | */ |
120 | int max98088_set_sysclk(struct maxim_priv *priv, unsigned int freq) | |
121 | { | |
122 | int error = 0; | |
123 | u8 pwr; | |
124 | ||
125 | /* Requested clock frequency is already setup */ | |
126 | if (freq == priv->sysclk) | |
127 | return 0; | |
128 | ||
129 | /* | |
130 | * Setup clocks for slave mode, and using the PLL | |
131 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | |
132 | * 0x02 (when master clk is 20MHz to 30MHz).. | |
133 | */ | |
134 | if (freq >= 10000000 && freq < 20000000) { | |
135 | error = maxim_i2c_write(priv, M98088_REG_SYS_CLK, 0x10); | |
136 | } else if ((freq >= 20000000) && (freq < 30000000)) { | |
137 | error = maxim_i2c_write(priv, M98088_REG_SYS_CLK, 0x20); | |
138 | } else { | |
139 | debug("%s: Invalid master clock frequency\n", __func__); | |
140 | return -EIO; | |
141 | } | |
142 | ||
143 | error |= maxim_i2c_read(priv, M98088_REG_PWR_SYS, &pwr); | |
144 | if (pwr & M98088_SHDNRUN) { | |
145 | error |= maxim_bic_or(priv, M98088_REG_PWR_SYS, | |
146 | M98088_SHDNRUN, 0); | |
147 | error |= maxim_bic_or(priv, M98088_REG_PWR_SYS, | |
148 | M98088_SHDNRUN, M98088_SHDNRUN); | |
149 | } | |
150 | ||
151 | debug("%s: Clock at %uHz\n", __func__, freq); | |
152 | if (error < 0) | |
153 | return -EIO; | |
154 | ||
155 | priv->sysclk = freq; | |
156 | ||
157 | return 0; | |
158 | } | |
159 | ||
160 | /* | |
161 | * Sets Max98090 I2S format | |
162 | * | |
163 | * @priv: max98088 information | |
164 | * @fmt: i2S format - supports a subset of the options defined in i2s.h. | |
165 | * | |
185f812c | 166 | * Return: -EIO for error, 0 for success. |
9a7210f6 SG |
167 | */ |
168 | int max98088_set_fmt(struct maxim_priv *priv, int fmt) | |
169 | { | |
170 | u8 reg15val; | |
171 | u8 reg14val = 0; | |
172 | int error = 0; | |
173 | ||
174 | if (fmt == priv->fmt) | |
175 | return 0; | |
176 | ||
177 | priv->fmt = fmt; | |
178 | ||
179 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | |
180 | case SND_SOC_DAIFMT_CBS_CFS: | |
181 | /* Slave mode PLL */ | |
182 | error |= maxim_i2c_write(priv, M98088_REG_DAI1_CLKCFG_HI, | |
183 | 0x80); | |
184 | error |= maxim_i2c_write(priv, M98088_REG_DAI1_CLKCFG_LO, | |
185 | 0x00); | |
186 | break; | |
187 | case SND_SOC_DAIFMT_CBM_CFM: | |
188 | /* Set to master mode */ | |
189 | reg14val |= M98088_DAI_MAS; | |
190 | break; | |
191 | case SND_SOC_DAIFMT_CBS_CFM: | |
192 | case SND_SOC_DAIFMT_CBM_CFS: | |
193 | default: | |
194 | debug("%s: Clock mode unsupported\n", __func__); | |
195 | return -EINVAL; | |
196 | } | |
197 | ||
198 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | |
199 | case SND_SOC_DAIFMT_I2S: | |
200 | reg14val |= M98088_DAI_DLY; | |
201 | break; | |
202 | case SND_SOC_DAIFMT_LEFT_J: | |
203 | break; | |
204 | default: | |
205 | debug("%s: Unrecognized format.\n", __func__); | |
206 | return -EINVAL; | |
207 | } | |
208 | ||
209 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | |
210 | case SND_SOC_DAIFMT_NB_NF: | |
211 | break; | |
212 | case SND_SOC_DAIFMT_NB_IF: | |
213 | reg14val |= M98088_DAI_WCI; | |
214 | break; | |
215 | case SND_SOC_DAIFMT_IB_NF: | |
216 | reg14val |= M98088_DAI_BCI; | |
217 | break; | |
218 | case SND_SOC_DAIFMT_IB_IF: | |
219 | reg14val |= M98088_DAI_BCI | M98088_DAI_WCI; | |
220 | break; | |
221 | default: | |
222 | debug("%s: Unrecognized inversion settings.\n", __func__); | |
223 | return -EINVAL; | |
224 | } | |
225 | ||
226 | error |= maxim_bic_or(priv, M98088_REG_DAI1_FORMAT, | |
227 | M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | | |
228 | M98088_DAI_WCI, reg14val); | |
229 | reg15val = M98088_DAI_BSEL64; | |
230 | error |= maxim_i2c_write(priv, M98088_REG_DAI1_CLOCK, reg15val); | |
231 | ||
232 | if (error < 0) { | |
233 | debug("%s: Error setting i2s format.\n", __func__); | |
234 | return -EIO; | |
235 | } | |
236 | ||
237 | return 0; | |
238 | } | |
239 | ||
240 | /* | |
241 | * max98088_reset() - reset the audio codec | |
242 | * | |
243 | * @priv: max98088 information | |
185f812c | 244 | * Return: -EIO for error, 0 for success. |
9a7210f6 SG |
245 | */ |
246 | static int max98088_reset(struct maxim_priv *priv) | |
247 | { | |
248 | int ret, i; | |
249 | u8 val; | |
250 | ||
251 | /* | |
252 | * Reset to hardware default for registers, as there is not a soft | |
253 | * reset hardware control register. | |
254 | */ | |
255 | for (i = M98088_REG_IRQ_ENABLE; i <= M98088_REG_PWR_SYS; i++) { | |
256 | switch (i) { | |
257 | case M98088_REG_BIAS_CNTL: | |
258 | val = 0xf0; | |
259 | break; | |
260 | case M98088_REG_DAC_BIAS2: | |
261 | val = 0x0f; | |
262 | break; | |
263 | default: | |
264 | val = 0; | |
265 | } | |
266 | ret = maxim_i2c_write(priv, i, val); | |
267 | if (ret < 0) { | |
268 | debug("%s: Failed to reset: %d\n", __func__, ret); | |
269 | return ret; | |
270 | } | |
271 | } | |
272 | ||
273 | return 0; | |
274 | } | |
275 | ||
276 | /** | |
277 | * max98088_device_init() - Initialise max98088 codec device | |
278 | * | |
279 | * @priv: max98088 information | |
280 | * | |
185f812c | 281 | * Return: -EIO for error, 0 for success. |
9a7210f6 SG |
282 | */ |
283 | static int max98088_device_init(struct maxim_priv *priv) | |
284 | { | |
285 | unsigned char id; | |
286 | int error = 0; | |
287 | ||
9a7210f6 SG |
288 | /* reset the codec, the DSP core, and disable all interrupts */ |
289 | error = max98088_reset(priv); | |
290 | if (error != 0) { | |
291 | debug("Reset\n"); | |
292 | return error; | |
293 | } | |
294 | ||
295 | /* initialize private data */ | |
296 | priv->sysclk = -1U; | |
297 | priv->rate = -1U; | |
298 | priv->fmt = -1U; | |
299 | ||
300 | error = maxim_i2c_read(priv, M98088_REG_REV_ID, &id); | |
301 | if (error < 0) { | |
302 | debug("%s: Failure reading hardware revision: %d\n", | |
303 | __func__, id); | |
304 | return -EIO; | |
305 | } | |
306 | debug("%s: Hardware revision: %d\n", __func__, id); | |
307 | ||
308 | return 0; | |
309 | } | |
310 | ||
311 | static int max98088_setup_interface(struct maxim_priv *priv) | |
312 | { | |
313 | int error; | |
314 | ||
315 | /* Reading interrupt status to clear them */ | |
316 | error = maxim_i2c_write(priv, M98088_REG_PWR_SYS, M98088_PWRSV); | |
317 | error |= maxim_i2c_write(priv, M98088_REG_IRQ_ENABLE, 0x00); | |
318 | ||
319 | /* | |
320 | * initialize registers to hardware default configuring audio | |
321 | * interface2 to DAI1 | |
322 | */ | |
323 | error |= maxim_i2c_write(priv, M98088_REG_MIX_DAC, | |
324 | M98088_DAI1L_TO_DACL | M98088_DAI1R_TO_DACR); | |
325 | error |= maxim_i2c_write(priv, M98088_REG_BIAS_CNTL, 0xF0); | |
326 | error |= maxim_i2c_write(priv, M98088_REG_DAC_BIAS2, 0x0F); | |
327 | error |= maxim_i2c_write(priv, M98088_REG_DAI1_IOCFG, | |
328 | M98088_S2NORMAL | M98088_SDATA); | |
329 | ||
330 | /* | |
331 | * route DACL and DACR output to headphone and speakers | |
332 | * Ordering: DACL, DACR, DACL, DACR | |
333 | */ | |
334 | error |= maxim_i2c_write(priv, M98088_REG_MIX_SPK_LEFT, 1); | |
335 | error |= maxim_i2c_write(priv, M98088_REG_MIX_SPK_RIGHT, 1); | |
336 | error |= maxim_i2c_write(priv, M98088_REG_MIX_HP_LEFT, 1); | |
337 | error |= maxim_i2c_write(priv, M98088_REG_MIX_HP_RIGHT, 1); | |
338 | ||
339 | /* set volume: -12db */ | |
340 | error |= maxim_i2c_write(priv, M98088_REG_LVL_SPK_L, 0x0f); | |
341 | error |= maxim_i2c_write(priv, M98088_REG_LVL_SPK_R, 0x0f); | |
342 | ||
343 | /* set volume: -22db */ | |
344 | error |= maxim_i2c_write(priv, M98088_REG_LVL_HP_L, 0x0d); | |
345 | error |= maxim_i2c_write(priv, M98088_REG_LVL_HP_R, 0x0d); | |
346 | ||
347 | /* power enable */ | |
348 | error |= maxim_i2c_write(priv, M98088_REG_PWR_EN_OUT, | |
349 | M98088_HPLEN | M98088_HPREN | M98088_SPLEN | | |
350 | M98088_SPREN | M98088_DALEN | M98088_DAREN); | |
351 | if (error < 0) | |
352 | return -EIO; | |
353 | ||
354 | return 0; | |
355 | } | |
356 | ||
357 | static int max98088_do_init(struct maxim_priv *priv, int sampling_rate, | |
358 | int mclk_freq, int bits_per_sample) | |
359 | { | |
360 | int ret = 0; | |
361 | ||
362 | ret = max98088_setup_interface(priv); | |
363 | if (ret < 0) { | |
364 | debug("%s: max98088 setup interface failed\n", __func__); | |
365 | return ret; | |
366 | } | |
367 | ||
368 | ret = max98088_set_sysclk(priv, mclk_freq); | |
369 | if (ret < 0) { | |
370 | debug("%s: max98088 codec set sys clock failed\n", __func__); | |
371 | return ret; | |
372 | } | |
373 | ||
374 | ret = max98088_hw_params(priv, sampling_rate, bits_per_sample); | |
375 | ||
376 | if (ret == 0) { | |
377 | ret = max98088_set_fmt(priv, SND_SOC_DAIFMT_I2S | | |
378 | SND_SOC_DAIFMT_NB_NF | | |
379 | SND_SOC_DAIFMT_CBS_CFS); | |
380 | } | |
381 | ||
382 | return ret; | |
383 | } | |
384 | ||
385 | static int max98088_set_params(struct udevice *dev, int interface, int rate, | |
386 | int mclk_freq, int bits_per_sample, | |
387 | uint channels) | |
388 | { | |
389 | struct maxim_priv *priv = dev_get_priv(dev); | |
390 | ||
391 | return max98088_do_init(priv, rate, mclk_freq, bits_per_sample); | |
392 | } | |
393 | ||
394 | static int max98088_probe(struct udevice *dev) | |
395 | { | |
396 | struct maxim_priv *priv = dev_get_priv(dev); | |
397 | int ret; | |
398 | ||
399 | priv->dev = dev; | |
400 | ret = max98088_device_init(priv); | |
401 | if (ret < 0) { | |
402 | debug("%s: max98088 codec chip init failed\n", __func__); | |
403 | return ret; | |
404 | } | |
405 | ||
406 | return 0; | |
407 | } | |
408 | ||
409 | static const struct audio_codec_ops max98088_ops = { | |
410 | .set_params = max98088_set_params, | |
411 | }; | |
412 | ||
413 | static const struct udevice_id max98088_ids[] = { | |
414 | { .compatible = "maxim,max98088" }, | |
415 | { } | |
416 | }; | |
417 | ||
418 | U_BOOT_DRIVER(max98088) = { | |
419 | .name = "max98088", | |
420 | .id = UCLASS_AUDIO_CODEC, | |
421 | .of_match = max98088_ids, | |
422 | .probe = max98088_probe, | |
423 | .ops = &max98088_ops, | |
41575d8e | 424 | .priv_auto = sizeof(struct maxim_priv), |
9a7210f6 | 425 | }; |