1e9f66f4fSSimon Glass // SPDX-License-Identifier: GPL-2.0+
25febe8dbSRajeshwari Shinde /*
35febe8dbSRajeshwari Shinde * max98095.c -- MAX98095 ALSA SoC Audio driver
45febe8dbSRajeshwari Shinde *
55febe8dbSRajeshwari Shinde * Copyright 2011 Maxim Integrated Products
65febe8dbSRajeshwari Shinde *
7e9f66f4fSSimon Glass * Modified for U-Boot by R. Chandrasekar (rcsekar@samsung.com)
85febe8dbSRajeshwari Shinde */
9150c5afeSSimon Glass
10150c5afeSSimon Glass #include <common.h>
11d6cadd59SSimon Glass #include <audio_codec.h>
12d6cadd59SSimon Glass #include <dm.h>
135febe8dbSRajeshwari Shinde #include <div64.h>
145febe8dbSRajeshwari Shinde #include <fdtdec.h>
155febe8dbSRajeshwari Shinde #include <i2c.h>
165febe8dbSRajeshwari Shinde #include <sound.h>
17a1efd49eSSimon Glass #include <asm/gpio.h>
185febe8dbSRajeshwari Shinde #include "i2s.h"
195febe8dbSRajeshwari Shinde #include "max98095.h"
205febe8dbSRajeshwari Shinde
215febe8dbSRajeshwari Shinde /* Index 0 is reserved. */
225febe8dbSRajeshwari Shinde int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000,
235febe8dbSRajeshwari Shinde 88200, 96000};
245febe8dbSRajeshwari Shinde
255febe8dbSRajeshwari Shinde /*
265febe8dbSRajeshwari Shinde * codec mclk clock divider coefficients based on sampling rate
275febe8dbSRajeshwari Shinde *
285febe8dbSRajeshwari Shinde * @param rate sampling rate
295febe8dbSRajeshwari Shinde * @param value address of indexvalue to be stored
305febe8dbSRajeshwari Shinde *
315febe8dbSRajeshwari Shinde * @return 0 for success or negative error code.
325febe8dbSRajeshwari Shinde */
rate_value(int rate,u8 * value)335febe8dbSRajeshwari Shinde static int rate_value(int rate, u8 *value)
345febe8dbSRajeshwari Shinde {
355febe8dbSRajeshwari Shinde int i;
365febe8dbSRajeshwari Shinde
375febe8dbSRajeshwari Shinde for (i = 1; i < ARRAY_SIZE(rate_table); i++) {
385febe8dbSRajeshwari Shinde if (rate_table[i] >= rate) {
395febe8dbSRajeshwari Shinde *value = i;
405febe8dbSRajeshwari Shinde return 0;
415febe8dbSRajeshwari Shinde }
425febe8dbSRajeshwari Shinde }
435febe8dbSRajeshwari Shinde *value = 1;
445febe8dbSRajeshwari Shinde
45*bc58184eSSimon Glass return -EINVAL;
465febe8dbSRajeshwari Shinde }
475febe8dbSRajeshwari Shinde
485febe8dbSRajeshwari Shinde /*
495febe8dbSRajeshwari Shinde * Sets hw params for max98095
505febe8dbSRajeshwari Shinde *
51a832a3e3SSimon Glass * @param priv max98095 information pointer
525febe8dbSRajeshwari Shinde * @param rate Sampling rate
535febe8dbSRajeshwari Shinde * @param bits_per_sample Bits per sample
545febe8dbSRajeshwari Shinde *
55*bc58184eSSimon Glass * @return 0 for success or negative error code.
565febe8dbSRajeshwari Shinde */
max98095_hw_params(struct maxim_priv * priv,enum en_max_audio_interface aif_id,unsigned int rate,unsigned int bits_per_sample)570ab6f0b3SSimon Glass static int max98095_hw_params(struct maxim_priv *priv,
586b40852dSDani Krishna Mohan enum en_max_audio_interface aif_id,
595febe8dbSRajeshwari Shinde unsigned int rate, unsigned int bits_per_sample)
605febe8dbSRajeshwari Shinde {
615febe8dbSRajeshwari Shinde u8 regval;
625febe8dbSRajeshwari Shinde int error;
636b40852dSDani Krishna Mohan unsigned short M98095_DAI_CLKMODE;
646b40852dSDani Krishna Mohan unsigned short M98095_DAI_FORMAT;
656b40852dSDani Krishna Mohan unsigned short M98095_DAI_FILTERS;
666b40852dSDani Krishna Mohan
676b40852dSDani Krishna Mohan if (aif_id == AIF1) {
686b40852dSDani Krishna Mohan M98095_DAI_CLKMODE = M98095_027_DAI1_CLKMODE;
696b40852dSDani Krishna Mohan M98095_DAI_FORMAT = M98095_02A_DAI1_FORMAT;
706b40852dSDani Krishna Mohan M98095_DAI_FILTERS = M98095_02E_DAI1_FILTERS;
716b40852dSDani Krishna Mohan } else {
726b40852dSDani Krishna Mohan M98095_DAI_CLKMODE = M98095_031_DAI2_CLKMODE;
736b40852dSDani Krishna Mohan M98095_DAI_FORMAT = M98095_034_DAI2_FORMAT;
746b40852dSDani Krishna Mohan M98095_DAI_FILTERS = M98095_038_DAI2_FILTERS;
756b40852dSDani Krishna Mohan }
765febe8dbSRajeshwari Shinde
775febe8dbSRajeshwari Shinde switch (bits_per_sample) {
785febe8dbSRajeshwari Shinde case 16:
790ab6f0b3SSimon Glass error = maxim_bic_or(priv, M98095_DAI_FORMAT, M98095_DAI_WS, 0);
805febe8dbSRajeshwari Shinde break;
815febe8dbSRajeshwari Shinde case 24:
820ab6f0b3SSimon Glass error = maxim_bic_or(priv, M98095_DAI_FORMAT, M98095_DAI_WS,
83a832a3e3SSimon Glass M98095_DAI_WS);
845febe8dbSRajeshwari Shinde break;
855febe8dbSRajeshwari Shinde default:
865febe8dbSRajeshwari Shinde debug("%s: Illegal bits per sample %d.\n",
875febe8dbSRajeshwari Shinde __func__, bits_per_sample);
88*bc58184eSSimon Glass return -EINVAL;
895febe8dbSRajeshwari Shinde }
905febe8dbSRajeshwari Shinde
915febe8dbSRajeshwari Shinde if (rate_value(rate, ®val)) {
925febe8dbSRajeshwari Shinde debug("%s: Failed to set sample rate to %d.\n",
935febe8dbSRajeshwari Shinde __func__, rate);
94*bc58184eSSimon Glass return -EINVAL;
955febe8dbSRajeshwari Shinde }
96a832a3e3SSimon Glass priv->rate = rate;
975febe8dbSRajeshwari Shinde
980ab6f0b3SSimon Glass error |= maxim_bic_or(priv, M98095_DAI_CLKMODE, M98095_CLKMODE_MASK,
99a832a3e3SSimon Glass regval);
1005febe8dbSRajeshwari Shinde
1015febe8dbSRajeshwari Shinde /* Update sample rate mode */
1025febe8dbSRajeshwari Shinde if (rate < 50000)
1030ab6f0b3SSimon Glass error |= maxim_bic_or(priv, M98095_DAI_FILTERS,
1045febe8dbSRajeshwari Shinde M98095_DAI_DHF, 0);
1055febe8dbSRajeshwari Shinde else
1060ab6f0b3SSimon Glass error |= maxim_bic_or(priv, M98095_DAI_FILTERS,
1075febe8dbSRajeshwari Shinde M98095_DAI_DHF, M98095_DAI_DHF);
1085febe8dbSRajeshwari Shinde
1095febe8dbSRajeshwari Shinde if (error < 0) {
1105febe8dbSRajeshwari Shinde debug("%s: Error setting hardware params.\n", __func__);
111*bc58184eSSimon Glass return -EIO;
1125febe8dbSRajeshwari Shinde }
1135febe8dbSRajeshwari Shinde
1145febe8dbSRajeshwari Shinde return 0;
1155febe8dbSRajeshwari Shinde }
1165febe8dbSRajeshwari Shinde
1175febe8dbSRajeshwari Shinde /*
1185febe8dbSRajeshwari Shinde * Configures Audio interface system clock for the given frequency
1195febe8dbSRajeshwari Shinde *
120a832a3e3SSimon Glass * @param priv max98095 information
1215febe8dbSRajeshwari Shinde * @param freq Sampling frequency in Hz
1225febe8dbSRajeshwari Shinde *
123*bc58184eSSimon Glass * @return 0 for success or negative error code.
1245febe8dbSRajeshwari Shinde */
max98095_set_sysclk(struct maxim_priv * priv,unsigned int freq)1250ab6f0b3SSimon Glass static int max98095_set_sysclk(struct maxim_priv *priv, unsigned int freq)
1265febe8dbSRajeshwari Shinde {
1275febe8dbSRajeshwari Shinde int error = 0;
1285febe8dbSRajeshwari Shinde
1295febe8dbSRajeshwari Shinde /* Requested clock frequency is already setup */
130a832a3e3SSimon Glass if (freq == priv->sysclk)
1315febe8dbSRajeshwari Shinde return 0;
1325febe8dbSRajeshwari Shinde
1335febe8dbSRajeshwari Shinde /* Setup clocks for slave mode, and using the PLL
1345febe8dbSRajeshwari Shinde * PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
1355febe8dbSRajeshwari Shinde * 0x02 (when master clk is 20MHz to 40MHz)..
1365febe8dbSRajeshwari Shinde * 0x03 (when master clk is 40MHz to 60MHz)..
1375febe8dbSRajeshwari Shinde */
1385febe8dbSRajeshwari Shinde if ((freq >= 10000000) && (freq < 20000000)) {
1390ab6f0b3SSimon Glass error = maxim_i2c_write(priv, M98095_026_SYS_CLK, 0x10);
1405febe8dbSRajeshwari Shinde } else if ((freq >= 20000000) && (freq < 40000000)) {
1410ab6f0b3SSimon Glass error = maxim_i2c_write(priv, M98095_026_SYS_CLK, 0x20);
1425febe8dbSRajeshwari Shinde } else if ((freq >= 40000000) && (freq < 60000000)) {
1430ab6f0b3SSimon Glass error = maxim_i2c_write(priv, M98095_026_SYS_CLK, 0x30);
1445febe8dbSRajeshwari Shinde } else {
1455febe8dbSRajeshwari Shinde debug("%s: Invalid master clock frequency\n", __func__);
146*bc58184eSSimon Glass return -EINVAL;
1475febe8dbSRajeshwari Shinde }
1485febe8dbSRajeshwari Shinde
1495febe8dbSRajeshwari Shinde debug("%s: Clock at %uHz\n", __func__, freq);
1505febe8dbSRajeshwari Shinde
1515febe8dbSRajeshwari Shinde if (error < 0)
152*bc58184eSSimon Glass return -EIO;
1535febe8dbSRajeshwari Shinde
154a832a3e3SSimon Glass priv->sysclk = freq;
1555febe8dbSRajeshwari Shinde return 0;
1565febe8dbSRajeshwari Shinde }
1575febe8dbSRajeshwari Shinde
1585febe8dbSRajeshwari Shinde /*
1595febe8dbSRajeshwari Shinde * Sets Max98095 I2S format
1605febe8dbSRajeshwari Shinde *
161a832a3e3SSimon Glass * @param priv max98095 information
1625febe8dbSRajeshwari Shinde * @param fmt i2S format - supports a subset of the options defined
1635febe8dbSRajeshwari Shinde * in i2s.h.
1645febe8dbSRajeshwari Shinde *
165*bc58184eSSimon Glass * @return 0 for success or negative error code.
1665febe8dbSRajeshwari Shinde */
max98095_set_fmt(struct maxim_priv * priv,int fmt,enum en_max_audio_interface aif_id)1670ab6f0b3SSimon Glass static int max98095_set_fmt(struct maxim_priv *priv, int fmt,
1686b40852dSDani Krishna Mohan enum en_max_audio_interface aif_id)
1695febe8dbSRajeshwari Shinde {
1705febe8dbSRajeshwari Shinde u8 regval = 0;
1715febe8dbSRajeshwari Shinde int error = 0;
1726b40852dSDani Krishna Mohan unsigned short M98095_DAI_CLKCFG_HI;
1736b40852dSDani Krishna Mohan unsigned short M98095_DAI_CLKCFG_LO;
1746b40852dSDani Krishna Mohan unsigned short M98095_DAI_FORMAT;
1756b40852dSDani Krishna Mohan unsigned short M98095_DAI_CLOCK;
1765febe8dbSRajeshwari Shinde
177a832a3e3SSimon Glass if (fmt == priv->fmt)
1785febe8dbSRajeshwari Shinde return 0;
1795febe8dbSRajeshwari Shinde
180a832a3e3SSimon Glass priv->fmt = fmt;
1815febe8dbSRajeshwari Shinde
1826b40852dSDani Krishna Mohan if (aif_id == AIF1) {
1836b40852dSDani Krishna Mohan M98095_DAI_CLKCFG_HI = M98095_028_DAI1_CLKCFG_HI;
1846b40852dSDani Krishna Mohan M98095_DAI_CLKCFG_LO = M98095_029_DAI1_CLKCFG_LO;
1856b40852dSDani Krishna Mohan M98095_DAI_FORMAT = M98095_02A_DAI1_FORMAT;
1866b40852dSDani Krishna Mohan M98095_DAI_CLOCK = M98095_02B_DAI1_CLOCK;
1876b40852dSDani Krishna Mohan } else {
1886b40852dSDani Krishna Mohan M98095_DAI_CLKCFG_HI = M98095_032_DAI2_CLKCFG_HI;
1896b40852dSDani Krishna Mohan M98095_DAI_CLKCFG_LO = M98095_033_DAI2_CLKCFG_LO;
1906b40852dSDani Krishna Mohan M98095_DAI_FORMAT = M98095_034_DAI2_FORMAT;
1916b40852dSDani Krishna Mohan M98095_DAI_CLOCK = M98095_035_DAI2_CLOCK;
1926b40852dSDani Krishna Mohan }
1936b40852dSDani Krishna Mohan
1945febe8dbSRajeshwari Shinde switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1955febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_CBS_CFS:
1965febe8dbSRajeshwari Shinde /* Slave mode PLL */
1970ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_DAI_CLKCFG_HI, 0x80);
1980ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_DAI_CLKCFG_LO, 0x00);
1995febe8dbSRajeshwari Shinde break;
2005febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_CBM_CFM:
2015febe8dbSRajeshwari Shinde /* Set to master mode */
2025febe8dbSRajeshwari Shinde regval |= M98095_DAI_MAS;
2035febe8dbSRajeshwari Shinde break;
2045febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_CBS_CFM:
2055febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_CBM_CFS:
2065febe8dbSRajeshwari Shinde default:
2075febe8dbSRajeshwari Shinde debug("%s: Clock mode unsupported\n", __func__);
208*bc58184eSSimon Glass return -EINVAL;
2095febe8dbSRajeshwari Shinde }
2105febe8dbSRajeshwari Shinde
2115febe8dbSRajeshwari Shinde switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
2125febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_I2S:
2135febe8dbSRajeshwari Shinde regval |= M98095_DAI_DLY;
2145febe8dbSRajeshwari Shinde break;
2155febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_LEFT_J:
2165febe8dbSRajeshwari Shinde break;
2175febe8dbSRajeshwari Shinde default:
2185febe8dbSRajeshwari Shinde debug("%s: Unrecognized format.\n", __func__);
219*bc58184eSSimon Glass return -EINVAL;
2205febe8dbSRajeshwari Shinde }
2215febe8dbSRajeshwari Shinde
2225febe8dbSRajeshwari Shinde switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
2235febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_NB_NF:
2245febe8dbSRajeshwari Shinde break;
2255febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_NB_IF:
2265febe8dbSRajeshwari Shinde regval |= M98095_DAI_WCI;
2275febe8dbSRajeshwari Shinde break;
2285febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_IB_NF:
2295febe8dbSRajeshwari Shinde regval |= M98095_DAI_BCI;
2305febe8dbSRajeshwari Shinde break;
2315febe8dbSRajeshwari Shinde case SND_SOC_DAIFMT_IB_IF:
2325febe8dbSRajeshwari Shinde regval |= M98095_DAI_BCI | M98095_DAI_WCI;
2335febe8dbSRajeshwari Shinde break;
2345febe8dbSRajeshwari Shinde default:
2355febe8dbSRajeshwari Shinde debug("%s: Unrecognized inversion settings.\n", __func__);
236*bc58184eSSimon Glass return -EINVAL;
2375febe8dbSRajeshwari Shinde }
2385febe8dbSRajeshwari Shinde
2390ab6f0b3SSimon Glass error |= maxim_bic_or(priv, M98095_DAI_FORMAT,
2406b40852dSDani Krishna Mohan M98095_DAI_MAS | M98095_DAI_DLY |
241a832a3e3SSimon Glass M98095_DAI_BCI | M98095_DAI_WCI, regval);
2425febe8dbSRajeshwari Shinde
2430ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_DAI_CLOCK, M98095_DAI_BSEL64);
2445febe8dbSRajeshwari Shinde
2455febe8dbSRajeshwari Shinde if (error < 0) {
2465febe8dbSRajeshwari Shinde debug("%s: Error setting i2s format.\n", __func__);
247*bc58184eSSimon Glass return -EIO;
2485febe8dbSRajeshwari Shinde }
2495febe8dbSRajeshwari Shinde
2505febe8dbSRajeshwari Shinde return 0;
2515febe8dbSRajeshwari Shinde }
2525febe8dbSRajeshwari Shinde
2535febe8dbSRajeshwari Shinde /*
2545febe8dbSRajeshwari Shinde * resets the audio codec
2555febe8dbSRajeshwari Shinde *
256a832a3e3SSimon Glass * @param priv Private data for driver
257*bc58184eSSimon Glass * @return 0 for success or negative error code.
2585febe8dbSRajeshwari Shinde */
max98095_reset(struct maxim_priv * priv)2590ab6f0b3SSimon Glass static int max98095_reset(struct maxim_priv *priv)
2605febe8dbSRajeshwari Shinde {
2615febe8dbSRajeshwari Shinde int i, ret;
2625febe8dbSRajeshwari Shinde
2635febe8dbSRajeshwari Shinde /*
2645febe8dbSRajeshwari Shinde * Gracefully reset the DSP core and the codec hardware in a proper
2655febe8dbSRajeshwari Shinde * sequence.
2665febe8dbSRajeshwari Shinde */
2670ab6f0b3SSimon Glass ret = maxim_i2c_write(priv, M98095_00F_HOST_CFG, 0);
2685febe8dbSRajeshwari Shinde if (ret != 0) {
2695febe8dbSRajeshwari Shinde debug("%s: Failed to reset DSP: %d\n", __func__, ret);
2705febe8dbSRajeshwari Shinde return ret;
2715febe8dbSRajeshwari Shinde }
2725febe8dbSRajeshwari Shinde
2730ab6f0b3SSimon Glass ret = maxim_i2c_write(priv, M98095_097_PWR_SYS, 0);
2745febe8dbSRajeshwari Shinde if (ret != 0) {
2755febe8dbSRajeshwari Shinde debug("%s: Failed to reset codec: %d\n", __func__, ret);
2765febe8dbSRajeshwari Shinde return ret;
2775febe8dbSRajeshwari Shinde }
2785febe8dbSRajeshwari Shinde
2795febe8dbSRajeshwari Shinde /*
2805febe8dbSRajeshwari Shinde * Reset to hardware default for registers, as there is not a soft
2815febe8dbSRajeshwari Shinde * reset hardware control register.
2825febe8dbSRajeshwari Shinde */
2835febe8dbSRajeshwari Shinde for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) {
2840ab6f0b3SSimon Glass ret = maxim_i2c_write(priv, i, 0);
2855febe8dbSRajeshwari Shinde if (ret < 0) {
2865febe8dbSRajeshwari Shinde debug("%s: Failed to reset: %d\n", __func__, ret);
2875febe8dbSRajeshwari Shinde return ret;
2885febe8dbSRajeshwari Shinde }
2895febe8dbSRajeshwari Shinde }
2905febe8dbSRajeshwari Shinde
2915febe8dbSRajeshwari Shinde return 0;
2925febe8dbSRajeshwari Shinde }
2935febe8dbSRajeshwari Shinde
2945febe8dbSRajeshwari Shinde /*
2955febe8dbSRajeshwari Shinde * Intialise max98095 codec device
2965febe8dbSRajeshwari Shinde *
297a832a3e3SSimon Glass * @param priv max98095 information
298*bc58184eSSimon Glass * @return 0 for success or negative error code.
2995febe8dbSRajeshwari Shinde */
max98095_device_init(struct maxim_priv * priv)3000ab6f0b3SSimon Glass static int max98095_device_init(struct maxim_priv *priv)
3015febe8dbSRajeshwari Shinde {
3025febe8dbSRajeshwari Shinde unsigned char id;
303*bc58184eSSimon Glass int ret;
3045febe8dbSRajeshwari Shinde
3055febe8dbSRajeshwari Shinde /* reset the codec, the DSP core, and disable all interrupts */
306*bc58184eSSimon Glass ret = max98095_reset(priv);
307*bc58184eSSimon Glass if (ret != 0) {
3085febe8dbSRajeshwari Shinde debug("Reset\n");
309*bc58184eSSimon Glass return ret;
3105febe8dbSRajeshwari Shinde }
3115febe8dbSRajeshwari Shinde
3125febe8dbSRajeshwari Shinde /* initialize private data */
313a832a3e3SSimon Glass priv->sysclk = -1U;
314a832a3e3SSimon Glass priv->rate = -1U;
315a832a3e3SSimon Glass priv->fmt = -1U;
3165febe8dbSRajeshwari Shinde
317*bc58184eSSimon Glass ret = maxim_i2c_read(priv, M98095_0FF_REV_ID, &id);
318*bc58184eSSimon Glass if (ret < 0) {
3195febe8dbSRajeshwari Shinde debug("%s: Failure reading hardware revision: %d\n",
3205febe8dbSRajeshwari Shinde __func__, id);
321*bc58184eSSimon Glass return ret;
3225febe8dbSRajeshwari Shinde }
3235febe8dbSRajeshwari Shinde debug("%s: Hardware revision: %c\n", __func__, (id - 0x40) + 'A');
3245febe8dbSRajeshwari Shinde
32582a27d2cSSimon Glass return 0;
32682a27d2cSSimon Glass }
32782a27d2cSSimon Glass
max98095_setup_interface(struct maxim_priv * priv,enum en_max_audio_interface aif_id)3280ab6f0b3SSimon Glass static int max98095_setup_interface(struct maxim_priv *priv,
32982a27d2cSSimon Glass enum en_max_audio_interface aif_id)
33082a27d2cSSimon Glass {
33182a27d2cSSimon Glass int error;
33282a27d2cSSimon Glass
3330ab6f0b3SSimon Glass error = maxim_i2c_write(priv, M98095_097_PWR_SYS, M98095_PWRSV);
3345febe8dbSRajeshwari Shinde
3355febe8dbSRajeshwari Shinde /*
3365febe8dbSRajeshwari Shinde * initialize registers to hardware default configuring audio
3375febe8dbSRajeshwari Shinde * interface2 to DAC
3385febe8dbSRajeshwari Shinde */
3396b40852dSDani Krishna Mohan if (aif_id == AIF1)
3400ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_048_MIX_DAC_LR,
3416b40852dSDani Krishna Mohan M98095_DAI1L_TO_DACL |
3426b40852dSDani Krishna Mohan M98095_DAI1R_TO_DACR);
3436b40852dSDani Krishna Mohan else
3440ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_048_MIX_DAC_LR,
3456b40852dSDani Krishna Mohan M98095_DAI2M_TO_DACL |
3466b40852dSDani Krishna Mohan M98095_DAI2M_TO_DACR);
3475febe8dbSRajeshwari Shinde
3480ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_092_PWR_EN_OUT,
3495febe8dbSRajeshwari Shinde M98095_SPK_SPREADSPECTRUM);
3500ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_04E_CFG_HP, M98095_HPNORMAL);
3516b40852dSDani Krishna Mohan if (aif_id == AIF1)
3520ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_02C_DAI1_IOCFG,
3535febe8dbSRajeshwari Shinde M98095_S1NORMAL | M98095_SDATA);
3546b40852dSDani Krishna Mohan else
3550ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_036_DAI2_IOCFG,
3565febe8dbSRajeshwari Shinde M98095_S2NORMAL | M98095_SDATA);
3575febe8dbSRajeshwari Shinde
3585febe8dbSRajeshwari Shinde /* take the codec out of the shut down */
3590ab6f0b3SSimon Glass error |= maxim_bic_or(priv, M98095_097_PWR_SYS, M98095_SHDNRUN,
3605febe8dbSRajeshwari Shinde M98095_SHDNRUN);
361a832a3e3SSimon Glass /*
362a832a3e3SSimon Glass * route DACL and DACR output to HO and Speakers
363a832a3e3SSimon Glass * Ordering: DACL, DACR, DACL, DACR
364a832a3e3SSimon Glass */
3650ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_050_MIX_SPK_LEFT, 0x01);
3660ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_051_MIX_SPK_RIGHT, 0x01);
3670ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_04C_MIX_HP_LEFT, 0x01);
3680ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_04D_MIX_HP_RIGHT, 0x01);
3695febe8dbSRajeshwari Shinde
3705febe8dbSRajeshwari Shinde /* power Enable */
3710ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_091_PWR_EN_OUT, 0xF3);
3725febe8dbSRajeshwari Shinde
3735febe8dbSRajeshwari Shinde /* set Volume */
3740ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_064_LVL_HP_L, 15);
3750ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_065_LVL_HP_R, 15);
3760ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_067_LVL_SPK_L, 16);
3770ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_068_LVL_SPK_R, 16);
3785febe8dbSRajeshwari Shinde
3795febe8dbSRajeshwari Shinde /* Enable DAIs */
3800ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_093_BIAS_CTRL, 0x30);
3816b40852dSDani Krishna Mohan if (aif_id == AIF1)
3820ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_096_PWR_DAC_CK, 0x01);
3836b40852dSDani Krishna Mohan else
3840ab6f0b3SSimon Glass error |= maxim_i2c_write(priv, M98095_096_PWR_DAC_CK, 0x07);
3855febe8dbSRajeshwari Shinde
3865febe8dbSRajeshwari Shinde if (error < 0)
387*bc58184eSSimon Glass return -EIO;
3885febe8dbSRajeshwari Shinde
3895febe8dbSRajeshwari Shinde return 0;
3905febe8dbSRajeshwari Shinde }
3915febe8dbSRajeshwari Shinde
max98095_do_init(struct maxim_priv * priv,enum en_max_audio_interface aif_id,int sampling_rate,int mclk_freq,int bits_per_sample)3920ab6f0b3SSimon Glass static int max98095_do_init(struct maxim_priv *priv,
3936b40852dSDani Krishna Mohan enum en_max_audio_interface aif_id,
3945febe8dbSRajeshwari Shinde int sampling_rate, int mclk_freq,
3955febe8dbSRajeshwari Shinde int bits_per_sample)
3965febe8dbSRajeshwari Shinde {
3975febe8dbSRajeshwari Shinde int ret = 0;
3985febe8dbSRajeshwari Shinde
39904660d64SSimon Glass ret = max98095_setup_interface(priv, aif_id);
4005febe8dbSRajeshwari Shinde if (ret < 0) {
401d6cadd59SSimon Glass debug("%s: max98095 setup interface failed\n", __func__);
4025febe8dbSRajeshwari Shinde return ret;
4035febe8dbSRajeshwari Shinde }
4045febe8dbSRajeshwari Shinde
40504660d64SSimon Glass ret = max98095_set_sysclk(priv, mclk_freq);
4065febe8dbSRajeshwari Shinde if (ret < 0) {
4075febe8dbSRajeshwari Shinde debug("%s: max98095 codec set sys clock failed\n", __func__);
4085febe8dbSRajeshwari Shinde return ret;
4095febe8dbSRajeshwari Shinde }
4105febe8dbSRajeshwari Shinde
41104660d64SSimon Glass ret = max98095_hw_params(priv, aif_id, sampling_rate,
4125febe8dbSRajeshwari Shinde bits_per_sample);
4135febe8dbSRajeshwari Shinde
4145febe8dbSRajeshwari Shinde if (ret == 0) {
41504660d64SSimon Glass ret = max98095_set_fmt(priv, SND_SOC_DAIFMT_I2S |
4165febe8dbSRajeshwari Shinde SND_SOC_DAIFMT_NB_NF |
4176b40852dSDani Krishna Mohan SND_SOC_DAIFMT_CBS_CFS,
4186b40852dSDani Krishna Mohan aif_id);
4195febe8dbSRajeshwari Shinde }
4205febe8dbSRajeshwari Shinde
4215febe8dbSRajeshwari Shinde return ret;
4225febe8dbSRajeshwari Shinde }
4235febe8dbSRajeshwari Shinde
max98095_set_params(struct udevice * dev,int interface,int rate,int mclk_freq,int bits_per_sample,uint channels)424d6cadd59SSimon Glass static int max98095_set_params(struct udevice *dev, int interface, int rate,
425d6cadd59SSimon Glass int mclk_freq, int bits_per_sample,
426d6cadd59SSimon Glass uint channels)
427d6cadd59SSimon Glass {
4280ab6f0b3SSimon Glass struct maxim_priv *priv = dev_get_priv(dev);
429d6cadd59SSimon Glass
430d6cadd59SSimon Glass return max98095_do_init(priv, interface, rate, mclk_freq,
431d6cadd59SSimon Glass bits_per_sample);
432d6cadd59SSimon Glass }
433d6cadd59SSimon Glass
max98095_probe(struct udevice * dev)434d6cadd59SSimon Glass static int max98095_probe(struct udevice *dev)
435d6cadd59SSimon Glass {
4360ab6f0b3SSimon Glass struct maxim_priv *priv = dev_get_priv(dev);
437d6cadd59SSimon Glass int ret;
438d6cadd59SSimon Glass
439d6cadd59SSimon Glass priv->dev = dev;
440d6cadd59SSimon Glass ret = max98095_device_init(priv);
441d6cadd59SSimon Glass if (ret < 0) {
442d6cadd59SSimon Glass debug("%s: max98095 codec chip init failed\n", __func__);
443d6cadd59SSimon Glass return ret;
444d6cadd59SSimon Glass }
445d6cadd59SSimon Glass
446d6cadd59SSimon Glass return 0;
447d6cadd59SSimon Glass }
448d6cadd59SSimon Glass
449d6cadd59SSimon Glass static const struct audio_codec_ops max98095_ops = {
450d6cadd59SSimon Glass .set_params = max98095_set_params,
451d6cadd59SSimon Glass };
452d6cadd59SSimon Glass
453d6cadd59SSimon Glass static const struct udevice_id max98095_ids[] = {
454d6cadd59SSimon Glass { .compatible = "maxim,max98095" },
455d6cadd59SSimon Glass { }
456d6cadd59SSimon Glass };
457d6cadd59SSimon Glass
458d6cadd59SSimon Glass U_BOOT_DRIVER(max98095) = {
459d6cadd59SSimon Glass .name = "max98095",
460d6cadd59SSimon Glass .id = UCLASS_AUDIO_CODEC,
461d6cadd59SSimon Glass .of_match = max98095_ids,
462d6cadd59SSimon Glass .probe = max98095_probe,
463d6cadd59SSimon Glass .ops = &max98095_ops,
4640ab6f0b3SSimon Glass .priv_auto_alloc_size = sizeof(struct maxim_priv),
465d6cadd59SSimon Glass };
466