diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/Kconfig | 8 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/codecs/hdac_hdmi.c | 5 | ||||
-rwxr-xr-x | sound/soc/codecs/max9867.c | 546 | ||||
-rwxr-xr-x | sound/soc/codecs/max9867.h | 83 | ||||
-rw-r--r-- | sound/soc/codecs/max98926.c | 606 | ||||
-rw-r--r-- | sound/soc/codecs/max98926.h | 848 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_sai.c | 3 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 42 |
9 files changed, 2121 insertions, 24 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index bfbb6de..b414a92 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -79,7 +79,9 @@ config SND_SOC_ALL_CODECS select SND_SOC_MAX98090 if I2C select SND_SOC_MAX98095 if I2C select SND_SOC_MAX98357A if GPIOLIB + select SND_SOC_MAX9867 if I2C select SND_SOC_MAX98925 if I2C + select SND_SOC_MAX98926 if I2C select SND_SOC_MAX9850 if I2C select SND_SOC_MAX9768 if I2C select SND_SOC_MAX9877 if I2C @@ -518,9 +520,15 @@ config SND_SOC_MAX98095 config SND_SOC_MAX98357A tristate +config SND_SOC_MAX9867 + tristate + config SND_SOC_MAX98925 tristate +config SND_SOC_MAX98926 + tristate + config SND_SOC_MAX9850 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 9acd777..d10418c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -74,7 +74,9 @@ snd-soc-max98088-objs := max98088.o snd-soc-max98090-objs := max98090.o snd-soc-max98095-objs := max98095.o snd-soc-max98357a-objs := max98357a.o +snd-soc-max9867-objs := max9867.o snd-soc-max98925-objs := max98925.o +snd-soc-max98926-objs := max98926.o snd-soc-max9850-objs := max9850.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o @@ -280,7 +282,9 @@ obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o +obj-$(CONFIG_SND_SOC_MAX9867) += snd-soc-max9867.o obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o +obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index cb0b036..26f9459 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -303,7 +303,6 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, if (ret < 0) return ret; - dip = (u8 *)&frame; break; case DRM_ELD_CONN_TYPE_DP: @@ -332,9 +331,9 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, /* Fill infoframe. Index auto-incremented */ hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); if (conn_type == DRM_ELD_CONN_TYPE_HDMI) { - for (i = 0; i < sizeof(frame); i++) + for (i = 0; i < sizeof(buffer); i++) snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, - AC_VERB_SET_HDMI_DIP_DATA, dip[i]); + AC_VERB_SET_HDMI_DIP_DATA, buffer[i]); } else { for (i = 0; i < sizeof(dp_ai); i++) snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c new file mode 100755 index 0000000..2a22fdd --- /dev/null +++ b/sound/soc/codecs/max9867.c @@ -0,0 +1,546 @@ +/* + * max9867.c -- max9867 ALSA SoC Audio driver + * + * Copyright 2013-15 Maxim Integrated Products + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/tlv.h> +#include "max9867.h" + +static const char *const max9867_spmode[] = { + "Stereo Diff", "Mono Diff", + "Stereo Cap", "Mono Cap", + "Stereo Single", "Mono Single", + "Stereo Single Fast", "Mono Single Fast" +}; +static const char *const max9867_sidetone_text[] = { + "None", "Left", "Right", "LeftRight", "LeftRightDiv2", +}; +static const char *const max9867_filter_text[] = {"IIR", "FIR"}; + +static SOC_ENUM_SINGLE_DECL(max9867_filter, MAX9867_CODECFLTR, 7, + max9867_filter_text); +static SOC_ENUM_SINGLE_DECL(max9867_spkmode, MAX9867_MODECONFIG, 0, + max9867_spmode); +static SOC_ENUM_SINGLE_DECL(max9867_sidetone, MAX9867_DACGAIN, 6, + max9867_sidetone_text); +static DECLARE_TLV_DB_SCALE(max9860_capture_tlv, -600, 200, 0); +static DECLARE_TLV_DB_SCALE(max9860_mic_tlv, 2000, 100, 1); +static DECLARE_TLV_DB_SCALE(max9860_adc_left_tlv, -1200, 100, 1); +static DECLARE_TLV_DB_SCALE(max9860_adc_right_tlv, -1200, 100, 1); +static const unsigned int max98088_micboost_tlv[] = { + TLV_DB_RANGE_HEAD(2), + 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), + 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), +}; + +static const struct snd_kcontrol_new max9867_snd_controls[] = { + SOC_DOUBLE_R("Master Playback Volume", MAX9867_LEFTVOL, + MAX9867_RIGHTVOL, 0, 63, 1), + SOC_DOUBLE_R_TLV("Capture Volume", MAX9867_LEFTMICGAIN, + MAX9867_RIGHTMICGAIN, + 0, 15, 1, max9860_capture_tlv), + SOC_DOUBLE_R_TLV("Mic Volume", MAX9867_LEFTMICGAIN, + MAX9867_RIGHTMICGAIN, 0, 31, 1, max9860_mic_tlv), + SOC_DOUBLE_R_TLV("Mic Boost Volume", MAX9867_LEFTMICGAIN, + MAX9867_RIGHTMICGAIN, 5, 3, 0, max98088_micboost_tlv), + SOC_ENUM("Digital Sidetone Src", max9867_sidetone), + SOC_SINGLE("Sidetone Volume", MAX9867_DACGAIN, 0, 31, 1), + SOC_SINGLE("DAC Volume", MAX9867_DACLEVEL, 4, 3, 0), + SOC_SINGLE("DAC Attenuation", MAX9867_DACLEVEL, 0, 15, 1), + SOC_SINGLE_TLV("ADC Left Volume", MAX9867_ADCLEVEL, + 4, 15, 1, max9860_adc_left_tlv), + SOC_SINGLE_TLV("ADC Right Volume", MAX9867_ADCLEVEL, + 0, 15, 1, max9860_adc_right_tlv), + SOC_ENUM("Speaker Mode", max9867_spkmode), + SOC_SINGLE("Volume Smoothing Switch", MAX9867_MODECONFIG, 6, 1, 0), + SOC_SINGLE("ZCD Switch", MAX9867_MODECONFIG, 5, 1, 0), + SOC_ENUM("DSP Filter", max9867_filter), +}; + +static const char *const max9867_mux[] = {"None", "Mic", "Line", "Mic_Line"}; + +static SOC_ENUM_SINGLE_DECL(max9867_mux_enum, + MAX9867_INPUTCONFIG, MAX9867_INPUT_SHIFT, + max9867_mux); + +static const struct snd_kcontrol_new max9867_dapm_mux_controls = + SOC_DAPM_ENUM("Route", max9867_mux_enum); + +static const struct snd_kcontrol_new max9867_left_dapm_control = + SOC_DAPM_SINGLE("Switch", MAX9867_PWRMAN, 6, 1, 0); +static const struct snd_kcontrol_new max9867_right_dapm_control = + SOC_DAPM_SINGLE("Switch", MAX9867_PWRMAN, 5, 1, 0); +static const struct snd_kcontrol_new max9867_line_dapm_control = + SOC_DAPM_SINGLE("Switch", MAX9867_LEFTLINELVL, 6, 1, 1); + +static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("Left DAC", NULL, MAX9867_PWRMAN, 3, 0), + SND_SOC_DAPM_DAC("Right DAC", NULL, MAX9867_PWRMAN, 2, 0), + SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("HPOUT"), + + SND_SOC_DAPM_AIF_IN("DAI_IN", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("Left ADC", "HiFi Capture", MAX9867_PWRMAN, 1, 0), + SND_SOC_DAPM_ADC("Right ADC", "HiFi Capture", MAX9867_PWRMAN, 0, 0), + SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, + &max9867_dapm_mux_controls), + + SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SWITCH("Left Line", MAX9867_LEFTLINELVL, 6, 1, + &max9867_left_dapm_control), + SND_SOC_DAPM_SWITCH("Right Line", MAX9867_RIGTHLINELVL, 6, 1, + &max9867_right_dapm_control), + SND_SOC_DAPM_SWITCH("Line Mixer", SND_SOC_NOPM, 0, 0, + &max9867_line_dapm_control), + SND_SOC_DAPM_INPUT("LINE_IN"), +}; + +static const struct snd_soc_dapm_route max9867_audio_map[] = { + {"Left DAC", NULL, "DAI_OUT"}, + {"Right DAC", NULL, "DAI_OUT"}, + {"Output Mixer", NULL, "Left DAC"}, + {"Output Mixer", NULL, "Right DAC"}, + {"HPOUT", NULL, "Output Mixer"}, + + {"Left ADC", NULL, "DAI_IN"}, + {"Right ADC", NULL, "DAI_IN"}, + {"Input Mixer", NULL, "Left ADC"}, + {"Input Mixer", NULL, "Right ADC"}, + {"Input Mux", "Line", "Input Mixer"}, + {"Input Mux", "Mic", "Input Mixer"}, + {"Input Mux", "Mic_Line", "Input Mixer"}, + {"Right Line", "Switch", "Input Mux"}, + {"Left Line", "Switch", "Input Mux"}, + {"LINE_IN", NULL, "Left Line"}, + {"LINE_IN", NULL, "Right Line"}, +}; + +enum rates { + pcm_rate_8, pcm_rate_16, pcm_rate_24, + pcm_rate_32, pcm_rate_44, + pcm_rate_48, max_pcm_rate, +}; + +struct ni_div_rates { + u32 mclk; + u16 ni[max_pcm_rate]; +} ni_div[] = { + {11289600, {0x116A, 0x22D4, 0x343F, 0x45A9, 0x6000, 0x687D} }, + {12000000, {0x1062, 0x20C5, 0x3127, 0x4189, 0x5A51, 0x624E} }, + {12288000, {0x1000, 0x2000, 0x3000, 0x4000, 0x5833, 0x6000} }, + {13000000, {0x0F20, 0x1E3F, 0x2D5F, 0x3C7F, 0x535F, 0x5ABE} }, + {19200000, {0x0A3D, 0x147B, 0x1EB8, 0x28F6, 0x3873, 0x3D71} }, + {24000000, {0x1062, 0x20C5, 0x1893, 0x4189, 0x5A51, 0x624E} }, + {26000000, {0x0F20, 0x1E3F, 0x16AF, 0x3C7F, 0x535F, 0x5ABE} }, + {27000000, {0x0E90, 0x1D21, 0x15D8, 0x3A41, 0x5048, 0x5762} }, +}; + +static inline int get_ni_value(int mclk, int rate) +{ + int i, ret = 0; + + /* find the closest rate index*/ + for (i = 0; i < ARRAY_SIZE(ni_div); i++) { + if (ni_div[i].mclk >= mclk) + break; + } + if (i == ARRAY_SIZE(ni_div)) + return -EINVAL; + + switch (rate) { + case 8000: + return ni_div[i].ni[pcm_rate_8]; + case 16000: + return ni_div[i].ni[pcm_rate_16]; + case 32000: + return ni_div[i].ni[pcm_rate_32]; + case 44100: + return ni_div[i].ni[pcm_rate_44]; + case 48000: + return ni_div[i].ni[pcm_rate_48]; + default: + pr_err("%s wrong rate %d\n", __func__, rate); + ret = -EINVAL; + } + return ret; +} + +static int max9867_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); + unsigned int ni_h, ni_l; + int value; + + value = get_ni_value(max9867->sysclk, params_rate(params)); + if (value < 0) + return value; + + ni_h = (0xFF00 & value) >> 8; + ni_l = 0x00FF & value; + /* set up the ni value */ + regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH, + MAX9867_NI_HIGH_MASK, ni_h); + regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW, + MAX9867_NI_LOW_MASK, ni_l); + if (!max9867->master) { + /* + * digital pll locks on to any externally supplied LRCLK signal + * and also enable rapid lock mode. + */ + regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW, + MAX9867_RAPID_LOCK, MAX9867_RAPID_LOCK); + regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH, + MAX9867_PLL, MAX9867_PLL); + } else { + unsigned long int bclk_rate, pclk_bclk_ratio; + int bclk_value; + + bclk_rate = params_rate(params) * 2 * params_width(params); + pclk_bclk_ratio = max9867->pclk/bclk_rate; + switch (params_width(params)) { + case 8: + case 16: + switch (pclk_bclk_ratio) { + case 2: + bclk_value = MAX9867_IFC1B_PCLK_2; + break; + case 4: + bclk_value = MAX9867_IFC1B_PCLK_4; + break; + case 8: + bclk_value = MAX9867_IFC1B_PCLK_8; + break; + case 16: + bclk_value = MAX9867_IFC1B_PCLK_16; + break; + default: + dev_err(codec->dev, + "unsupported sampling rate\n"); + return -EINVAL; + } + break; + case 24: + bclk_value = MAX9867_IFC1B_24BIT; + break; + case 32: + bclk_value = MAX9867_IFC1B_32BIT; + break; + default: + dev_err(codec->dev, "unsupported sampling rate\n"); + return -EINVAL; + } + regmap_update_bits(max9867->regmap, MAX9867_IFC1B, + MAX9867_IFC1B_BCLK_MASK, bclk_value); + } + return 0; +} + +static int max9867_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); + + regmap_update_bits(max9867->regmap, MAX9867_PWRMAN, + MAX9867_SHTDOWN_MASK, MAX9867_SHTDOWN_MASK); + return 0; +} + +static int max9867_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); + + if (mute) + regmap_update_bits(max9867->regmap, MAX9867_DACLEVEL, + MAX9867_DAC_MUTE_MASK, MAX9867_DAC_MUTE_MASK); + else + regmap_update_bits(max9867->regmap, MAX9867_DACLEVEL, + MAX9867_DAC_MUTE_MASK, 0); + return 0; +} + +static int max9867_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); + int value = 0; + + /* Set the prescaler based on the master clock frequency*/ + if (freq >= 10000000 && freq <= 20000000) { + value |= MAX9867_PSCLK_10_20; + max9867->pclk = freq; + } else if (freq >= 20000000 && freq <= 40000000) { + value |= MAX9867_PSCLK_20_40; + max9867->pclk = freq/2; + } else if (freq >= 40000000 && freq <= 60000000) { + value |= MAX9867_PSCLK_40_60; + max9867->pclk = freq/4; + } else { + pr_err("bad clock frequency %d", freq); + return -EINVAL; + } + value = value << MAX9867_PSCLK_SHIFT; + max9867->sysclk = freq; + /* exact integer mode is not supported */ + value &= ~MAX9867_FREQ_MASK; + regmap_update_bits(max9867->regmap, MAX9867_SYSCLK, + MAX9867_PSCLK_MASK, value); + return 0; +} + +static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); + u8 iface1A = 0, iface1B = 0; + int ret; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + max9867->master = 1; + iface1A |= MAX9867_MASTER; + break; + case SND_SOC_DAIFMT_CBS_CFS: + max9867->master = 0; + iface1A &= ~MAX9867_MASTER; + break; + default: + return -EINVAL; + } + + /* for i2s compatible mode */ + iface1A |= MAX9867_I2S_DLY; + /* SDOUT goes to hiz state after all data is transferred */ + iface1A |= MAX9867_SDOUT_HIZ; + + /* Clock inversion bits, BCI and WCI */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + iface1A |= MAX9867_WCI_MODE | MAX9867_BCI_MODE; + break; + case SND_SOC_DAIFMT_IB_NF: + iface1A |= MAX9867_BCI_MODE; + break; + case SND_SOC_DAIFMT_NB_IF: + iface1A |= MAX9867_WCI_MODE; + break; + default: + return -EINVAL; + } + + ret = regmap_write(max9867->regmap, MAX9867_IFC1A, iface1A); + ret = regmap_write(max9867->regmap, MAX9867_IFC1B, iface1B); + return 0; +} + +static struct snd_soc_dai_ops max9867_dai_ops = { + .set_fmt = max9867_dai_set_fmt, + .set_sysclk = max9867_set_dai_sysclk, + .prepare = max9867_prepare, + .digital_mute = max9867_mute, + .hw_params = max9867_dai_hw_params, +}; + +#define MAX9867_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) +#define MAX9867_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) + +static struct snd_soc_dai_driver max9867_dai[] = { + { + .name = "max9867-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MAX9867_RATES, + .formats = MAX9867_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MAX9867_RATES, + .formats = MAX9867_FORMATS, + }, + .ops = &max9867_dai_ops, + } +}; + +#ifdef CONFIG_PM_SLEEP +static int max9867_suspend(struct device *dev) +{ + struct max9867_priv *max9867 = dev_get_drvdata(dev); + + /* Drop down to power saving mode when system is suspended */ + regmap_update_bits(max9867->regmap, MAX9867_PWRMAN, + MAX9867_SHTDOWN_MASK, ~MAX9867_SHTDOWN_MASK); + return 0; +} + +static int max9867_resume(struct device *dev) +{ + struct max9867_priv *max9867 = dev_get_drvdata(dev); + + regmap_update_bits(max9867->regmap, MAX9867_PWRMAN, + MAX9867_SHTDOWN_MASK, MAX9867_SHTDOWN_MASK); + return 0; +} +#endif + +static int max9867_probe(struct snd_soc_codec *codec) +{ + struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "max98090_probe\n"); + max9867->codec = codec; + return 0; +} + +static struct snd_soc_codec_driver max9867_codec = { + .probe = max9867_probe, + .controls = max9867_snd_controls, + .num_controls = ARRAY_SIZE(max9867_snd_controls), + .dapm_routes = max9867_audio_map, + .num_dapm_routes = ARRAY_SIZE(max9867_audio_map), + .dapm_widgets = max9867_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max9867_dapm_widgets), +}; + +static bool max9867_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX9867_STATUS: + case MAX9867_JACKSTATUS: + case MAX9867_AUXHIGH: + case MAX9867_AUXLOW: + return true; + default: + return false; + } +} + +static const struct reg_default max9867_reg[] = { + { 0x04, 0x00 }, + { 0x05, 0x00 }, + { 0x06, 0x00 }, + { 0x07, 0x00 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0A, 0x00 }, + { 0x0B, 0x00 }, + { 0x0C, 0x00 }, + { 0x0D, 0x00 }, + { 0x0E, 0x00 }, + { 0x0F, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, +}; + +static const struct regmap_config max9867_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX9867_REVISION, + .reg_defaults = max9867_reg, + .num_reg_defaults = ARRAY_SIZE(max9867_reg), + .volatile_reg = max9867_volatile_register, + .cache_type = REGCACHE_RBTREE, +}; + +static int max9867_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct max9867_priv *max9867; + int ret = 0, reg; + + max9867 = devm_kzalloc(&i2c->dev, + sizeof(*max9867), GFP_KERNEL); + if (!max9867) + return -ENOMEM; + + i2c_set_clientdata(i2c, max9867); + max9867->regmap = devm_regmap_init_i2c(i2c, &max9867_regmap); + if (IS_ERR(max9867->regmap)) { + ret = PTR_ERR(max9867->regmap); + dev_err(&i2c->dev, + "Failed to allocate regmap: %d\n", ret); + return ret; + } + ret = regmap_read(max9867->regmap, + MAX9867_REVISION, ®); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to read: %d\n", ret); + return ret; + } + dev_info(&i2c->dev, "device revision: %x\n", reg); + ret = snd_soc_register_codec(&i2c->dev, &max9867_codec, + max9867_dai, ARRAY_SIZE(max9867_dai)); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); + return ret; + } + return ret; +} + +static int max9867_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id max9867_i2c_id[] = { + { "max9867", 0 }, + { } +}; + +static const struct of_device_id max9867_of_match[] = { + { .compatible = "maxim,max9867", }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, max9867_i2c_id); + +static const struct dev_pm_ops max9867_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(max9867_suspend, max9867_resume) +}; + +static struct i2c_driver max9867_i2c_driver = { + .driver = { + .name = "max9867", + .of_match_table = of_match_ptr(max9867_of_match), + .pm = &max9867_pm_ops, + }, + .probe = max9867_i2c_probe, + .remove = max9867_i2c_remove, + .id_table = max9867_i2c_id, +}; + +module_i2c_driver(max9867_i2c_driver); + +MODULE_AUTHOR("anish kumar <yesanishhere@gmail.com>"); +MODULE_DESCRIPTION("ALSA SoC MAX9867 driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max9867.h b/sound/soc/codecs/max9867.h new file mode 100755 index 0000000..65590b4 --- /dev/null +++ b/sound/soc/codecs/max9867.h @@ -0,0 +1,83 @@ +/* + * max9867.h -- MAX9867 ALSA SoC Audio driver + * + * Copyright 2013-2015 Maxim Integrated Products + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _MAX9867_H +#define _MAX9867_H + +/* MAX9867 register space */ + +#define MAX9867_STATUS 0x00 +#define MAX9867_JACKSTATUS 0x01 +#define MAX9867_AUXHIGH 0x02 +#define MAX9867_AUXLOW 0x03 +#define MAX9867_INTEN 0x04 +#define MAX9867_SYSCLK 0x05 +#define MAX9867_FREQ_MASK 0xF +#define MAX9867_PSCLK_SHIFT 0x4 +#define MAX9867_PSCLK_WIDTH 0x2 +#define MAX9867_PSCLK_MASK (0x03<<MAX9867_PSCLK_SHIFT) +#define MAX9867_PSCLK_10_20 0x1 +#define MAX9867_PSCLK_20_40 0x2 +#define MAX9867_PSCLK_40_60 0x3 +#define MAX9867_AUDIOCLKHIGH 0x06 +#define MAX9867_NI_HIGH_WIDTH 0x7 +#define MAX9867_NI_HIGH_MASK 0x7F +#define MAX9867_NI_LOW_MASK 0x7F +#define MAX9867_NI_LOW_SHIFT 0x1 +#define MAX9867_PLL (1<<7) +#define MAX9867_AUDIOCLKLOW 0x07 +#define MAX9867_RAPID_LOCK 0x01 +#define MAX9867_IFC1A 0x08 +#define MAX9867_MASTER (1<<7) +#define MAX9867_I2S_DLY (1<<4) +#define MAX9867_SDOUT_HIZ (1<<3) +#define MAX9867_TDM_MODE (1<<2) +#define MAX9867_WCI_MODE (1<<6) +#define MAX9867_BCI_MODE (1<<5) +#define MAX9867_IFC1B 0x09 +#define MAX9867_IFC1B_BCLK_MASK 7 +#define MAX9867_IFC1B_32BIT 0x01 +#define MAX9867_IFC1B_24BIT 0x02 +#define MAX9867_IFC1B_PCLK_2 4 +#define MAX9867_IFC1B_PCLK_4 5 +#define MAX9867_IFC1B_PCLK_8 6 +#define MAX9867_IFC1B_PCLK_16 7 +#define MAX9867_CODECFLTR 0x0a +#define MAX9867_DACGAIN 0x0b +#define MAX9867_DACLEVEL 0x0c +#define MAX9867_DAC_MUTE_SHIFT 0x6 +#define MAX9867_DAC_MUTE_WIDTH 0x1 +#define MAX9867_DAC_MUTE_MASK (0x1<<MAX9867_DAC_MUTE_SHIFT) +#define MAX9867_ADCLEVEL 0x0d +#define MAX9867_LEFTLINELVL 0x0e +#define MAX9867_RIGTHLINELVL 0x0f +#define MAX9867_LEFTVOL 0x10 +#define MAX9867_RIGHTVOL 0x11 +#define MAX9867_LEFTMICGAIN 0x12 +#define MAX9867_RIGHTMICGAIN 0x13 +#define MAX9867_INPUTCONFIG 0x14 +#define MAX9867_INPUT_SHIFT 0x6 +#define MAX9867_MICCONFIG 0x15 +#define MAX9867_MODECONFIG 0x16 +#define MAX9867_PWRMAN 0x17 +#define MAX9867_SHTDOWN_MASK (1<<7) +#define MAX9867_REVISION 0xff + +#define MAX9867_CACHEREGNUM 10 + +/* codec private data */ +struct max9867_priv { + struct regmap *regmap; + struct snd_soc_codec *codec; + unsigned int sysclk; + unsigned int pclk; + unsigned int master; +}; +#endif diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c new file mode 100644 index 0000000..5245e10 --- /dev/null +++ b/sound/soc/codecs/max98926.c @@ -0,0 +1,606 @@ +/* + * max98926.c -- ALSA SoC MAX98926 driver + * Copyright 2013-15 Maxim Integrated Products + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/cdev.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/tlv.h> +#include "max98926.h" + +static const char * const max98926_boost_voltage_txt[] = { + "8.5V", "8.25V", "8.0V", "7.75V", "7.5V", "7.25V", "7.0V", "6.75V", + "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V" +}; + +static const char * const max98926_boost_current_txt[] = { + "0.6", "0.8", "1.0", "1.2", "1.4", "1.6", "1.8", "2.0", + "2.2", "2.4", "2.6", "2.8", "3.2", "3.6", "4.0", "4.4" +}; + +static const char *const max98926_dai_txt[] = { + "Left", "Right", "LeftRight", "LeftRightDiv2", +}; + +static const char *const max98926_pdm_ch_text[] = { + "Current", "Voltage", +}; + +static const char *const max98926_hpf_cutoff_txt[] = { + "Disable", "DC Block", "100Hz", + "200Hz", "400Hz", "800Hz", +}; + +static struct reg_default max98926_reg[] = { + { 0x0B, 0x00 }, /* IRQ Enable0 */ + { 0x0C, 0x00 }, /* IRQ Enable1 */ + { 0x0D, 0x00 }, /* IRQ Enable2 */ + { 0x0E, 0x00 }, /* IRQ Clear0 */ + { 0x0F, 0x00 }, /* IRQ Clear1 */ + { 0x10, 0x00 }, /* IRQ Clear2 */ + { 0x11, 0xC0 }, /* Map0 */ + { 0x12, 0x00 }, /* Map1 */ + { 0x13, 0x00 }, /* Map2 */ + { 0x14, 0xF0 }, /* Map3 */ + { 0x15, 0x00 }, /* Map4 */ + { 0x16, 0xAB }, /* Map5 */ + { 0x17, 0x89 }, /* Map6 */ + { 0x18, 0x00 }, /* Map7 */ + { 0x19, 0x00 }, /* Map8 */ + { 0x1A, 0x04 }, /* DAI Clock Mode 1 */ + { 0x1B, 0x00 }, /* DAI Clock Mode 2 */ + { 0x1C, 0x00 }, /* DAI Clock Divider Denominator MSBs */ + { 0x1D, 0x00 }, /* DAI Clock Divider Denominator LSBs */ + { 0x1E, 0xF0 }, /* DAI Clock Divider Numerator MSBs */ + { 0x1F, 0x00 }, /* DAI Clock Divider Numerator LSBs */ + { 0x20, 0x50 }, /* Format */ + { 0x21, 0x00 }, /* TDM Slot Select */ + { 0x22, 0x00 }, /* DOUT Configuration VMON */ + { 0x23, 0x00 }, /* DOUT Configuration IMON */ + { 0x24, 0x00 }, /* DOUT Configuration VBAT */ + { 0x25, 0x00 }, /* DOUT Configuration VBST */ + { 0x26, 0x00 }, /* DOUT Configuration FLAG */ + { 0x27, 0xFF }, /* DOUT HiZ Configuration 1 */ + { 0x28, 0xFF }, /* DOUT HiZ Configuration 2 */ + { 0x29, 0xFF }, /* DOUT HiZ Configuration 3 */ + { 0x2A, 0xFF }, /* DOUT HiZ Configuration 4 */ + { 0x2B, 0x02 }, /* DOUT Drive Strength */ + { 0x2C, 0x90 }, /* Filters */ + { 0x2D, 0x00 }, /* Gain */ + { 0x2E, 0x02 }, /* Gain Ramping */ + { 0x2F, 0x00 }, /* Speaker Amplifier */ + { 0x30, 0x0A }, /* Threshold */ + { 0x31, 0x00 }, /* ALC Attack */ + { 0x32, 0x80 }, /* ALC Atten and Release */ + { 0x33, 0x00 }, /* ALC Infinite Hold Release */ + { 0x34, 0x92 }, /* ALC Configuration */ + { 0x35, 0x01 }, /* Boost Converter */ + { 0x36, 0x00 }, /* Block Enable */ + { 0x37, 0x00 }, /* Configuration */ + { 0x38, 0x00 }, /* Global Enable */ + { 0x3A, 0x00 }, /* Boost Limiter */ +}; + +static const struct soc_enum max98926_voltage_enum[] = { + SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS, 0, + ARRAY_SIZE(max98926_pdm_ch_text), + max98926_pdm_ch_text), +}; + +static const struct snd_kcontrol_new max98926_voltage_control = + SOC_DAPM_ENUM("Route", max98926_voltage_enum); + +static const struct soc_enum max98926_current_enum[] = { + SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS, + MAX98926_PDM_SOURCE_1_SHIFT, + ARRAY_SIZE(max98926_pdm_ch_text), + max98926_pdm_ch_text), +}; + +static const struct snd_kcontrol_new max98926_current_control = + SOC_DAPM_ENUM("Route", max98926_current_enum); + +static const struct snd_kcontrol_new max98926_mixer_controls[] = { + SOC_DAPM_SINGLE("PCM Single Switch", MAX98926_SPK_AMP, + MAX98926_INSELECT_MODE_SHIFT, 0, 0), + SOC_DAPM_SINGLE("PDM Single Switch", MAX98926_SPK_AMP, + MAX98926_INSELECT_MODE_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new max98926_dai_controls[] = { + SOC_DAPM_SINGLE("Left", MAX98926_GAIN, + MAX98926_DAC_IN_SEL_SHIFT, 0, 0), + SOC_DAPM_SINGLE("Right", MAX98926_GAIN, + MAX98926_DAC_IN_SEL_SHIFT, 1, 0), + SOC_DAPM_SINGLE("LeftRight", MAX98926_GAIN, + MAX98926_DAC_IN_SEL_SHIFT, 2, 0), + SOC_DAPM_SINGLE("(Left+Right)/2 Switch", MAX98926_GAIN, + MAX98926_DAC_IN_SEL_SHIFT, 3, 0), +}; + +static const struct snd_soc_dapm_widget max98926_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("Amp Enable", NULL, MAX98926_BLOCK_ENABLE, + MAX98926_SPK_EN_SHIFT, 0), + SND_SOC_DAPM_SUPPLY("Global Enable", MAX98926_GLOBAL_ENABLE, + MAX98926_EN_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("VI Enable", MAX98926_BLOCK_ENABLE, + MAX98926_ADC_IMON_EN_WIDTH | + MAX98926_ADC_VMON_EN_SHIFT, + 0, NULL, 0), + SND_SOC_DAPM_PGA("BST Enable", MAX98926_BLOCK_ENABLE, + MAX98926_BST_EN_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("BE_OUT"), + SND_SOC_DAPM_MIXER("PCM Sel", MAX98926_SPK_AMP, + MAX98926_INSELECT_MODE_SHIFT, 0, + &max98926_mixer_controls[0], + ARRAY_SIZE(max98926_mixer_controls)), + SND_SOC_DAPM_MIXER("DAI Sel", + MAX98926_GAIN, MAX98926_DAC_IN_SEL_SHIFT, 0, + &max98926_dai_controls[0], + ARRAY_SIZE(max98926_dai_controls)), + SND_SOC_DAPM_MUX("PDM CH1 Source", + MAX98926_DAI_CLK_DIV_N_LSBS, + MAX98926_PDM_CURRENT_SHIFT, + 0, &max98926_current_control), + SND_SOC_DAPM_MUX("PDM CH0 Source", + MAX98926_DAI_CLK_DIV_N_LSBS, + MAX98926_PDM_VOLTAGE_SHIFT, + 0, &max98926_voltage_control), +}; + +static const struct snd_soc_dapm_route max98926_audio_map[] = { + {"VI Enable", NULL, "DAI_OUT"}, + {"DAI Sel", "Left", "VI Enable"}, + {"DAI Sel", "Right", "VI Enable"}, + {"DAI Sel", "LeftRight", "VI Enable"}, + {"DAI Sel", "LeftRightDiv2", "VI Enable"}, + {"PCM Sel", "PCM", "DAI Sel"}, + + {"PDM CH1 Source", "Current", "DAI_OUT"}, + {"PDM CH1 Source", "Voltage", "DAI_OUT"}, + {"PDM CH0 Source", "Current", "DAI_OUT"}, + {"PDM CH0 Source", "Voltage", "DAI_OUT"}, + {"PCM Sel", "Analog", "PDM CH1 Source"}, + {"PCM Sel", "Analog", "PDM CH0 Source"}, + {"Amp Enable", NULL, "PCM Sel"}, + + {"BST Enable", NULL, "Amp Enable"}, + {"BE_OUT", NULL, "BST Enable"}, +}; + +static bool max98926_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98926_VBAT_DATA: + case MAX98926_VBST_DATA: + case MAX98926_LIVE_STATUS0: + case MAX98926_LIVE_STATUS1: + case MAX98926_LIVE_STATUS2: + case MAX98926_STATE0: + case MAX98926_STATE1: + case MAX98926_STATE2: + case MAX98926_FLAG0: + case MAX98926_FLAG1: + case MAX98926_FLAG2: + case MAX98926_VERSION: + return true; + default: + return false; + } +} + +static bool max98926_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98926_IRQ_CLEAR0: + case MAX98926_IRQ_CLEAR1: + case MAX98926_IRQ_CLEAR2: + case MAX98926_ALC_HOLD_RLS: + return false; + default: + return true; + } +}; + +DECLARE_TLV_DB_SCALE(max98926_spk_tlv, -600, 100, 0); +DECLARE_TLV_DB_RANGE(max98926_current_tlv, + 0, 11, TLV_DB_SCALE_ITEM(20, 20, 0), + 12, 15, TLV_DB_SCALE_ITEM(320, 40, 0), +); + +static SOC_ENUM_SINGLE_DECL(max98926_dac_hpf_cutoff, + MAX98926_FILTERS, MAX98926_DAC_HPF_SHIFT, + max98926_hpf_cutoff_txt); + +static SOC_ENUM_SINGLE_DECL(max98926_boost_voltage, + MAX98926_CONFIGURATION, MAX98926_BST_VOUT_SHIFT, + max98926_boost_voltage_txt); + +static const struct snd_kcontrol_new max98926_snd_controls[] = { + SOC_SINGLE_TLV("Speaker Volume", MAX98926_GAIN, + MAX98926_SPK_GAIN_SHIFT, + (1<<MAX98926_SPK_GAIN_WIDTH)-1, 0, + max98926_spk_tlv), + SOC_SINGLE("Ramp Switch", MAX98926_GAIN_RAMPING, + MAX98926_SPK_RMP_EN_SHIFT, 1, 0), + SOC_SINGLE("ZCD Switch", MAX98926_GAIN_RAMPING, + MAX98926_SPK_ZCD_EN_SHIFT, 1, 0), + SOC_SINGLE("ALC Switch", MAX98926_THRESHOLD, + MAX98926_ALC_EN_SHIFT, 1, 0), + SOC_SINGLE("ALC Threshold", MAX98926_THRESHOLD, + MAX98926_ALC_TH_SHIFT, + (1<<MAX98926_ALC_TH_WIDTH)-1, 0), + SOC_ENUM("Boost Output Voltage", max98926_boost_voltage), + SOC_SINGLE_TLV("Boost Current Limit", MAX98926_BOOST_LIMITER, + MAX98926_BST_ILIM_SHIFT, + (1<<MAX98926_BST_ILIM_SHIFT)-1, 0, + max98926_current_tlv), + SOC_ENUM("DAC HPF Cutoff", max98926_dac_hpf_cutoff), + SOC_DOUBLE("PDM Channel One", MAX98926_DAI_CLK_DIV_N_LSBS, + MAX98926_PDM_CHANNEL_1_SHIFT, + MAX98926_PDM_CHANNEL_1_HIZ, 1, 0), + SOC_DOUBLE("PDM Channel Zero", MAX98926_DAI_CLK_DIV_N_LSBS, + MAX98926_PDM_CHANNEL_0_SHIFT, + MAX98926_PDM_CHANNEL_0_HIZ, 1, 0), +}; + +static const struct { + int rate; + int sr; +} rate_table[] = { + { + .rate = 8000, + .sr = 0, + }, + { + .rate = 11025, + .sr = 1, + }, + { + .rate = 12000, + .sr = 2, + }, + { + .rate = 16000, + .sr = 3, + }, + { + .rate = 22050, + .sr = 4, + }, + { + .rate = 24000, + .sr = 5, + }, + { + .rate = 32000, + .sr = 6, + }, + { + .rate = 44100, + .sr = 7, + }, + { + .rate = 48000, + .sr = 8, + }, +}; + +static void max98926_set_sense_data(struct max98926_priv *max98926) +{ + regmap_update_bits(max98926->regmap, + MAX98926_DOUT_CFG_VMON, + MAX98926_DAI_VMON_EN_MASK, + MAX98926_DAI_VMON_EN_MASK); + regmap_update_bits(max98926->regmap, + MAX98926_DOUT_CFG_IMON, + MAX98926_DAI_IMON_EN_MASK, + MAX98926_DAI_IMON_EN_MASK); + + if (!max98926->interleave_mode) { + /* set VMON slots */ + regmap_update_bits(max98926->regmap, + MAX98926_DOUT_CFG_VMON, + MAX98926_DAI_VMON_SLOT_MASK, + max98926->v_slot); + /* set IMON slots */ + regmap_update_bits(max98926->regmap, + MAX98926_DOUT_CFG_IMON, + MAX98926_DAI_IMON_SLOT_MASK, + max98926->i_slot); + } else { + /* enable interleave mode */ + regmap_update_bits(max98926->regmap, + MAX98926_FORMAT, + MAX98926_DAI_INTERLEAVE_MASK, + MAX98926_DAI_INTERLEAVE_MASK); + /* set interleave slots */ + regmap_update_bits(max98926->regmap, + MAX98926_DOUT_CFG_VBAT, + MAX98926_DAI_INTERLEAVE_SLOT_MASK, + max98926->v_slot); + } +} + +static int max98926_dai_set_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); + unsigned int invert = 0; + + dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + max98926_set_sense_data(max98926); + break; + default: + dev_err(codec->dev, "DAI clock mode unsupported"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + invert = MAX98926_DAI_WCI_MASK; + break; + case SND_SOC_DAIFMT_IB_NF: + invert = MAX98926_DAI_BCI_MASK; + break; + case SND_SOC_DAIFMT_IB_IF: + invert = MAX98926_DAI_BCI_MASK | MAX98926_DAI_WCI_MASK; + break; + default: + dev_err(codec->dev, "DAI invert mode unsupported"); + return -EINVAL; + } + + regmap_write(max98926->regmap, + MAX98926_FORMAT, MAX98926_DAI_DLY_MASK); + regmap_update_bits(max98926->regmap, MAX98926_FORMAT, + MAX98926_DAI_BCI_MASK, invert); + return 0; +} + +static int max98926_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + int dai_sr = -EINVAL; + int rate = params_rate(params), i; + struct snd_soc_codec *codec = dai->codec; + struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); + int blr_clk_ratio; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + regmap_update_bits(max98926->regmap, + MAX98926_FORMAT, + MAX98926_DAI_CHANSZ_MASK, + MAX98926_DAI_CHANSZ_16); + max98926->ch_size = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + regmap_update_bits(max98926->regmap, + MAX98926_FORMAT, + MAX98926_DAI_CHANSZ_MASK, + MAX98926_DAI_CHANSZ_24); + max98926->ch_size = 24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + regmap_update_bits(max98926->regmap, + MAX98926_FORMAT, + MAX98926_DAI_CHANSZ_MASK, + MAX98926_DAI_CHANSZ_32); + max98926->ch_size = 32; + break; + default: + dev_dbg(codec->dev, "format unsupported %d", + params_format(params)); + return -EINVAL; + } + + /* BCLK/LRCLK ratio calculation */ + blr_clk_ratio = params_channels(params) * max98926->ch_size; + + switch (blr_clk_ratio) { + case 32: + regmap_update_bits(max98926->regmap, + MAX98926_DAI_CLK_MODE2, + MAX98926_DAI_BSEL_MASK, + MAX98926_DAI_BSEL_32); + break; + case 48: + regmap_update_bits(max98926->regmap, + MAX98926_DAI_CLK_MODE2, + MAX98926_DAI_BSEL_MASK, + MAX98926_DAI_BSEL_48); + break; + case 64: + regmap_update_bits(max98926->regmap, + MAX98926_DAI_CLK_MODE2, + MAX98926_DAI_BSEL_MASK, + MAX98926_DAI_BSEL_64); + break; + default: + return -EINVAL; + } + + /* find the closest rate */ + for (i = 0; i < ARRAY_SIZE(rate_table); i++) { + if (rate_table[i].rate >= rate) { + dai_sr = rate_table[i].sr; + break; + } + } + if (dai_sr < 0) + return -EINVAL; + + /* set DAI_SR to correct LRCLK frequency */ + regmap_update_bits(max98926->regmap, + MAX98926_DAI_CLK_MODE2, + MAX98926_DAI_SR_MASK, dai_sr << MAX98926_DAI_SR_SHIFT); + return 0; +} + +#define MAX98926_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops max98926_dai_ops = { + .set_fmt = max98926_dai_set_fmt, + .hw_params = max98926_dai_hw_params, +}; + +static struct snd_soc_dai_driver max98926_dai[] = { +{ + .name = "max98926-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = MAX98926_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = MAX98926_FORMATS, + }, + .ops = &max98926_dai_ops, +} +}; + +static int max98926_probe(struct snd_soc_codec *codec) +{ + struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); + + max98926->codec = codec; + codec->control_data = max98926->regmap; + /* Hi-Z all the slots */ + regmap_write(max98926->regmap, MAX98926_DOUT_HIZ_CFG4, 0xF0); + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_max98926 = { + .probe = max98926_probe, + .controls = max98926_snd_controls, + .num_controls = ARRAY_SIZE(max98926_snd_controls), + .dapm_routes = max98926_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98926_audio_map), + .dapm_widgets = max98926_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets), +}; + +static struct regmap_config max98926_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX98926_VERSION, + .reg_defaults = max98926_reg, + .num_reg_defaults = ARRAY_SIZE(max98926_reg), + .volatile_reg = max98926_volatile_register, + .readable_reg = max98926_readable_register, + .cache_type = REGCACHE_RBTREE, +}; + +static int max98926_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + int ret, reg; + u32 value; + struct max98926_priv *max98926; + + max98926 = devm_kzalloc(&i2c->dev, + sizeof(*max98926), GFP_KERNEL); + if (!max98926) + return -ENOMEM; + + i2c_set_clientdata(i2c, max98926); + max98926->regmap = devm_regmap_init_i2c(i2c, &max98926_regmap); + if (IS_ERR(max98926->regmap)) { + ret = PTR_ERR(max98926->regmap); + dev_err(&i2c->dev, + "Failed to allocate regmap: %d\n", ret); + goto err_out; + } + if (of_property_read_bool(i2c->dev.of_node, "interleave-mode")) + max98926->interleave_mode = true; + + if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) { + if (value > MAX98926_DAI_VMON_SLOT_1E_1F) { + dev_err(&i2c->dev, "vmon slot number is wrong:\n"); + return -EINVAL; + } + max98926->v_slot = value; + } + if (!of_property_read_u32(i2c->dev.of_node, "imon-slot-no", &value)) { + if (value > MAX98926_DAI_IMON_SLOT_1E_1F) { + dev_err(&i2c->dev, "imon slot number is wrong:\n"); + return -EINVAL; + } + max98926->i_slot = value; + } + ret = regmap_read(max98926->regmap, + MAX98926_VERSION, ®); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to read: %x\n", reg); + return ret; + } + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98926, + max98926_dai, ARRAY_SIZE(max98926_dai)); + if (ret < 0) + dev_err(&i2c->dev, + "Failed to register codec: %d\n", ret); + dev_info(&i2c->dev, "device version: %x\n", reg); +err_out: + return ret; +} + +static int max98926_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id max98926_i2c_id[] = { + { "max98926", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max98926_i2c_id); + +static const struct of_device_id max98926_of_match[] = { + { .compatible = "maxim,max98926", }, + { } +}; +MODULE_DEVICE_TABLE(of, max98926_of_match); + +static struct i2c_driver max98926_i2c_driver = { + .driver = { + .name = "max98926", + .of_match_table = of_match_ptr(max98926_of_match), + .pm = NULL, + }, + .probe = max98926_i2c_probe, + .remove = max98926_i2c_remove, + .id_table = max98926_i2c_id, +}; + +module_i2c_driver(max98926_i2c_driver) +MODULE_DESCRIPTION("ALSA SoC MAX98926 driver"); +MODULE_AUTHOR("Anish kumar <anish.kumar@maximintegrated.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max98926.h b/sound/soc/codecs/max98926.h new file mode 100644 index 0000000..9d7ab6d --- /dev/null +++ b/sound/soc/codecs/max98926.h @@ -0,0 +1,848 @@ +/* + * max98926.h -- MAX98926 ALSA SoC Audio driver + * Copyright 2013-2015 Maxim Integrated Products + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _MAX98926_H +#define _MAX98926_H + +#define MAX98926_CHIP_VERSION 0x40 +#define MAX98926_CHIP_VERSION1 0x50 + +#define MAX98926_VBAT_DATA 0x00 +#define MAX98926_VBST_DATA 0x01 +#define MAX98926_LIVE_STATUS0 0x02 +#define MAX98926_LIVE_STATUS1 0x03 +#define MAX98926_LIVE_STATUS2 0x04 +#define MAX98926_STATE0 0x05 +#define MAX98926_STATE1 0x06 +#define MAX98926_STATE2 0x07 +#define MAX98926_FLAG0 0x08 +#define MAX98926_FLAG1 0x09 +#define MAX98926_FLAG2 0x0A +#define MAX98926_IRQ_ENABLE0 0x0B +#define MAX98926_IRQ_ENABLE1 0x0C +#define MAX98926_IRQ_ENABLE2 0x0D +#define MAX98926_IRQ_CLEAR0 0x0E +#define MAX98926_IRQ_CLEAR1 0x0F +#define MAX98926_IRQ_CLEAR2 0x10 +#define MAX98926_MAP0 0x11 +#define MAX98926_MAP1 0x12 +#define MAX98926_MAP2 0x13 +#define MAX98926_MAP3 0x14 +#define MAX98926_MAP4 0x15 +#define MAX98926_MAP5 0x16 +#define MAX98926_MAP6 0x17 +#define MAX98926_MAP7 0x18 +#define MAX98926_MAP8 0x19 +#define MAX98926_DAI_CLK_MODE1 0x1A +#define MAX98926_DAI_CLK_MODE2 0x1B +#define MAX98926_DAI_CLK_DIV_M_MSBS 0x1C +#define MAX98926_DAI_CLK_DIV_M_LSBS 0x1D +#define MAX98926_DAI_CLK_DIV_N_MSBS 0x1E +#define MAX98926_DAI_CLK_DIV_N_LSBS 0x1F +#define MAX98926_FORMAT 0x20 +#define MAX98926_TDM_SLOT_SELECT 0x21 +#define MAX98926_DOUT_CFG_VMON 0x22 +#define MAX98926_DOUT_CFG_IMON 0x23 +#define MAX98926_DOUT_CFG_VBAT 0x24 +#define MAX98926_DOUT_CFG_VBST 0x25 +#define MAX98926_DOUT_CFG_FLAG 0x26 +#define MAX98926_DOUT_HIZ_CFG1 0x27 +#define MAX98926_DOUT_HIZ_CFG2 0x28 +#define MAX98926_DOUT_HIZ_CFG3 0x29 +#define MAX98926_DOUT_HIZ_CFG4 0x2A +#define MAX98926_DOUT_DRV_STRENGTH 0x2B +#define MAX98926_FILTERS 0x2C +#define MAX98926_GAIN 0x2D +#define MAX98926_GAIN_RAMPING 0x2E +#define MAX98926_SPK_AMP 0x2F +#define MAX98926_THRESHOLD 0x30 +#define MAX98926_ALC_ATTACK 0x31 +#define MAX98926_ALC_ATTEN_RLS 0x32 +#define MAX98926_ALC_HOLD_RLS 0x33 +#define MAX98926_ALC_CONFIGURATION 0x34 +#define MAX98926_BOOST_CONVERTER 0x35 +#define MAX98926_BLOCK_ENABLE 0x36 +#define MAX98926_CONFIGURATION 0x37 +#define MAX98926_GLOBAL_ENABLE 0x38 +#define MAX98926_BOOST_LIMITER 0x3A +#define MAX98926_VERSION 0xFF + +#define MAX98926_REG_CNT (MAX98926_R03A_BOOST_LIMITER+1) + +#define MAX98926_PDM_CURRENT_MASK (1<<7) +#define MAX98926_PDM_CURRENT_SHIFT 7 +#define MAX98926_PDM_VOLTAGE_MASK (1<<3) +#define MAX98926_PDM_VOLTAGE_SHIFT 3 +#define MAX98926_PDM_CHANNEL_0_MASK (1<<2) +#define MAX98926_PDM_CHANNEL_0_SHIFT 2 +#define MAX98926_PDM_CHANNEL_1_MASK (1<<6) +#define MAX98926_PDM_CHANNEL_1_SHIFT 6 +#define MAX98926_PDM_CHANNEL_1_HIZ 5 +#define MAX98926_PDM_CHANNEL_0_HIZ 1 +#define MAX98926_PDM_SOURCE_0_SHIFT 0 +#define MAX98926_PDM_SOURCE_0_MASK (1<<0) +#define MAX98926_PDM_SOURCE_1_MASK (1<<4) +#define MAX98926_PDM_SOURCE_1_SHIFT 4 + +/* MAX98926 Register Bit Fields */ + +/* MAX98926_R002_LIVE_STATUS0 */ +#define MAX98926_THERMWARN_STATUS_MASK (1<<3) +#define MAX98926_THERMWARN_STATUS_SHIFT 3 +#define MAX98926_THERMWARN_STATUS_WIDTH 1 +#define MAX98926_THERMSHDN_STATUS_MASK (1<<1) +#define MAX98926_THERMSHDN_STATUS_SHIFT 1 +#define MAX98926_THERMSHDN_STATUS_WIDTH 1 + +/* MAX98926_R003_LIVE_STATUS1 */ +#define MAX98926_SPKCURNT_STATUS_MASK (1<<5) +#define MAX98926_SPKCURNT_STATUS_SHIFT 5 +#define MAX98926_SPKCURNT_STATUS_WIDTH 1 +#define MAX98926_WATCHFAIL_STATUS_MASK (1<<4) +#define MAX98926_WATCHFAIL_STATUS_SHIFT 4 +#define MAX98926_WATCHFAIL_STATUS_WIDTH 1 +#define MAX98926_ALCINFH_STATUS_MASK (1<<3) +#define MAX98926_ALCINFH_STATUS_SHIFT 3 +#define MAX98926_ALCINFH_STATUS_WIDTH 1 +#define MAX98926_ALCACT_STATUS_MASK (1<<2) +#define MAX98926_ALCACT_STATUS_SHIFT 2 +#define MAX98926_ALCACT_STATUS_WIDTH 1 +#define MAX98926_ALCMUT_STATUS_MASK (1<<1) +#define MAX98926_ALCMUT_STATUS_SHIFT 1 +#define MAX98926_ALCMUT_STATUS_WIDTH 1 +#define MAX98926_ACLP_STATUS_MASK (1<<0) +#define MAX98926_ACLP_STATUS_SHIFT 0 +#define MAX98926_ACLP_STATUS_WIDTH 1 + +/* MAX98926_R004_LIVE_STATUS2 */ +#define MAX98926_SLOTOVRN_STATUS_MASK (1<<6) +#define MAX98926_SLOTOVRN_STATUS_SHIFT 6 +#define MAX98926_SLOTOVRN_STATUS_WIDTH 1 +#define MAX98926_INVALSLOT_STATUS_MASK (1<<5) +#define MAX98926_INVALSLOT_STATUS_SHIFT 5 +#define MAX98926_INVALSLOT_STATUS_WIDTH 1 +#define MAX98926_SLOTCNFLT_STATUS_MASK (1<<4) +#define MAX98926_SLOTCNFLT_STATUS_SHIFT 4 +#define MAX98926_SLOTCNFLT_STATUS_WIDTH 1 +#define MAX98926_VBSTOVFL_STATUS_MASK (1<<3) +#define MAX98926_VBSTOVFL_STATUS_SHIFT 3 +#define MAX98926_VBSTOVFL_STATUS_WIDTH 1 +#define MAX98926_VBATOVFL_STATUS_MASK (1<<2) +#define MAX98926_VBATOVFL_STATUS_SHIFT 2 +#define MAX98926_VBATOVFL_STATUS_WIDTH 1 +#define MAX98926_IMONOVFL_STATUS_MASK (1<<1) +#define MAX98926_IMONOVFL_STATUS_SHIFT 1 +#define MAX98926_IMONOVFL_STATUS_WIDTH 1 +#define MAX98926_VMONOVFL_STATUS_MASK (1<<0) +#define MAX98926_VMONOVFL_STATUS_SHIFT 0 +#define MAX98926_VMONOVFL_STATUS_WIDTH 1 + +/* MAX98926_R005_STATE0 */ +#define MAX98926_THERMWARN_END_STATE_MASK (1<<3) +#define MAX98926_THERMWARN_END_STATE_SHIFT 3 +#define MAX98926_THERMWARN_END_STATE_WIDTH 1 +#define MAX98926_THERMWARN_BGN_STATE_MASK (1<<2) +#define MAX98926_THERMWARN_BGN_STATE_SHIFT 1 +#define MAX98926_THERMWARN_BGN_STATE_WIDTH 1 +#define MAX98926_THERMSHDN_END_STATE_MASK (1<<1) +#define MAX98926_THERMSHDN_END_STATE_SHIFT 1 +#define MAX98926_THERMSHDN_END_STATE_WIDTH 1 +#define MAX98926_THERMSHDN_BGN_STATE_MASK (1<<0) +#define MAX98926_THERMSHDN_BGN_STATE_SHIFT 0 +#define MAX98926_THERMSHDN_BGN_STATE_WIDTH 1 + +/* MAX98926_R006_STATE1 */ +#define MAX98926_SPRCURNT_STATE_MASK (1<<5) +#define MAX98926_SPRCURNT_STATE_SHIFT 5 +#define MAX98926_SPRCURNT_STATE_WIDTH 1 +#define MAX98926_WATCHFAIL_STATE_MASK (1<<4) +#define MAX98926_WATCHFAIL_STATE_SHIFT 4 +#define MAX98926_WATCHFAIL_STATE_WIDTH 1 +#define MAX98926_ALCINFH_STATE_MASK (1<<3) +#define MAX98926_ALCINFH_STATE_SHIFT 3 +#define MAX98926_ALCINFH_STATE_WIDTH 1 +#define MAX98926_ALCACT_STATE_MASK (1<<2) +#define MAX98926_ALCACT_STATE_SHIFT 2 +#define MAX98926_ALCACT_STATE_WIDTH 1 +#define MAX98926_ALCMUT_STATE_MASK (1<<1) +#define MAX98926_ALCMUT_STATE_SHIFT 1 +#define MAX98926_ALCMUT_STATE_WIDTH 1 +#define MAX98926_ALCP_STATE_MASK (1<<0) +#define MAX98926_ALCP_STATE_SHIFT 0 +#define MAX98926_ALCP_STATE_WIDTH 1 + +/* MAX98926_R007_STATE2 */ +#define MAX98926_SLOTOVRN_STATE_MASK (1<<6) +#define MAX98926_SLOTOVRN_STATE_SHIFT 6 +#define MAX98926_SLOTOVRN_STATE_WIDTH 1 +#define MAX98926_INVALSLOT_STATE_MASK (1<<5) +#define MAX98926_INVALSLOT_STATE_SHIFT 5 +#define MAX98926_INVALSLOT_STATE_WIDTH 1 +#define MAX98926_SLOTCNFLT_STATE_MASK (1<<4) +#define MAX98926_SLOTCNFLT_STATE_SHIFT 4 +#define MAX98926_SLOTCNFLT_STATE_WIDTH 1 +#define MAX98926_VBSTOVFL_STATE_MASK (1<<3) +#define MAX98926_VBSTOVFL_STATE_SHIFT 3 +#define MAX98926_VBSTOVFL_STATE_WIDTH 1 +#define MAX98926_VBATOVFL_STATE_MASK (1<<2) +#define MAX98926_VBATOVFL_STATE_SHIFT 2 +#define MAX98926_VBATOVFL_STATE_WIDTH 1 +#define MAX98926_IMONOVFL_STATE_MASK (1<<1) +#define MAX98926_IMONOVFL_STATE_SHIFT 1 +#define MAX98926_IMONOVFL_STATE_WIDTH 1 +#define MAX98926_VMONOVFL_STATE_MASK (1<<0) +#define MAX98926_VMONOVFL_STATE_SHIFT 0 +#define MAX98926_VMONOVFL_STATE_WIDTH 1 + +/* MAX98926_R008_FLAG0 */ +#define MAX98926_THERMWARN_END_FLAG_MASK (1<<3) +#define MAX98926_THERMWARN_END_FLAG_SHIFT 3 +#define MAX98926_THERMWARN_END_FLAG_WIDTH 1 +#define MAX98926_THERMWARN_BGN_FLAG_MASK (1<<2) +#define MAX98926_THERMWARN_BGN_FLAG_SHIFT 2 +#define MAX98926_THERMWARN_BGN_FLAG_WIDTH 1 +#define MAX98926_THERMSHDN_END_FLAG_MASK (1<<1) +#define MAX98926_THERMSHDN_END_FLAG_SHIFT 1 +#define MAX98926_THERMSHDN_END_FLAG_WIDTH 1 +#define MAX98926_THERMSHDN_BGN_FLAG_MASK (1<<0) +#define MAX98926_THERMSHDN_BGN_FLAG_SHIFT 0 +#define MAX98926_THERMSHDN_BGN_FLAG_WIDTH 1 + +/* MAX98926_R009_FLAG1 */ +#define MAX98926_SPKCURNT_FLAG_MASK (1<<5) +#define MAX98926_SPKCURNT_FLAG_SHIFT 5 +#define MAX98926_SPKCURNT_FLAG_WIDTH 1 +#define MAX98926_WATCHFAIL_FLAG_MASK (1<<4) +#define MAX98926_WATCHFAIL_FLAG_SHIFT 4 +#define MAX98926_WATCHFAIL_FLAG_WIDTH 1 +#define MAX98926_ALCINFH_FLAG_MASK (1<<3) +#define MAX98926_ALCINFH_FLAG_SHIFT 3 +#define MAX98926_ALCINFH_FLAG_WIDTH 1 +#define MAX98926_ALCACT_FLAG_MASK (1<<2) +#define MAX98926_ALCACT_FLAG_SHIFT 2 +#define MAX98926_ALCACT_FLAG_WIDTH 1 +#define MAX98926_ALCMUT_FLAG_MASK (1<<1) +#define MAX98926_ALCMUT_FLAG_SHIFT 1 +#define MAX98926_ALCMUT_FLAG_WIDTH 1 +#define MAX98926_ALCP_FLAG_MASK (1<<0) +#define MAX98926_ALCP_FLAG_SHIFT 0 +#define MAX98926_ALCP_FLAG_WIDTH 1 + +/* MAX98926_R00A_FLAG2 */ +#define MAX98926_SLOTOVRN_FLAG_MASK (1<<6) +#define MAX98926_SLOTOVRN_FLAG_SHIFT 6 +#define MAX98926_SLOTOVRN_FLAG_WIDTH 1 +#define MAX98926_INVALSLOT_FLAG_MASK (1<<5) +#define MAX98926_INVALSLOT_FLAG_SHIFT 5 +#define MAX98926_INVALSLOT_FLAG_WIDTH 1 +#define MAX98926_SLOTCNFLT_FLAG_MASK (1<<4) +#define MAX98926_SLOTCNFLT_FLAG_SHIFT 4 +#define MAX98926_SLOTCNFLT_FLAG_WIDTH 1 +#define MAX98926_VBSTOVFL_FLAG_MASK (1<<3) +#define MAX98926_VBSTOVFL_FLAG_SHIFT 3 +#define MAX98926_VBSTOVFL_FLAG_WIDTH 1 +#define MAX98926_VBATOVFL_FLAG_MASK (1<<2) +#define MAX98926_VBATOVFL_FLAG_SHIFT 2 +#define MAX98926_VBATOVFL_FLAG_WIDTH 1 +#define MAX98926_IMONOVFL_FLAG_MASK (1<<1) +#define MAX98926_IMONOVFL_FLAG_SHIFT 1 +#define MAX98926_IMONOVFL_FLAG_WIDTH 1 +#define MAX98926_VMONOVFL_FLAG_MASK (1<<0) +#define MAX98926_VMONOVFL_FLAG_SHIFT 0 +#define MAX98926_VMONOVFL_FLAG_WIDTH 1 + +/* MAX98926_R00B_IRQ_ENABLE0 */ +#define MAX98926_THERMWARN_END_EN_MASK (1<<3) +#define MAX98926_THERMWARN_END_EN_SHIFT 3 +#define MAX98926_THERMWARN_END_EN_WIDTH 1 +#define MAX98926_THERMWARN_BGN_EN_MASK (1<<2) +#define MAX98926_THERMWARN_BGN_EN_SHIFT 2 +#define MAX98926_THERMWARN_BGN_EN_WIDTH 1 +#define MAX98926_THERMSHDN_END_EN_MASK (1<<1) +#define MAX98926_THERMSHDN_END_EN_SHIFT 1 +#define MAX98926_THERMSHDN_END_EN_WIDTH 1 +#define MAX98926_THERMSHDN_BGN_EN_MASK (1<<0) +#define MAX98926_THERMSHDN_BGN_EN_SHIFT 0 +#define MAX98926_THERMSHDN_BGN_EN_WIDTH 1 + +/* MAX98926_R00C_IRQ_ENABLE1 */ +#define MAX98926_SPKCURNT_EN_MASK (1<<5) +#define MAX98926_SPKCURNT_EN_SHIFT 5 +#define MAX98926_SPKCURNT_EN_WIDTH 1 +#define MAX98926_WATCHFAIL_EN_MASK (1<<4) +#define MAX98926_WATCHFAIL_EN_SHIFT 4 +#define MAX98926_WATCHFAIL_EN_WIDTH 1 +#define MAX98926_ALCINFH_EN_MASK (1<<3) +#define MAX98926_ALCINFH_EN_SHIFT 3 +#define MAX98926_ALCINFH_EN_WIDTH 1 +#define MAX98926_ALCACT_EN_MASK (1<<2) +#define MAX98926_ALCACT_EN_SHIFT 2 +#define MAX98926_ALCACT_EN_WIDTH 1 +#define MAX98926_ALCMUT_EN_MASK (1<<1) +#define MAX98926_ALCMUT_EN_SHIFT 1 +#define MAX98926_ALCMUT_EN_WIDTH 1 +#define MAX98926_ALCP_EN_MASK (1<<0) +#define MAX98926_ALCP_EN_SHIFT 0 +#define MAX98926_ALCP_EN_WIDTH 1 + +/* MAX98926_R00D_IRQ_ENABLE2 */ +#define MAX98926_SLOTOVRN_EN_MASK (1<<6) +#define MAX98926_SLOTOVRN_EN_SHIFT 6 +#define MAX98926_SLOTOVRN_EN_WIDTH 1 +#define MAX98926_INVALSLOT_EN_MASK (1<<5) +#define MAX98926_INVALSLOT_EN_SHIFT 5 +#define MAX98926_INVALSLOT_EN_WIDTH 1 +#define MAX98926_SLOTCNFLT_EN_MASK (1<<4) +#define MAX98926_SLOTCNFLT_EN_SHIFT 4 +#define MAX98926_SLOTCNFLT_EN_WIDTH 1 +#define MAX98926_VBSTOVFL_EN_MASK (1<<3) +#define MAX98926_VBSTOVFL_EN_SHIFT 3 +#define MAX98926_VBSTOVFL_EN_WIDTH 1 +#define MAX98926_VBATOVFL_EN_MASK (1<<2) +#define MAX98926_VBATOVFL_EN_SHIFT 2 +#define MAX98926_VBATOVFL_EN_WIDTH 1 +#define MAX98926_IMONOVFL_EN_MASK (1<<1) +#define MAX98926_IMONOVFL_EN_SHIFT 1 +#define MAX98926_IMONOVFL_EN_WIDTH 1 +#define MAX98926_VMONOVFL_EN_MASK (1<<0) +#define MAX98926_VMONOVFL_EN_SHIFT 0 +#define MAX98926_VMONOVFL_EN_WIDTH 1 + +/* MAX98926_R00E_IRQ_CLEAR0 */ +#define MAX98926_THERMWARN_END_CLR_MASK (1<<3) +#define MAX98926_THERMWARN_END_CLR_SHIFT 3 +#define MAX98926_THERMWARN_END_CLR_WIDTH 1 +#define MAX98926_THERMWARN_BGN_CLR_MASK (1<<2) +#define MAX98926_THERMWARN_BGN_CLR_SHIFT 2 +#define MAX98926_THERMWARN_BGN_CLR_WIDTH 1 +#define MAX98926_THERMSHDN_END_CLR_MASK (1<<1) +#define MAX98926_THERMSHDN_END_CLR_SHIFT 1 +#define MAX98926_THERMSHDN_END_CLR_WIDTH 1 +#define MAX98926_THERMSHDN_BGN_CLR_MASK (1<<0) +#define MAX98926_THERMSHDN_BGN_CLR_SHIFT 0 +#define MAX98926_THERMSHDN_BGN_CLR_WIDTH 1 + +/* MAX98926_R00F_IRQ_CLEAR1 */ +#define MAX98926_SPKCURNT_CLR_MASK (1<<5) +#define MAX98926_SPKCURNT_CLR_SHIFT 5 +#define MAX98926_SPKCURNT_CLR_WIDTH 1 +#define MAX98926_WATCHFAIL_CLR_MASK (1<<4) +#define MAX98926_WATCHFAIL_CLR_SHIFT 4 +#define MAX98926_WATCHFAIL_CLR_WIDTH 1 +#define MAX98926_ALCINFH_CLR_MASK (1<<3) +#define MAX98926_ALCINFH_CLR_SHIFT 3 +#define MAX98926_ALCINFH_CLR_WIDTH 1 +#define MAX98926_ALCACT_CLR_MASK (1<<2) +#define MAX98926_ALCACT_CLR_SHIFT 2 +#define MAX98926_ALCACT_CLR_WIDTH 1 +#define MAX98926_ALCMUT_CLR_MASK (1<<1) +#define MAX98926_ALCMUT_CLR_SHIFT 1 +#define MAX98926_ALCMUT_CLR_WIDTH 1 +#define MAX98926_ALCP_CLR_MASK (1<<0) +#define MAX98926_ALCP_CLR_SHIFT 0 +#define MAX98926_ALCP_CLR_WIDTH 1 + +/* MAX98926_R010_IRQ_CLEAR2 */ +#define MAX98926_SLOTOVRN_CLR_MASK (1<<6) +#define MAX98926_SLOTOVRN_CLR_SHIFT 6 +#define MAX98926_SLOTOVRN_CLR_WIDTH 1 +#define MAX98926_INVALSLOT_CLR_MASK (1<<5) +#define MAX98926_INVALSLOT_CLR_SHIFT 5 +#define MAX98926_INVALSLOT_CLR_WIDTH 1 +#define MAX98926_SLOTCNFLT_CLR_MASK (1<<4) +#define MAX98926_SLOTCNFLT_CLR_SHIFT 4 +#define MAX98926_SLOTCNFLT_CLR_WIDTH 1 +#define MAX98926_VBSTOVFL_CLR_MASK (1<<3) +#define MAX98926_VBSTOVFL_CLR_SHIFT 3 +#define MAX98926_VBSTOVFL_CLR_WIDTH 1 +#define MAX98926_VBATOVFL_CLR_MASK (1<<2) +#define MAX98926_VBATOVFL_CLR_SHIFT 2 +#define MAX98926_VBATOVFL_CLR_WIDTH 1 +#define MAX98926_IMONOVFL_CLR_MASK (1<<1) +#define MAX98926_IMONOVFL_CLR_SHIFT 1 +#define MAX98926_IMONOVFL_CLR_WIDTH 1 +#define MAX98926_VMONOVFL_CLR_MASK (1<<0) +#define MAX98926_VMONOVFL_CLR_SHIFT 0 +#define MAX98926_VMONOVFL_CLR_WIDTH 1 + +/* MAX98926_R011_MAP0 */ +#define MAX98926_ER_THERMWARN_EN_MASK (1<<7) +#define MAX98926_ER_THERMWARN_EN_SHIFT 7 +#define MAX98926_ER_THERMWARN_EN_WIDTH 1 +#define MAX98926_ER_THERMWARN_MAP_MASK (0x07<<4) +#define MAX98926_ER_THERMWARN_MAP_SHIFT 4 +#define MAX98926_ER_THERMWARN_MAP_WIDTH 3 + +/* MAX98926_R012_MAP1 */ +#define MAX98926_ER_ALCMUT_EN_MASK (1<<7) +#define MAX98926_ER_ALCMUT_EN_SHIFT 7 +#define MAX98926_ER_ALCMUT_EN_WIDTH 1 +#define MAX98926_ER_ALCMUT_MAP_MASK (0x07<<4) +#define MAX98926_ER_ALCMUT_MAP_SHIFT 4 +#define MAX98926_ER_ALCMUT_MAP_WIDTH 3 +#define MAX98926_ER_ALCP_EN_MASK (1<<3) +#define MAX98926_ER_ALCP_EN_SHIFT 3 +#define MAX98926_ER_ALCP_EN_WIDTH 1 +#define MAX98926_ER_ALCP_MAP_MASK (0x07<<0) +#define MAX98926_ER_ALCP_MAP_SHIFT 0 +#define MAX98926_ER_ALCP_MAP_WIDTH 3 + +/* MAX98926_R013_MAP2 */ +#define MAX98926_ER_ALCINFH_EN_MASK (1<<7) +#define MAX98926_ER_ALCINFH_EN_SHIFT 7 +#define MAX98926_ER_ALCINFH_EN_WIDTH 1 +#define MAX98926_ER_ALCINFH_MAP_MASK (0x07<<4) +#define MAX98926_ER_ALCINFH_MAP_SHIFT 4 +#define MAX98926_ER_ALCINFH_MAP_WIDTH 3 +#define MAX98926_ER_ALCACT_EN_MASK (1<<3) +#define MAX98926_ER_ALCACT_EN_SHIFT 3 +#define MAX98926_ER_ALCACT_EN_WIDTH 1 +#define MAX98926_ER_ALCACT_MAP_MASK (0x07<<0) +#define MAX98926_ER_ALCACT_MAP_SHIFT 0 +#define MAX98926_ER_ALCACT_MAP_WIDTH 3 + +/* MAX98926_R014_MAP3 */ +#define MAX98926_ER_SPKCURNT_EN_MASK (1<<7) +#define MAX98926_ER_SPKCURNT_EN_SHIFT 7 +#define MAX98926_ER_SPKCURNT_EN_WIDTH 1 +#define MAX98926_ER_SPKCURNT_MAP_MASK (0x07<<4) +#define MAX98926_ER_SPKCURNT_MAP_SHIFT 4 +#define MAX98926_ER_SPKCURNT_MAP_WIDTH 3 + +/* MAX98926_R015_MAP4 */ +/* RESERVED */ + +/* MAX98926_R016_MAP5 */ +#define MAX98926_ER_IMONOVFL_EN_MASK (1<<7) +#define MAX98926_ER_IMONOVFL_EN_SHIFT 7 +#define MAX98926_ER_IMONOVFL_EN_WIDTH 1 +#define MAX98926_ER_IMONOVFL_MAP_MASK (0x07<<4) +#define MAX98926_ER_IMONOVFL_MAP_SHIFT 4 +#define MAX98926_ER_IMONOVFL_MAP_WIDTH 3 +#define MAX98926_ER_VMONOVFL_EN_MASK (1<<3) +#define MAX98926_ER_VMONOVFL_EN_SHIFT 3 +#define MAX98926_ER_VMONOVFL_EN_WIDTH 1 +#define MAX98926_ER_VMONOVFL_MAP_MASK (0x07<<0) +#define MAX98926_ER_VMONOVFL_MAP_SHIFT 0 +#define MAX98926_ER_VMONOVFL_MAP_WIDTH 3 + +/* MAX98926_R017_MAP6 */ +#define MAX98926_ER_VBSTOVFL_EN_MASK (1<<7) +#define MAX98926_ER_VBSTOVFL_EN_SHIFT 7 +#define MAX98926_ER_VBSTOVFL_EN_WIDTH 1 +#define MAX98926_ER_VBSTOVFL_MAP_MASK (0x07<<4) +#define MAX98926_ER_VBSTOVFL_MAP_SHIFT 4 +#define MAX98926_ER_VBSTOVFL_MAP_WIDTH 3 +#define MAX98926_ER_VBATOVFL_EN_MASK (1<<3) +#define MAX98926_ER_VBATOVFL_EN_SHIFT 3 +#define MAX98926_ER_VBATOVFL_EN_WIDTH 1 +#define MAX98926_ER_VBATOVFL_MAP_MASK (0x07<<0) +#define MAX98926_ER_VBATOVFL_MAP_SHIFT 0 +#define MAX98926_ER_VBATOVFL_MAP_WIDTH 3 + +/* MAX98926_R018_MAP7 */ +#define MAX98926_ER_INVALSLOT_EN_MASK (1<<7) +#define MAX98926_ER_INVALSLOT_EN_SHIFT 7 +#define MAX98926_ER_INVALSLOT_EN_WIDTH 1 +#define MAX98926_ER_INVALSLOT_MAP_MASK (0x07<<4) +#define MAX98926_ER_INVALSLOT_MAP_SHIFT 4 +#define MAX98926_ER_INVALSLOT_MAP_WIDTH 3 +#define MAX98926_ER_SLOTCNFLT_EN_MASK (1<<3) +#define MAX98926_ER_SLOTCNFLT_EN_SHIFT 3 +#define MAX98926_ER_SLOTCNFLT_EN_WIDTH 1 +#define MAX98926_ER_SLOTCNFLT_MAP_MASK (0x07<<0) +#define MAX98926_ER_SLOTCNFLT_MAP_SHIFT 0 +#define MAX98926_ER_SLOTCNFLT_MAP_WIDTH 3 + +/* MAX98926_R019_MAP8 */ +#define MAX98926_ER_SLOTOVRN_EN_MASK (1<<3) +#define MAX98926_ER_SLOTOVRN_EN_SHIFT 3 +#define MAX98926_ER_SLOTOVRN_EN_WIDTH 1 +#define MAX98926_ER_SLOTOVRN_MAP_MASK (0x07<<0) +#define MAX98926_ER_SLOTOVRN_MAP_SHIFT 0 +#define MAX98926_ER_SLOTOVRN_MAP_WIDTH 3 + +/* MAX98926_R01A_DAI_CLK_MODE1 */ +#define MAX98926_DAI_CLK_SOURCE_MASK (1<<6) +#define MAX98926_DAI_CLK_SOURCE_SHIFT 6 +#define MAX98926_DAI_CLK_SOURCE_WIDTH 1 +#define MAX98926_MDLL_MULT_MASK (0x0F<<0) +#define MAX98926_MDLL_MULT_SHIFT 0 +#define MAX98926_MDLL_MULT_WIDTH 4 + +#define MAX98926_MDLL_MULT_MCLKx8 6 +#define MAX98926_MDLL_MULT_MCLKx16 8 + +/* MAX98926_R01B_DAI_CLK_MODE2 */ +#define MAX98926_DAI_SR_MASK (0x0F<<4) +#define MAX98926_DAI_SR_SHIFT 4 +#define MAX98926_DAI_SR_WIDTH 4 +#define MAX98926_DAI_MAS_MASK (1<<3) +#define MAX98926_DAI_MAS_SHIFT 3 +#define MAX98926_DAI_MAS_WIDTH 1 +#define MAX98926_DAI_BSEL_MASK (0x07<<0) +#define MAX98926_DAI_BSEL_SHIFT 0 +#define MAX98926_DAI_BSEL_WIDTH 3 + +#define MAX98926_DAI_BSEL_32 (0 << MAX98926_DAI_BSEL_SHIFT) +#define MAX98926_DAI_BSEL_48 (1 << MAX98926_DAI_BSEL_SHIFT) +#define MAX98926_DAI_BSEL_64 (2 << MAX98926_DAI_BSEL_SHIFT) +#define MAX98926_DAI_BSEL_256 (6 << MAX98926_DAI_BSEL_SHIFT) + +/* MAX98926_R01C_DAI_CLK_DIV_M_MSBS */ +#define MAX98926_DAI_M_MSBS_MASK (0xFF<<0) +#define MAX98926_DAI_M_MSBS_SHIFT 0 +#define MAX98926_DAI_M_MSBS_WIDTH 8 + +/* MAX98926_R01D_DAI_CLK_DIV_M_LSBS */ +#define MAX98926_DAI_M_LSBS_MASK (0xFF<<0) +#define MAX98926_DAI_M_LSBS_SHIFT 0 +#define MAX98926_DAI_M_LSBS_WIDTH 8 + +/* MAX98926_R01E_DAI_CLK_DIV_N_MSBS */ +#define MAX98926_DAI_N_MSBS_MASK (0x7F<<0) +#define MAX98926_DAI_N_MSBS_SHIFT 0 +#define MAX98926_DAI_N_MSBS_WIDTH 7 + +/* MAX98926_R01F_DAI_CLK_DIV_N_LSBS */ +#define MAX98926_DAI_N_LSBS_MASK (0xFF<<0) +#define MAX98926_DAI_N_LSBS_SHIFT 0 +#define MAX98926_DAI_N_LSBS_WIDTH 8 + +/* MAX98926_R020_FORMAT */ +#define MAX98926_DAI_CHANSZ_MASK (0x03<<6) +#define MAX98926_DAI_CHANSZ_SHIFT 6 +#define MAX98926_DAI_CHANSZ_WIDTH 2 +#define MAX98926_DAI_INTERLEAVE_MASK (1<<5) +#define MAX98926_DAI_INTERLEAVE_SHIFT 5 +#define MAX98926_DAI_INTERLEAVE_WIDTH 1 +#define MAX98926_DAI_EXTBCLK_HIZ_MASK (1<<4) +#define MAX98926_DAI_EXTBCLK_HIZ_SHIFT 4 +#define MAX98926_DAI_EXTBCLK_HIZ_WIDTH 1 +#define MAX98926_DAI_WCI_MASK (1<<3) +#define MAX98926_DAI_WCI_SHIFT 3 +#define MAX98926_DAI_WCI_WIDTH 1 +#define MAX98926_DAI_BCI_MASK (1<<2) +#define MAX98926_DAI_BCI_SHIFT 2 +#define MAX98926_DAI_BCI_WIDTH 1 +#define MAX98926_DAI_DLY_MASK (1<<1) +#define MAX98926_DAI_DLY_SHIFT 1 +#define MAX98926_DAI_DLY_WIDTH 1 +#define MAX98926_DAI_TDM_MASK (1<<0) +#define MAX98926_DAI_TDM_SHIFT 0 +#define MAX98926_DAI_TDM_WIDTH 1 + +#define MAX98926_DAI_CHANSZ_16 (1 << MAX98926_DAI_CHANSZ_SHIFT) +#define MAX98926_DAI_CHANSZ_24 (2 << MAX98926_DAI_CHANSZ_SHIFT) +#define MAX98926_DAI_CHANSZ_32 (3 << MAX98926_DAI_CHANSZ_SHIFT) + +/* MAX98926_R021_TDM_SLOT_SELECT */ +#define MAX98926_DAI_DO_EN_MASK (1<<7) +#define MAX98926_DAI_DO_EN_SHIFT 7 +#define MAX98926_DAI_DO_EN_WIDTH 1 +#define MAX98926_DAI_DIN_EN_MASK (1<<6) +#define MAX98926_DAI_DIN_EN_SHIFT 6 +#define MAX98926_DAI_DIN_EN_WIDTH 1 +#define MAX98926_DAI_INR_SOURCE_MASK (0x07<<3) +#define MAX98926_DAI_INR_SOURCE_SHIFT 3 +#define MAX98926_DAI_INR_SOURCE_WIDTH 3 +#define MAX98926_DAI_INL_SOURCE_MASK (0x07<<0) +#define MAX98926_DAI_INL_SOURCE_SHIFT 0 +#define MAX98926_DAI_INL_SOURCE_WIDTH 3 + +/* MAX98926_R022_DOUT_CFG_VMON */ +#define MAX98926_DAI_VMON_EN_MASK (1<<5) +#define MAX98926_DAI_VMON_EN_SHIFT 5 +#define MAX98926_DAI_VMON_EN_WIDTH 1 +#define MAX98926_DAI_VMON_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_VMON_SLOT_SHIFT 0 +#define MAX98926_DAI_VMON_SLOT_WIDTH 5 + +#define MAX98926_DAI_VMON_SLOT_00_01 (0 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_01_02 (1 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_02_03 (2 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_03_04 (3 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_04_05 (4 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_05_06 (5 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_06_07 (6 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_07_08 (7 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_08_09 (8 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_09_0A (9 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0A_0B (10 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0B_0C (11 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0C_0D (12 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0D_0E (13 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0E_0F (14 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0F_10 (15 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_10_11 (16 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_11_12 (17 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_12_13 (18 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_13_14 (19 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_14_15 (20 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_15_16 (21 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_16_17 (22 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_17_18 (23 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_18_19 (24 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_19_1A (25 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1A_1B (26 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1B_1C (27 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1C_1D (28 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1D_1E (29 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1E_1F (30 << MAX98926_DAI_VMON_SLOT_SHIFT) + +/* MAX98926_R023_DOUT_CFG_IMON */ +#define MAX98926_DAI_IMON_EN_MASK (1<<5) +#define MAX98926_DAI_IMON_EN_SHIFT 5 +#define MAX98926_DAI_IMON_EN_WIDTH 1 +#define MAX98926_DAI_IMON_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_IMON_SLOT_SHIFT 0 +#define MAX98926_DAI_IMON_SLOT_WIDTH 5 + +#define MAX98926_DAI_IMON_SLOT_00_01 (0 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_01_02 (1 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_02_03 (2 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_03_04 (3 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_04_05 (4 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_05_06 (5 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_06_07 (6 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_07_08 (7 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_08_09 (8 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_09_0A (9 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0A_0B (10 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0B_0C (11 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0C_0D (12 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0D_0E (13 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0E_0F (14 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0F_10 (15 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_10_11 (16 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_11_12 (17 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_12_13 (18 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_13_14 (19 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_14_15 (20 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_15_16 (21 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_16_17 (22 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_17_18 (23 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_18_19 (24 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_19_1A (25 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1A_1B (26 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1B_1C (27 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1C_1D (28 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1D_1E (29 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1E_1F (30 << MAX98926_DAI_IMON_SLOT_SHIFT) + +/* MAX98926_R024_DOUT_CFG_VBAT */ +#define MAX98926_DAI_INTERLEAVE_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_INTERLEAVE_SLOT_SHIFT 0 +#define MAX98926_DAI_INTERLEAVE_SLOT_WIDTH 5 + +/* MAX98926_R025_DOUT_CFG_VBST */ +#define MAX98926_DAI_VBST_EN_MASK (1<<5) +#define MAX98926_DAI_VBST_EN_SHIFT 5 +#define MAX98926_DAI_VBST_EN_WIDTH 1 +#define MAX98926_DAI_VBST_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_VBST_SLOT_SHIFT 0 +#define MAX98926_DAI_VBST_SLOT_WIDTH 5 + +/* MAX98926_R026_DOUT_CFG_FLAG */ +#define MAX98926_DAI_FLAG_EN_MASK (1<<5) +#define MAX98926_DAI_FLAG_EN_SHIFT 5 +#define MAX98926_DAI_FLAG_EN_WIDTH 1 +#define MAX98926_DAI_FLAG_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_FLAG_SLOT_SHIFT 0 +#define MAX98926_DAI_FLAG_SLOT_WIDTH 5 + +/* MAX98926_R027_DOUT_HIZ_CFG1 */ +#define MAX98926_DAI_SLOT_HIZ_CFG1_MASK (0xFF<<0) +#define MAX98926_DAI_SLOT_HIZ_CFG1_SHIFT 0 +#define MAX98926_DAI_SLOT_HIZ_CFG1_WIDTH 8 + +/* MAX98926_R028_DOUT_HIZ_CFG2 */ +#define MAX98926_DAI_SLOT_HIZ_CFG2_MASK (0xFF<<0) +#define MAX98926_DAI_SLOT_HIZ_CFG2_SHIFT 0 +#define MAX98926_DAI_SLOT_HIZ_CFG2_WIDTH 8 + +/* MAX98926_R029_DOUT_HIZ_CFG3 */ +#define MAX98926_DAI_SLOT_HIZ_CFG3_MASK (0xFF<<0) +#define MAX98926_DAI_SLOT_HIZ_CFG3_SHIFT 0 +#define MAX98926_DAI_SLOT_HIZ_CFG3_WIDTH 8 + +/* MAX98926_R02A_DOUT_HIZ_CFG4 */ +#define MAX98926_DAI_SLOT_HIZ_CFG4_MASK (0xFF<<0) +#define MAX98926_DAI_SLOT_HIZ_CFG4_SHIFT 0 +#define MAX98926_DAI_SLOT_HIZ_CFG4_WIDTH 8 + +/* MAX98926_R02B_DOUT_DRV_STRENGTH */ +#define MAX98926_DAI_OUT_DRIVE_MASK (0x03<<0) +#define MAX98926_DAI_OUT_DRIVE_SHIFT 0 +#define MAX98926_DAI_OUT_DRIVE_WIDTH 2 + +/* MAX98926_R02C_FILTERS */ +#define MAX98926_ADC_DITHER_EN_MASK (1<<7) +#define MAX98926_ADC_DITHER_EN_SHIFT 7 +#define MAX98926_ADC_DITHER_EN_WIDTH 1 +#define MAX98926_IV_DCB_EN_MASK (1<<6) +#define MAX98926_IV_DCB_EN_SHIFT 6 +#define MAX98926_IV_DCB_EN_WIDTH 1 +#define MAX98926_DAC_DITHER_EN_MASK (1<<4) +#define MAX98926_DAC_DITHER_EN_SHIFT 4 +#define MAX98926_DAC_DITHER_EN_WIDTH 1 +#define MAX98926_DAC_FILTER_MODE_MASK (1<<3) +#define MAX98926_DAC_FILTER_MODE_SHIFT 3 +#define MAX98926_DAC_FILTER_MODE_WIDTH 1 +#define MAX98926_DAC_HPF_MASK (0x07<<0) +#define MAX98926_DAC_HPF_SHIFT 0 +#define MAX98926_DAC_HPF_WIDTH 3 +#define MAX98926_DAC_HPF_DISABLE (0 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_DC_BLOCK (1 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_EN_100 (2 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_EN_200 (3 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_EN_400 (4 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_EN_800 (5 << MAX98926_DAC_HPF_SHIFT) + +/* MAX98926_R02D_GAIN */ +#define MAX98926_DAC_IN_SEL_MASK (0x03<<5) +#define MAX98926_DAC_IN_SEL_SHIFT 5 +#define MAX98926_DAC_IN_SEL_WIDTH 2 +#define MAX98926_SPK_GAIN_MASK (0x1F<<0) +#define MAX98926_SPK_GAIN_SHIFT 0 +#define MAX98926_SPK_GAIN_WIDTH 5 + +#define MAX98926_DAC_IN_SEL_LEFT_DAI (0 << MAX98926_DAC_IN_SEL_SHIFT) +#define MAX98926_DAC_IN_SEL_RIGHT_DAI (1 << MAX98926_DAC_IN_SEL_SHIFT) +#define MAX98926_DAC_IN_SEL_SUMMED_DAI (2 << MAX98926_DAC_IN_SEL_SHIFT) +#define MAX98926_DAC_IN_SEL_DIV2_SUMMED_DAI (3 << MAX98926_DAC_IN_SEL_SHIFT) + +/* MAX98926_R02E_GAIN_RAMPING */ +#define MAX98926_SPK_RMP_EN_MASK (1<<1) +#define MAX98926_SPK_RMP_EN_SHIFT 1 +#define MAX98926_SPK_RMP_EN_WIDTH 1 +#define MAX98926_SPK_ZCD_EN_MASK (1<<0) +#define MAX98926_SPK_ZCD_EN_SHIFT 0 +#define MAX98926_SPK_ZCD_EN_WIDTH 1 + +/* MAX98926_R02F_SPK_AMP */ +#define MAX98926_SPK_MODE_MASK (1<<0) +#define MAX98926_SPK_MODE_SHIFT 0 +#define MAX98926_SPK_MODE_WIDTH 1 +#define MAX98926_INSELECT_MODE_MASK (1<<1) +#define MAX98926_INSELECT_MODE_SHIFT 1 +#define MAX98926_INSELECT_MODE_WIDTH 1 + +/* MAX98926_R030_THRESHOLD */ +#define MAX98926_ALC_EN_MASK (1<<5) +#define MAX98926_ALC_EN_SHIFT 5 +#define MAX98926_ALC_EN_WIDTH 1 +#define MAX98926_ALC_TH_MASK (0x1F<<0) +#define MAX98926_ALC_TH_SHIFT 0 +#define MAX98926_ALC_TH_WIDTH 5 + +/* MAX98926_R031_ALC_ATTACK */ +#define MAX98926_ALC_ATK_STEP_MASK (0x0F<<4) +#define MAX98926_ALC_ATK_STEP_SHIFT 4 +#define MAX98926_ALC_ATK_STEP_WIDTH 4 +#define MAX98926_ALC_ATK_RATE_MASK (0x7<<0) +#define MAX98926_ALC_ATK_RATE_SHIFT 0 +#define MAX98926_ALC_ATK_RATE_WIDTH 3 + +/* MAX98926_R032_ALC_ATTEN_RLS */ +#define MAX98926_ALC_MAX_ATTEN_MASK (0x0F<<4) +#define MAX98926_ALC_MAX_ATTEN_SHIFT 4 +#define MAX98926_ALC_MAX_ATTEN_WIDTH 4 +#define MAX98926_ALC_RLS_RATE_MASK (0x7<<0) +#define MAX98926_ALC_RLS_RATE_SHIFT 0 +#define MAX98926_ALC_RLS_RATE_WIDTH 3 + +/* MAX98926_R033_ALC_HOLD_RLS */ +#define MAX98926_ALC_RLS_TGR_MASK (1<<0) +#define MAX98926_ALC_RLS_TGR_SHIFT 0 +#define MAX98926_ALC_RLS_TGR_WIDTH 1 + +/* MAX98926_R034_ALC_CONFIGURATION */ +#define MAX98926_ALC_MUTE_EN_MASK (1<<7) +#define MAX98926_ALC_MUTE_EN_SHIFT 7 +#define MAX98926_ALC_MUTE_EN_WIDTH 1 +#define MAX98926_ALC_MUTE_DLY_MASK (0x07<<4) +#define MAX98926_ALC_MUTE_DLY_SHIFT 4 +#define MAX98926_ALC_MUTE_DLY_WIDTH 3 +#define MAX98926_ALC_RLS_DBT_MASK (0x07<<0) +#define MAX98926_ALC_RLS_DBT_SHIFT 0 +#define MAX98926_ALC_RLS_DBT_WIDTH 3 + +/* MAX98926_R035_BOOST_CONVERTER */ +#define MAX98926_BST_SYNC_MASK (1<<7) +#define MAX98926_BST_SYNC_SHIFT 7 +#define MAX98926_BST_SYNC_WIDTH 1 +#define MAX98926_BST_PHASE_MASK (0x03<<4) +#define MAX98926_BST_PHASE_SHIFT 4 +#define MAX98926_BST_PHASE_WIDTH 2 +#define MAX98926_BST_SKIP_MODE_MASK (0x03<<0) +#define MAX98926_BST_SKIP_MODE_SHIFT 0 +#define MAX98926_BST_SKIP_MODE_WIDTH 2 + +/* MAX98926_R036_BLOCK_ENABLE */ +#define MAX98926_BST_EN_MASK (1<<7) +#define MAX98926_BST_EN_SHIFT 7 +#define MAX98926_BST_EN_WIDTH 1 +#define MAX98926_WATCH_EN_MASK (1<<6) +#define MAX98926_WATCH_EN_SHIFT 6 +#define MAX98926_WATCH_EN_WIDTH 1 +#define MAX98926_CLKMON_EN_MASK (1<<5) +#define MAX98926_CLKMON_EN_SHIFT 5 +#define MAX98926_CLKMON_EN_WIDTH 1 +#define MAX98926_SPK_EN_MASK (1<<4) +#define MAX98926_SPK_EN_SHIFT 4 +#define MAX98926_SPK_EN_WIDTH 1 +#define MAX98926_ADC_VBST_EN_MASK (1<<3) +#define MAX98926_ADC_VBST_EN_SHIFT 3 +#define MAX98926_ADC_VBST_EN_WIDTH 1 +#define MAX98926_ADC_VBAT_EN_MASK (1<<2) +#define MAX98926_ADC_VBAT_EN_SHIFT 2 +#define MAX98926_ADC_VBAT_EN_WIDTH 1 +#define MAX98926_ADC_IMON_EN_MASK (1<<1) +#define MAX98926_ADC_IMON_EN_SHIFT 1 +#define MAX98926_ADC_IMON_EN_WIDTH 1 +#define MAX98926_ADC_VMON_EN_MASK (1<<0) +#define MAX98926_ADC_VMON_EN_SHIFT 0 +#define MAX98926_ADC_VMON_EN_WIDTH 1 + +/* MAX98926_R037_CONFIGURATION */ +#define MAX98926_BST_VOUT_MASK (0x0F<<4) +#define MAX98926_BST_VOUT_SHIFT 4 +#define MAX98926_BST_VOUT_WIDTH 4 +#define MAX98926_THERMWARN_LEVEL_MASK (0x03<<2) +#define MAX98926_THERMWARN_LEVEL_SHIFT 2 +#define MAX98926_THERMWARN_LEVEL_WIDTH 2 +#define MAX98926_WATCH_TIME_MASK (0x03<<0) +#define MAX98926_WATCH_TIME_SHIFT 0 +#define MAX98926_WATCH_TIME_WIDTH 2 + +/* MAX98926_R038_GLOBAL_ENABLE */ +#define MAX98926_EN_MASK (1<<7) +#define MAX98926_EN_SHIFT 7 +#define MAX98926_EN_WIDTH 1 + +/* MAX98926_R03A_BOOST_LIMITER */ +#define MAX98926_BST_ILIM_MASK (0xF<<4) +#define MAX98926_BST_ILIM_SHIFT 4 +#define MAX98926_BST_ILIM_WIDTH 4 + +/* MAX98926_R0FF_VERSION */ +#define MAX98926_REV_ID_MASK (0xFF<<0) +#define MAX98926_REV_ID_SHIFT 0 +#define MAX98926_REV_ID_WIDTH 8 + +struct max98926_priv { + struct regmap *regmap; + struct snd_soc_codec *codec; + unsigned int sysclk; + unsigned int v_slot; + unsigned int i_slot; + unsigned int ch_size; + unsigned int interleave_mode; +}; +#endif diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index fef264d..0754df7 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -17,6 +17,7 @@ #include <linux/of_address.h> #include <linux/regmap.h> #include <linux/slab.h> +#include <linux/time.h> #include <sound/core.h> #include <sound/dmaengine_pcm.h> #include <sound/pcm_params.h> @@ -919,7 +920,7 @@ static int fsl_sai_resume(struct device *dev) regcache_cache_only(sai->regmap, false); regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR); - msleep(1); + usleep_range(1000, 2000); regmap_write(sai->regmap, FSL_SAI_TCSR, 0); regmap_write(sai->regmap, FSL_SAI_RCSR, 0); return regcache_sync(sai->regmap); diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 40dfd8a..ed8de10 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -112,20 +112,6 @@ struct fsl_ssi_rxtx_reg_val { struct fsl_ssi_reg_val tx; }; -static const struct reg_default fsl_ssi_reg_defaults[] = { - {CCSR_SSI_SCR, 0x00000000}, - {CCSR_SSI_SIER, 0x00003003}, - {CCSR_SSI_STCR, 0x00000200}, - {CCSR_SSI_SRCR, 0x00000200}, - {CCSR_SSI_STCCR, 0x00040000}, - {CCSR_SSI_SRCCR, 0x00040000}, - {CCSR_SSI_SACNT, 0x00000000}, - {CCSR_SSI_STMSK, 0x00000000}, - {CCSR_SSI_SRMSK, 0x00000000}, - {CCSR_SSI_SACCEN, 0x00000000}, - {CCSR_SSI_SACCDIS, 0x00000000}, -}; - static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -190,8 +176,7 @@ static const struct regmap_config fsl_ssi_regconfig = { .val_bits = 32, .reg_stride = 4, .val_format_endian = REGMAP_ENDIAN_NATIVE, - .reg_defaults = fsl_ssi_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(fsl_ssi_reg_defaults), + .num_reg_defaults_raw = CCSR_SSI_SACCDIS / sizeof(uint32_t) + 1, .readable_reg = fsl_ssi_readable_reg, .volatile_reg = fsl_ssi_volatile_reg, .precious_reg = fsl_ssi_precious_reg, @@ -201,6 +186,7 @@ static const struct regmap_config fsl_ssi_regconfig = { struct fsl_ssi_soc_data { bool imx; + bool imx21regs; /* imx21-class SSI - no SACC{ST,EN,DIS} regs */ bool offline_config; u32 sisr_write_mask; }; @@ -303,6 +289,7 @@ static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = { static struct fsl_ssi_soc_data fsl_ssi_imx21 = { .imx = true, + .imx21regs = true, .offline_config = true, .sisr_write_mask = 0, }; @@ -586,8 +573,12 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) */ regmap_write(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV); - regmap_write(regs, CCSR_SSI_SACCDIS, 0xff); - regmap_write(regs, CCSR_SSI_SACCEN, 0x300); + + /* no SACC{ST,EN,DIS} regs on imx21-class SSI */ + if (!ssi_private->soc->imx21regs) { + regmap_write(regs, CCSR_SSI_SACCDIS, 0xff); + regmap_write(regs, CCSR_SSI_SACCEN, 0x300); + } /* * Enable SSI, Transmit and Receive. AC97 has to communicate with the @@ -1397,6 +1388,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) struct resource *res; void __iomem *iomem; char name[64]; + struct regmap_config regconfig = fsl_ssi_regconfig; of_id = of_match_device(fsl_ssi_ids, &pdev->dev); if (!of_id || !of_id->data) @@ -1444,15 +1436,25 @@ static int fsl_ssi_probe(struct platform_device *pdev) return PTR_ERR(iomem); ssi_private->ssi_phys = res->start; + if (ssi_private->soc->imx21regs) { + /* + * According to datasheet imx21-class SSI + * don't have SACC{ST,EN,DIS} regs. + */ + regconfig.max_register = CCSR_SSI_SRMSK; + regconfig.num_reg_defaults_raw = + CCSR_SSI_SRMSK / sizeof(uint32_t) + 1; + } + ret = of_property_match_string(np, "clock-names", "ipg"); if (ret < 0) { ssi_private->has_ipg_clk_name = false; ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem, - &fsl_ssi_regconfig); + ®config); } else { ssi_private->has_ipg_clk_name = true; ssi_private->regs = devm_regmap_init_mmio_clk(&pdev->dev, - "ipg", iomem, &fsl_ssi_regconfig); + "ipg", iomem, ®config); } if (IS_ERR(ssi_private->regs)) { dev_err(&pdev->dev, "Failed to init register map\n"); |