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