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