summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorShengjiu Wang <b02247@freescale.com>2014-05-12 13:38:52 +0800
committerNitin Garg <nitin.garg@freescale.com>2014-08-27 18:28:49 -0500
commit5588f3590453f0b0dba42a91e0465b9e84eac825 (patch)
treecc17f0c05782d4af67119695225ae52d30665ca8 /sound
parent24157860b770cb54c1f6c0f3c2e1f7be6cb10936 (diff)
ENGR00313280-2 ASoC: fsl: Merge upsteamed cs42xx8 driver.
The upsteamed commit is 0c516b4ff85c0be4cee5b30ae59c9565c7f91a00 ASoC: cs42xx8: Add codec driver support for CS42448/CS42888 This patch adds support for the Cirrus Logic CS42448/CS42888 Audio CODEC that has six/four 24-bit AD and eight 24-bit DA converters. [ CS42448/CS42888 supports both I2C and SPI control ports. As initial patch, this patch only adds the support for I2C. ] Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com> Acked-by: Brian Austin <brian.austin@cirrus.com> Acked-by: Paul Handrigan <Paul.Handrigan@cirrus.com> Signed-off-by: Mark Brown <broonie@linaro.org> Signed-off-by: Shengjiu Wang <b02247@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/Kconfig10
-rw-r--r--sound/soc/codecs/Makefile6
-rw-r--r--sound/soc/codecs/cs42888.c913
-rw-r--r--sound/soc/codecs/cs42888.h123
-rw-r--r--sound/soc/codecs/cs42xx8-i2c.c64
-rw-r--r--sound/soc/codecs/cs42xx8.c602
-rw-r--r--sound/soc/codecs/cs42xx8.h238
-rw-r--r--sound/soc/fsl/imx-cs42888.c8
8 files changed, 920 insertions, 1044 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7b7801e06b86..60e4fe8b6fe4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -35,7 +35,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CS42L73 if I2C
select SND_SOC_CS4270 if I2C
select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
- select SND_SOC_CS42888 if I2C
+ select SND_SOC_CS42XX8_I2C if I2C
select SND_SOC_CX20442 if TTY
select SND_SOC_DA7210 if I2C
select SND_SOC_DA7213 if I2C
@@ -241,9 +241,15 @@ config SND_SOC_CS4270_VD33_ERRATA
config SND_SOC_CS4271
tristate
-config SND_SOC_CS42888
+config SND_SOC_CS42XX8
tristate
+config SND_SOC_CS42XX8_I2C
+ tristate "Cirrus Logic CS42448/CS42888 CODEC (I2C)"
+ depends on I2C
+ select SND_SOC_CS42XX8
+ select REGMAP_I2C
+
config SND_SOC_CX20442
tristate
depends on TTY
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index ea9bd25f9a4a..57a05ca96798 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -22,7 +22,8 @@ snd-soc-cs42l52-objs := cs42l52.o
snd-soc-cs42l73-objs := cs42l73.o
snd-soc-cs4270-objs := cs4270.o
snd-soc-cs4271-objs := cs4271.o
-snd-soc-cs42888-objs := cs42888.o
+snd-soc-cs42xx8-objs := cs42xx8.o
+snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o
snd-soc-cx20442-objs := cx20442.o
snd-soc-da7210-objs := da7210.o
snd-soc-da7213-objs := da7213.o
@@ -150,7 +151,8 @@ obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
-obj-$(CONFIG_SND_SOC_CS42888) += snd-soc-cs42888.o
+obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o
+obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
diff --git a/sound/soc/codecs/cs42888.c b/sound/soc/codecs/cs42888.c
deleted file mode 100644
index 24b68a4de234..000000000000
--- a/sound/soc/codecs/cs42888.c
+++ /dev/null
@@ -1,913 +0,0 @@
-/*
- * cs42888.c -- CS42888 ALSA SoC Audio Driver
- * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/tlv.h>
-#include <sound/initval.h>
-#include <asm/div64.h>
-#include "cs42888.h"
-
-#define CS42888_NUM_SUPPLIES 4
-static const char *cs42888_supply_names[CS42888_NUM_SUPPLIES] = {
- "VA",
- "VD",
- "VLS",
- "VLC",
-};
-
-#define CS42888_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-
-/* Private data for the CS42888 */
-struct cs42888_private {
- struct clk *clk;
- struct snd_soc_codec *codec;
- u8 reg_cache[CS42888_NUMREGS + 1];
- unsigned int mclk; /* Input frequency of the MCLK pin */
- unsigned int slave_mode;
- struct regulator_bulk_data supplies[CS42888_NUM_SUPPLIES];
-};
-
-/**
- * cs42888_fill_cache - pre-fill the CS42888 register cache.
- * @codec: the codec for this CS42888
- *
- * This function fills in the CS42888 register cache by reading the register
- * values from the hardware.
- *
- * This CS42888 registers are cached to avoid excessive I2C I/O operations.
- * After the initial read to pre-fill the cache, the CS42888 never updates
- * the register values, so we won't have a cache coherency problem.
- *
- * We use the auto-increment feature of the CS42888 to read all registers in
- * one shot.
- */
-static int cs42888_fill_cache(struct snd_soc_codec *codec)
-{
- u8 *cache = codec->reg_cache;
- struct i2c_client *i2c_client = to_i2c_client(codec->dev);
- s32 length;
-
- length = i2c_smbus_read_i2c_block_data(i2c_client,
- CS42888_FIRSTREG | CS42888_I2C_INCR, CS42888_NUMREGS, \
- cache + 1);
-
- if (length != CS42888_NUMREGS) {
- dev_err(codec->dev, "i2c read failure, addr=0x%x\n",
- i2c_client->addr);
- return -EIO;
- }
- return 0;
-}
-
-#ifdef DEBUG
-static void dump_reg(struct snd_soc_codec *codec)
-{
- int i, reg;
- int ret;
- u8 *cache = codec->reg_cache + 1;
-
- dev_dbg(codec->dev, "dump begin\n");
- dev_dbg(codec->dev, "reg value in cache\n");
- for (i = 0; i < CS42888_NUMREGS; i++)
- dev_dbg(codec->dev, "reg[%d] = 0x%x\n", i, cache[i]);
-
- dev_dbg(codec->dev, "real reg value\n");
- ret = cs42888_fill_cache(codec);
- if (ret < 0) {
- dev_err(codec->dev, "failed to fill register cache\n");
- return ret;
- }
- for (i = 0; i < CS42888_NUMREGS; i++)
- dev_dbg(codec->dev, "reg[%d] = 0x%x\n", i, cache[i]);
-
- dev_dbg(codec->dev, "dump end\n");
-}
-#else
-static void dump_reg(struct snd_soc_codec *codec)
-{
-}
-#endif
-
-/* -127.5dB to 0dB with step of 0.5dB */
-static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
-/* -64dB to 24dB with step of 0.5dB */
-static const DECLARE_TLV_DB_SCALE(adc_tlv, -6400, 50, 1);
-
-static int cs42888_out_vu(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return snd_soc_put_volsw_2r(kcontrol, ucontrol);
-}
-
-static int cs42888_info_volsw_s8(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = mc->max - mc->min;
- return 0;
-}
-
-static int cs42888_get_volsw_s8(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- s8 val = snd_soc_read(codec, mc->reg);
- ucontrol->value.integer.value[0] = val - mc->min;
-
- val = snd_soc_read(codec, mc->rreg);
- ucontrol->value.integer.value[1] = val - mc->min;
- return 0;
-}
-
-int cs42888_put_volsw_s8(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned short val;
- int ret;
-
- val = ucontrol->value.integer.value[0] + mc->min;
- ret = snd_soc_write(codec, mc->reg, val);
- if (ret < 0) {
- dev_err(codec->dev, "i2c write failed\n");
- return ret;
- }
-
- val = ucontrol->value.integer.value[1] + mc->min;
- ret = snd_soc_write(codec, mc->rreg, val);
- if (ret < 0) {
- dev_err(codec->dev, "i2c write failed\n");
- return ret;
- }
- return 0;
-}
-
-#define SOC_CS42888_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
- xinvert, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = (xname), \
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, \
- .get = snd_soc_get_volsw, \
- .put = cs42888_out_vu, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = reg_left, \
- .rreg = reg_right, \
- .shift = xshift, \
- .max = xmax, \
- .invert = xinvert} \
-}
-
-#define SOC_CS42888_DOUBLE_R_S8_TLV(xname, reg_left, reg_right, xmin, xmax, \
- tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- .tlv.p = (tlv_array), \
- .info = cs42888_info_volsw_s8, \
- .get = cs42888_get_volsw_s8, \
- .put = cs42888_put_volsw_s8, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = reg_left, \
- .rreg = reg_right, \
- .min = xmin, \
- .max = xmax} \
-}
-
-static const char *cs42888_adcfilter[] = { "None", "High Pass" };
-static const char *cs42888_dacinvert[] = { "Disabled", "Enabled" };
-static const char *cs42888_adcinvert[] = { "Disabled", "Enabled" };
-static const char *cs42888_dacamute[] = { "Disabled", "AutoMute" };
-static const char *cs42888_dac_sngvol[] = { "Disabled", "Enabled" };
-static const char *cs42888_dac_szc[] = { "Immediate Change", "Zero Cross",
- "Soft Ramp", "Soft Ramp on Zero Cross" };
-static const char *cs42888_mute_adc[] = { "UnMute", "Mute" };
-static const char *cs42888_adc_sngvol[] = { "Disabled", "Enabled" };
-static const char *cs42888_adc_szc[] = { "Immediate Change", "Zero Cross",
- "Soft Ramp", "Soft Ramp on Zero Cross" };
-static const char *cs42888_dac_dem[] = { "No-De-Emphasis", "De-Emphasis" };
-static const char *cs42888_adc_single[] = { "Differential", "Single-Ended" };
-
-static const struct soc_enum cs42888_enum[] = {
- SOC_ENUM_SINGLE(CS42888_ADCCTL, 7, 2, cs42888_adcfilter),
- SOC_ENUM_DOUBLE(CS42888_DACINV, 0, 1, 2, cs42888_dacinvert),
- SOC_ENUM_DOUBLE(CS42888_DACINV, 2, 3, 2, cs42888_dacinvert),
- SOC_ENUM_DOUBLE(CS42888_DACINV, 4, 5, 2, cs42888_dacinvert),
- SOC_ENUM_DOUBLE(CS42888_DACINV, 6, 7, 2, cs42888_dacinvert),
- SOC_ENUM_DOUBLE(CS42888_ADCINV, 0, 1, 2, cs42888_adcinvert),
- SOC_ENUM_DOUBLE(CS42888_ADCINV, 2, 3, 2, cs42888_adcinvert),
- SOC_ENUM_SINGLE(CS42888_TRANS, 4, 2, cs42888_dacamute),
- SOC_ENUM_SINGLE(CS42888_TRANS, 7, 2, cs42888_dac_sngvol),
- SOC_ENUM_SINGLE(CS42888_TRANS, 5, 4, cs42888_dac_szc),
- SOC_ENUM_SINGLE(CS42888_TRANS, 3, 2, cs42888_mute_adc),
- SOC_ENUM_SINGLE(CS42888_TRANS, 2, 2, cs42888_adc_sngvol),
- SOC_ENUM_SINGLE(CS42888_TRANS, 0, 4, cs42888_adc_szc),
- SOC_ENUM_SINGLE(CS42888_ADCCTL, 5, 2, cs42888_dac_dem),
- SOC_ENUM_SINGLE(CS42888_ADCCTL, 4, 2, cs42888_adc_single),
- SOC_ENUM_SINGLE(CS42888_ADCCTL, 3, 2, cs42888_adc_single),
-};
-
-static const struct snd_kcontrol_new cs42888_snd_controls[] = {
- SOC_CS42888_DOUBLE_R_TLV("DAC1 Playback Volume", CS42888_VOLAOUT1,
- CS42888_VOLAOUT2, 0, 0xff, 1, dac_tlv),
- SOC_CS42888_DOUBLE_R_TLV("DAC2 Playback Volume", CS42888_VOLAOUT3,
- CS42888_VOLAOUT4, 0, 0xff, 1, dac_tlv),
- SOC_CS42888_DOUBLE_R_TLV("DAC3 Playback Volume", CS42888_VOLAOUT5,
- CS42888_VOLAOUT6, 0, 0xff, 1, dac_tlv),
- SOC_CS42888_DOUBLE_R_TLV("DAC4 Playback Volume", CS42888_VOLAOUT7,
- CS42888_VOLAOUT8, 0, 0xff, 1, dac_tlv),
- SOC_CS42888_DOUBLE_R_S8_TLV("ADC1 Capture Volume", CS42888_VOLAIN1,
- CS42888_VOLAIN2, -128, 48, adc_tlv),
- SOC_CS42888_DOUBLE_R_S8_TLV("ADC2 Capture Volume", CS42888_VOLAIN3,
- CS42888_VOLAIN4, -128, 48, adc_tlv),
- SOC_ENUM("ADC High-Pass Filter Switch", cs42888_enum[0]),
- SOC_ENUM("DAC1 Invert Switch", cs42888_enum[1]),
- SOC_ENUM("DAC2 Invert Switch", cs42888_enum[2]),
- SOC_ENUM("DAC3 Invert Switch", cs42888_enum[3]),
- SOC_ENUM("DAC4 Invert Switch", cs42888_enum[4]),
- SOC_ENUM("ADC1 Invert Switch", cs42888_enum[5]),
- SOC_ENUM("ADC2 Invert Switch", cs42888_enum[6]),
- SOC_ENUM("DAC Auto Mute Switch", cs42888_enum[7]),
- SOC_ENUM("DAC Single Volume Control Switch", cs42888_enum[8]),
- SOC_ENUM("DAC Soft Ramp and Zero Cross Control Switch", cs42888_enum[9]),
- SOC_ENUM("Mute ADC Serial Port Switch", cs42888_enum[10]),
- SOC_ENUM("ADC Single Volume Control Switch", cs42888_enum[11]),
- SOC_ENUM("ADC Soft Ramp and Zero Cross Control Switch", cs42888_enum[12]),
- SOC_ENUM("DAC Deemphasis Switch", cs42888_enum[13]),
- SOC_ENUM("ADC1 Single Ended Mode Switch", cs42888_enum[14]),
- SOC_ENUM("ADC2 Single Ended Mode Switch", cs42888_enum[15]),
-};
-
-
-static const struct snd_soc_dapm_widget cs42888_dapm_widgets[] = {
- SND_SOC_DAPM_DAC("DAC1", "codec-Playback", CS42888_PWRCTL, 1, 1),
- SND_SOC_DAPM_DAC("DAC2", "codec-Playback", CS42888_PWRCTL, 2, 1),
- SND_SOC_DAPM_DAC("DAC3", "codec-Playback", CS42888_PWRCTL, 3, 1),
- SND_SOC_DAPM_DAC("DAC4", "codec-Playback", CS42888_PWRCTL, 4, 1),
-
- SND_SOC_DAPM_OUTPUT("AOUT1L"),
- SND_SOC_DAPM_OUTPUT("AOUT1R"),
- SND_SOC_DAPM_OUTPUT("AOUT2L"),
- SND_SOC_DAPM_OUTPUT("AOUT2R"),
- SND_SOC_DAPM_OUTPUT("AOUT3L"),
- SND_SOC_DAPM_OUTPUT("AOUT3R"),
- SND_SOC_DAPM_OUTPUT("AOUT4L"),
- SND_SOC_DAPM_OUTPUT("AOUT4R"),
-
- SND_SOC_DAPM_ADC("ADC1", "codec-Capture", CS42888_PWRCTL, 5, 1),
- SND_SOC_DAPM_ADC("ADC2", "codec-Capture", CS42888_PWRCTL, 6, 1),
-
- SND_SOC_DAPM_INPUT("AIN1L"),
- SND_SOC_DAPM_INPUT("AIN1R"),
- SND_SOC_DAPM_INPUT("AIN2L"),
- SND_SOC_DAPM_INPUT("AIN2R"),
-
- SND_SOC_DAPM_PGA_E("PWR", CS42888_PWRCTL, 0, 1, NULL, 0,
- NULL, 0),
-};
-
-static const struct snd_soc_dapm_route audio_map[] = {
- /* Playback */
- { "PWR", NULL, "DAC1" },
- { "PWR", NULL, "DAC1" },
-
- { "PWR", NULL, "DAC2" },
- { "PWR", NULL, "DAC2" },
-
- { "PWR", NULL, "DAC3" },
- { "PWR", NULL, "DAC3" },
-
- { "PWR", NULL, "DAC4" },
- { "PWR", NULL, "DAC4" },
-
- { "AOUT1L", NULL, "PWR" },
- { "AOUT1R", NULL, "PWR" },
-
- { "AOUT2L", NULL, "PWR" },
- { "AOUT2R", NULL, "PWR" },
-
- { "AOUT3L", NULL, "PWR" },
- { "AOUT3R", NULL, "PWR" },
-
- { "AOUT4L", NULL, "PWR" },
- { "AOUT4R", NULL, "PWR" },
-
- /* Capture */
- { "PWR", NULL, "AIN1L" },
- { "PWR", NULL, "AIN1R" },
-
- { "PWR", NULL, "AIN2L" },
- { "PWR", NULL, "AIN2R" },
-
- { "ADC1", NULL, "PWR" },
- { "ADC1", NULL, "PWR" },
-
- { "ADC2", NULL, "PWR" },
- { "ADC2", NULL, "PWR" },
-};
-
-
-static int cs42888_add_widgets(struct snd_soc_codec *codec)
-{
- snd_soc_dapm_new_controls(&codec->dapm, cs42888_dapm_widgets,
- ARRAY_SIZE(cs42888_dapm_widgets));
-
- snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
-
- snd_soc_dapm_new_widgets(&codec->dapm);
- return 0;
-}
-
-/**
- * struct cs42888_mode_ratios - clock ratio tables
- * @ratio: the ratio of MCLK to the sample rate
- * @speed_mode: the Speed Mode bits to set in the Mode Control register for
- * this ratio
- * @mclk: the Ratio Select bits to set in the Mode Control register for this
- * ratio
- *
- * The data for this chart is taken from Table 10 of the CS42888 reference
- * manual.
- *
- * This table is used to determine how to program the Functional Mode register.
- * It is also used by cs42888_set_dai_sysclk() to tell ALSA which sampling
- * rates the CS42888 currently supports.
- *
- * @speed_mode is the corresponding bit pattern to be written to the
- * MODE bits of the Mode Control Register
- *
- * @mclk is the corresponding bit pattern to be wirten to the MCLK bits of
- * the Mode Control Register.
- *
- */
-struct cs42888_mode_ratios {
- unsigned int ratio;
- u8 speed_mode;
- u8 mclk;
-};
-
-static struct cs42888_mode_ratios cs42888_mode_ratios[] = {
- {64, CS42888_MODE_4X, CS42888_MODE_DIV1},
- {96, CS42888_MODE_4X, CS42888_MODE_DIV2},
- {128, CS42888_MODE_2X, CS42888_MODE_DIV1},
- {192, CS42888_MODE_2X, CS42888_MODE_DIV2},
- {256, CS42888_MODE_1X, CS42888_MODE_DIV1},
- {384, CS42888_MODE_2X, CS42888_MODE_DIV4},
- {512, CS42888_MODE_1X, CS42888_MODE_DIV3},
- {768, CS42888_MODE_1X, CS42888_MODE_DIV4},
- {1024, CS42888_MODE_1X, CS42888_MODE_DIV5}
-};
-
-/* The number of MCLK/LRCK ratios supported by the CS42888 */
-#define NUM_MCLK_RATIOS ARRAY_SIZE(cs42888_mode_ratios)
-
-/**
- * cs42888_set_dai_sysclk - determine the CS42888 samples rates.
- * @codec_dai: the codec DAI
- * @clk_id: the clock ID (ignored)
- * @freq: the MCLK input frequency
- * @dir: the clock direction (ignored)
- *
- * This function is used to tell the codec driver what the input MCLK
- * frequency is.
- *
- */
-static int cs42888_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 cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
-
- cs42888->mclk = freq;
- return 0;
-}
-
-/**
- * cs42888_set_dai_fmt - configure the codec for the selected audio format
- * @codec_dai: the codec DAI
- * @format: a SND_SOC_DAIFMT_x value indicating the data format
- *
- * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
- * codec accordingly.
- *
- * Currently, this function only supports SND_SOC_DAIFMT_I2S and
- * SND_SOC_DAIFMT_LEFT_J. The CS42888 codec also supports right-justified
- * data for playback only, but ASoC currently does not support different
- * formats for playback vs. record.
- */
-static int cs42888_set_dai_fmt(struct snd_soc_dai *codec_dai,
- unsigned int format)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
- int ret = 0;
- u8 val;
-
- val = snd_soc_read(codec, CS42888_FORMAT);
- val &= ~CS42888_FORMAT_DAC_DIF_MASK;
- val &= ~CS42888_FORMAT_ADC_DIF_MASK;
- /* set DAI format */
- switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_LEFT_J:
- val |= DIF_LEFT_J << CS42888_FORMAT_DAC_DIF_OFFSET;
- val |= DIF_LEFT_J << CS42888_FORMAT_ADC_DIF_OFFSET;
- break;
- case SND_SOC_DAIFMT_I2S:
- val |= DIF_I2S << CS42888_FORMAT_DAC_DIF_OFFSET;
- val |= DIF_I2S << CS42888_FORMAT_ADC_DIF_OFFSET;
- break;
- case SND_SOC_DAIFMT_RIGHT_J:
- val |= DIF_RIGHT_J << CS42888_FORMAT_DAC_DIF_OFFSET;
- val |= DIF_RIGHT_J << CS42888_FORMAT_ADC_DIF_OFFSET;
- break;
- default:
- dev_err(codec->dev, "invalid dai format\n");
- return -EINVAL;
- }
-
- ret = snd_soc_write(codec, CS42888_FORMAT, val);
- if (ret < 0) {
- dev_err(codec->dev, "i2c write failed\n");
- return ret;
- }
-
- val = snd_soc_read(codec, CS42888_MODE);
- /* set master/slave audio interface */
- switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBS_CFS:
- cs42888->slave_mode = 1;
- val &= ~CS42888_MODE_SPEED_MASK;
- val |= CS42888_MODE_SLAVE;
- break;
- case SND_SOC_DAIFMT_CBM_CFM:
- cs42888->slave_mode = 0;
- break;
- default:
- /* all other modes are unsupported by the hardware */
- return -EINVAL;
- }
-
- ret = snd_soc_write(codec, CS42888_MODE, val);
- if (ret < 0) {
- dev_err(codec->dev, "i2c write failed\n");
- return ret;
- }
-
- dump_reg(codec);
- return ret;
-}
-
-/**
- * cs42888_hw_params - program the CS42888 with the given hardware parameters.
- * @substream: the audio stream
- * @params: the hardware parameters to set
-
- * @dai: the SOC DAI (ignored)
- *
- * This function programs the hardware with the values provided.
- * Specifically, the sample rate and the data format.
- *
- * The .ops functions are used to provide board-specific data, like input
- * frequencies, to this driver. This function takes that information,
- * combines it with the hardware parameters provided, and programs the
- * hardware accordingly.
- */
-static int cs42888_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
- struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
- int ret;
- u32 i, rate, ratio, val;
-
- rate = params_rate(params); /* Sampling rate, in Hz */
- ratio = cs42888->mclk / rate; /* MCLK/LRCK ratio */
- for (i = 0; i < NUM_MCLK_RATIOS; i++) {
- if (cs42888_mode_ratios[i].ratio == ratio)
- break;
- }
-
- if (i == NUM_MCLK_RATIOS) {
- /* We did not find a matching ratio */
- dev_err(codec->dev, "could not find matching ratio\n");
- return -EINVAL;
- }
-
- if (!cs42888->slave_mode) {
- val = snd_soc_read(codec, CS42888_MODE);
- val &= ~CS42888_MODE_SPEED_MASK;
- val |= cs42888_mode_ratios[i].speed_mode;
- val &= ~CS42888_MODE_DIV_MASK;
- val |= cs42888_mode_ratios[i].mclk;
- } else {
- val = snd_soc_read(codec, CS42888_MODE);
- val &= ~CS42888_MODE_SPEED_MASK;
- val |= CS42888_MODE_SLAVE;
- val &= ~CS42888_MODE_DIV_MASK;
- val |= cs42888_mode_ratios[i].mclk;
- }
- ret = snd_soc_write(codec, CS42888_MODE, val);
- if (ret < 0) {
- dev_err(codec->dev, "i2c write failed\n");
- return ret;
- }
-
- /* Unmute all the channels */
- val = snd_soc_read(codec, CS42888_MUTE);
- val &= ~CS42888_MUTE_ALL;
- ret = snd_soc_write(codec, CS42888_MUTE, val);
- if (ret < 0) {
- dev_err(codec->dev, "i2c write failed\n");
- return ret;
- }
-
- ret = cs42888_fill_cache(codec);
- if (ret < 0) {
- dev_err(codec->dev, "failed to fill register cache\n");
- return ret;
- }
-
- dump_reg(codec);
- return ret;
-}
-
-/**
- * cs42888_shutdown - cs42888 enters into low power mode again.
- * @substream: the audio stream
- * @dai: the SOC DAI (ignored)
- *
- * The .ops functions are used to provide board-specific data, like input
- * frequencies, to this driver. This function takes that information,
- * combines it with the hardware parameters provided, and programs the
- * hardware accordingly.
- */
-static void cs42888_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
- int ret;
- u8 val;
-
- /* Mute all the channels */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- val = snd_soc_read(codec, CS42888_MUTE);
- val |= CS42888_MUTE_ALL;
- ret = snd_soc_write(codec, CS42888_MUTE, val);
- if (ret < 0)
- dev_err(codec->dev, "i2c write failed\n");
- }
-}
-
-static int cs42888_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_card *card = rtd->card;
- struct snd_soc_dai *tmp_codec_dai;
- struct snd_soc_pcm_runtime *tmp_rtd;
- u32 i;
-
- for (i = 0; i < card->num_rtd; i++) {
- tmp_codec_dai = card->rtd[i].codec_dai;
- tmp_rtd = (struct snd_soc_pcm_runtime *)(card->rtd + i);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- cancel_delayed_work(&tmp_rtd->delayed_work);
- }
- return 0;
-}
-
-static struct snd_soc_dai_ops cs42888_dai_ops = {
- .set_fmt = cs42888_set_dai_fmt,
- .set_sysclk = cs42888_set_dai_sysclk,
- .hw_params = cs42888_hw_params,
- .shutdown = cs42888_shutdown,
- .prepare = cs42888_prepare,
-};
-
-
-static struct snd_soc_dai_driver cs42888_dai = {
- .name = "CS42888",
- .playback = {
- .stream_name = "codec-Playback",
- .channels_min = 2,
- .channels_max = 8,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = CS42888_FORMATS,
- },
- .capture = {
- .stream_name = "codec-Capture",
- .channels_min = 2,
- .channels_max = 4,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = CS42888_FORMATS,
- },
- .ops = &cs42888_dai_ops,
-};
-
-/**
- * cs42888_probe - ASoC probe function
- * @pdev: platform device
- *
- * This function is called when ASoC has all the pieces it needs to
- * instantiate a sound driver.
- */
-static int cs42888_probe(struct snd_soc_codec *codec)
-{
- struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
- int ret, i, val;
-
- cs42888->codec = codec;
- /* setup i2c data ops */
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
- for (i = 0; i < ARRAY_SIZE(cs42888->supplies); i++)
- cs42888->supplies[i].supply = cs42888_supply_names[i];
-
- ret = devm_regulator_bulk_get(codec->dev,
- ARRAY_SIZE(cs42888->supplies), cs42888->supplies);
- if (ret) {
- dev_err(codec->dev, "Failed to request supplies: %d\n",
- ret);
- return ret;
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(cs42888->supplies),
- cs42888->supplies);
- if (ret) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n",
- ret);
- goto err;
- }
- msleep(1);
-
- /* The I2C interface is set up, so pre-fill our register cache */
- ret = cs42888_fill_cache(codec);
- if (ret < 0) {
- dev_err(codec->dev, "failed to fill register cache\n");
- goto err;
- }
-
- /* Enter low power state */
- val = snd_soc_read(codec, CS42888_PWRCTL);
- val |= CS42888_PWRCTL_PDN_MASK;
- ret = snd_soc_write(codec, CS42888_PWRCTL, val);
- if (ret < 0) {
- dev_err(codec->dev, "i2c write failed\n");
- goto err;
- }
-
- /* Disable auto-mute */
- val = snd_soc_read(codec, CS42888_TRANS);
- val &= ~CS42888_TRANS_AMUTE_MASK;
- val &= ~CS42888_TRANS_DAC_SZC_MASK;
- val |= CS42888_TRANS_DAC_SZC_SR;
- ret = snd_soc_write(codec, CS42888_TRANS, val);
- if (ret < 0) {
- dev_err(codec->dev, "i2c write failed\n");
- goto err;
- }
- /* Add the non-DAPM controls */
- snd_soc_add_codec_controls(codec, cs42888_snd_controls,
- ARRAY_SIZE(cs42888_snd_controls));
-
- /* Add DAPM controls */
- cs42888_add_widgets(codec);
- return 0;
-err:
- regulator_bulk_disable(ARRAY_SIZE(cs42888->supplies),
- cs42888->supplies);
- return ret;
-}
-
-/**
- * cs42888_remove - ASoC remove function
- * @pdev: platform device
- *
- * This function is the counterpart to cs42888_probe().
- */
-static int cs42888_remove(struct snd_soc_codec *codec)
-{
- struct cs42888_private *cs42888 = snd_soc_codec_get_drvdata(codec);
-
- regulator_bulk_disable(ARRAY_SIZE(cs42888->supplies),
- cs42888->supplies);
-
- return 0;
-};
-
-/*
- * ASoC codec device structure
- *
- * Assign this variable to the codec_dev field of the machine driver's
- * snd_soc_device structure.
- */
-static struct snd_soc_codec_driver cs42888_driver = {
- .probe = cs42888_probe,
- .remove = cs42888_remove,
- .reg_cache_size = CS42888_NUMREGS + 1,
- .reg_word_size = sizeof(u8),
- .reg_cache_step = 1,
-};
-
-/**
- * cs42888_i2c_probe - initialize the I2C interface of the CS42888
- * @i2c_client: the I2C client object
- * @id: the I2C device ID (ignored)
- *
- * This function is called whenever the I2C subsystem finds a device that
- * matches the device ID given via a prior call to i2c_add_driver().
- */
-static int cs42888_i2c_probe(struct i2c_client *i2c_client,
- const struct i2c_device_id *id)
-{
- struct cs42888_private *cs42888;
- int ret, val;
-
- /* Verify that we have a CS42888 */
- val = i2c_smbus_read_byte_data(i2c_client, CS42888_CHIPID);
- if (val < 0) {
- dev_err(&i2c_client->dev, "Device with ID register %x is not a CS42888", val);
- return -ENODEV;
- }
- /* The top four bits of the chip ID should be 0000. */
- if ((val & CS42888_CHIPID_ID_MASK) != 0x00) {
- dev_err(&i2c_client->dev, "device is not a CS42888\n");
- return -ENODEV;
- }
-
- dev_info(&i2c_client->dev, "found device at i2c address %X\n",
- i2c_client->addr);
- dev_info(&i2c_client->dev, "hardware revision %X\n", val & 0xF);
-
- /* Allocate enough space for the snd_soc_codec structure
- and our private data together. */
- cs42888 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42888_private), GFP_KERNEL);
- if (!cs42888) {
- dev_err(&i2c_client->dev, "could not allocate codec\n");
- return -ENOMEM;
- }
-
- i2c_set_clientdata(i2c_client, cs42888);
-
- cs42888->clk = devm_clk_get(&i2c_client->dev, NULL);
- if (IS_ERR(cs42888->clk)) {
- ret = PTR_ERR(cs42888->clk);
- dev_err(&i2c_client->dev, "Cannot get the clock: %d\n", ret);
- return ret;
- }
-
- cs42888->mclk = clk_get_rate(cs42888->clk);
-
- ret = snd_soc_register_codec(&i2c_client->dev,
- &cs42888_driver, &cs42888_dai, 1);
- if (ret) {
- dev_err(&i2c_client->dev, "Failed to register codec:%d\n", ret);
- return ret;
- }
- return 0;
-}
-
-/**
- * cs42888_i2c_remove - remove an I2C device
- * @i2c_client: the I2C client object
- *
- * This function is the counterpart to cs42888_i2c_probe().
- */
-static int cs42888_i2c_remove(struct i2c_client *i2c_client)
-{
- snd_soc_unregister_codec(&i2c_client->dev);
- return 0;
-}
-
-/*
- * cs42888_i2c_id - I2C device IDs supported by this driver
- */
-static struct i2c_device_id cs42888_i2c_id[] = {
- {"cs42888", 0},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, cs42888_i2c_id);
-
-#ifdef CONFIG_PM
-/* This suspend/resume implementation can handle both - a simple standby
- * where the codec remains powered, and a full suspend, where the voltage
- * domain the codec is connected to is teared down and/or any other hardware
- * reset condition is asserted.
- *
- * The codec's own power saving features are enabled in the suspend callback,
- * and all registers are written back to the hardware when resuming.
- */
-
-static int cs42888_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
-{
- struct cs42888_private *cs42888 = i2c_get_clientdata(client);
- struct snd_soc_codec *codec = cs42888->codec;
- int reg = snd_soc_read(codec, CS42888_PWRCTL) | CS42888_PWRCTL_PDN_MASK;
- return snd_soc_write(codec, CS42888_PWRCTL, reg);
-}
-
-static int cs42888_i2c_resume(struct i2c_client *client)
-{
- struct cs42888_private *cs42888 = i2c_get_clientdata(client);
- struct snd_soc_codec *codec = cs42888->codec;
- int reg;
-
- /* In case the device was put to hard reset during sleep, we need to
- * wait 500ns here before any I2C communication. */
- ndelay(500);
-
- /* first restore the entire register cache ... */
- for (reg = CS42888_FIRSTREG; reg <= CS42888_LASTREG; reg++) {
- u8 val = snd_soc_read(codec, reg);
-
- if (i2c_smbus_write_byte_data(client, reg, val)) {
- dev_err(codec->dev, "i2c write failed\n");
- return -EIO;
- }
- }
-
- /* ... then disable the power-down bits */
- reg = snd_soc_read(codec, CS42888_PWRCTL);
- reg &= ~CS42888_PWRCTL_PDN_MASK;
- return snd_soc_write(codec, CS42888_PWRCTL, reg);
-}
-#else
-#define cs42888_i2c_suspend NULL
-#define cs42888_i2c_resume NULL
-#endif /* CONFIG_PM */
-
-/*
- * cs42888_i2c_driver - I2C device identification
- *
- * This structure tells the I2C subsystem how to identify and support a
- * given I2C device type.
- */
-
-static const struct of_device_id cs42888_dt_ids[] = {
- { .compatible = "cirrus,cs42888", },
- { /* sentinel */ }
-};
-
-static struct i2c_driver cs42888_i2c_driver = {
- .driver = {
- .name = "cs42888",
- .owner = THIS_MODULE,
- .of_match_table = cs42888_dt_ids,
- },
- .probe = cs42888_i2c_probe,
- .remove = cs42888_i2c_remove,
- .suspend = cs42888_i2c_suspend,
- .resume = cs42888_i2c_resume,
- .id_table = cs42888_i2c_id,
-};
-
-module_i2c_driver(cs42888_i2c_driver);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("Cirrus Logic CS42888 ALSA SoC Codec Driver");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42888.h b/sound/soc/codecs/cs42888.h
deleted file mode 100644
index d06d78196b9a..000000000000
--- a/sound/soc/codecs/cs42888.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef _CS42888_H
-#define _CS42888_H
-
-/* CS42888 registers addresses */
-#define CS42888_CHIPID 0x01 /* Chip ID */
-#define CS42888_PWRCTL 0x02 /* Power Control */
-#define CS42888_MODE 0x03 /* Functional Mode */
-#define CS42888_FORMAT 0x04 /* Interface Formats */
-#define CS42888_ADCCTL 0x05 /* ADC Control */
-#define CS42888_TRANS 0x06 /* Transition Control */
-#define CS42888_MUTE 0x07 /* Mute Control */
-#define CS42888_VOLAOUT1 0x08 /* Volume Control AOUT1*/
-#define CS42888_VOLAOUT2 0x09 /* Volume Control AOUT2*/
-#define CS42888_VOLAOUT3 0x0A /* Volume Control AOUT3*/
-#define CS42888_VOLAOUT4 0x0B /* Volume Control AOUT4*/
-#define CS42888_VOLAOUT5 0x0C /* Volume Control AOUT5*/
-#define CS42888_VOLAOUT6 0x0D /* Volume Control AOUT6*/
-#define CS42888_VOLAOUT7 0x0E /* Volume Control AOUT7*/
-#define CS42888_VOLAOUT8 0x0F /* Volume Control AOUT8*/
-#define CS42888_DACINV 0x10 /* DAC Channel Invert */
-#define CS42888_VOLAIN1 0x11 /* Volume Control AIN1 */
-#define CS42888_VOLAIN2 0x12 /* Volume Control AIN2 */
-#define CS42888_VOLAIN3 0x13 /* Volume Control AIN3 */
-#define CS42888_VOLAIN4 0x14 /* Volume Control AIN4 */
-#define CS42888_ADCINV 0x17 /* ADC Channel Invert */
-#define CS42888_STATUSCTL 0x18 /* Status Control */
-#define CS42888_STATUS 0x19 /* Status */
-#define CS42888_STATUSMASK 0x1A /* Status Mask */
-
-#define CS42888_FIRSTREG 0x01
-#define CS42888_LASTREG 0x1A
-#define CS42888_NUMREGS (CS42888_LASTREG - CS42888_FIRSTREG + 1)
-#define CS42888_I2C_INCR 0x80
-
-/* Bit masks for the CS42888 registers */
-#define CS42888_CHIPID_ID_MASK 0xF0
-#define CS42888_CHIPID_REV 0x0F
-#define CS42888_PWRCTL_PDN_ADC2_OFFSET 6
-#define CS42888_PWRCTL_PDN_ADC1_OFFSET 5
-#define CS42888_PWRCTL_PDN_DAC4_OFFSET 4
-#define CS42888_PWRCTL_PDN_DAC3_OFFSET 3
-#define CS42888_PWRCTL_PDN_DAC2_OFFSET 2
-#define CS42888_PWRCTL_PDN_DAC1_OFFSET 1
-#define CS42888_PWRCTL_PDN_OFFSET 0
-#define CS42888_PWRCTL_PDN_ADC2_MASK (1 << CS42888_PWRCTL_PDN_ADC2_OFFSET)
-#define CS42888_PWRCTL_PDN_ADC1_MASK (1 << CS42888_PWRCTL_PDN_ADC1_OFFSET)
-#define CS42888_PWRCTL_PDN_DAC4_MASK (1 << CS42888_PWRCTL_PDN_DAC4_OFFSET)
-#define CS42888_PWRCTL_PDN_DAC3_MASK (1 << CS42888_PWRCTL_PDN_DAC3_OFFSET)
-#define CS42888_PWRCTL_PDN_DAC2_MASK (1 << CS42888_PWRCTL_PDN_DAC2_OFFSET)
-#define CS42888_PWRCTL_PDN_DAC1_MASK (1 << CS42888_PWRCTL_PDN_DAC1_OFFSET)
-#define CS42888_PWRCTL_PDN_MASK (1 << CS42888_PWRCTL_PDN_OFFSET)
-
-#define CS42888_MODE_SPEED_MASK 0xF0
-#define CS42888_MODE_1X 0x00
-#define CS42888_MODE_2X 0x50
-#define CS42888_MODE_4X 0xA0
-#define CS42888_MODE_SLAVE 0xF0
-#define CS42888_MODE_DIV_MASK 0x0E
-#define CS42888_MODE_DIV1 0x00
-#define CS42888_MODE_DIV2 0x02
-#define CS42888_MODE_DIV3 0x04
-#define CS42888_MODE_DIV4 0x06
-#define CS42888_MODE_DIV5 0x08
-
-#define CS42888_FORMAT_FREEZE_OFFSET 7
-#define CS42888_FORMAT_AUX_DIF_OFFSET 6
-#define CS42888_FORMAT_DAC_DIF_OFFSET 3
-#define CS42888_FORMAT_ADC_DIF_OFFSET 0
-#define CS42888_FORMAT_FREEZE_MASK (1 << CS42888_FORMAT_FREEZE_OFFSET)
-#define CS42888_FORMAT_AUX_DIF_MASK (1 << CS42888_FORMAT_AUX_DIF_OFFSET)
-#define CS42888_FORMAT_DAC_DIF_MASK (7 << CS42888_FORMAT_DAC_DIF_OFFSET)
-#define CS42888_FORMAT_ADC_DIF_MASK (7 << CS42888_FORMAT_ADC_DIF_OFFSET)
-
-#define CS42888_TRANS_DAC_SNGVOL_OFFSET 7
-#define CS42888_TRANS_DAC_SZC_OFFSET 5
-#define CS42888_TRANS_AMUTE_OFFSET 4
-#define CS42888_TRANS_MUTE_ADC_SP_OFFSET 3
-#define CS42888_TRANS_ADC_SNGVOL_OFFSET 2
-#define CS42888_TRANS_ADC_SZC_OFFSET 0
-#define CS42888_TRANS_DAC_SNGVOL_MASK (1 << CS42888_TRANS_DAC_SNGVOL_OFFSET)
-#define CS42888_TRANS_DAC_SZC_MASK (3 << CS42888_TRANS_DAC_SZC_OFFSET)
-#define CS42888_TRANS_AMUTE_MASK (1 << CS42888_TRANS_AMUTE_OFFSET)
-#define CS42888_TRANS_MUTE_ADC_SP_MASK (1 << CS42888_TRANS_MUTE_ADC_SP_OFFSET)
-#define CS42888_TRANS_ADC_SNGVOL_MASK (1 << CS42888_TRANS_ADC_SNGVOL_OFFSET)
-#define CS42888_TRANS_ADC_SZC_MASK (3 << CS42888_TRANS_ADC_SZC_OFFSET)
-#define CS42888_TRANS_DAC_SZC_IC (0 << CS42888_TRANS_DAC_SZC_OFFSET)
-#define CS42888_TRANS_DAC_SZC_ZC (1 << CS42888_TRANS_DAC_SZC_OFFSET)
-#define CS42888_TRANS_DAC_SZC_SR (2 << CS42888_TRANS_DAC_SZC_OFFSET)
-#define CS42888_TRANS_DAC_SZC_SRZC (3 << CS42888_TRANS_DAC_SZC_OFFSET)
-
-#define CS42888_MUTE_AOUT8 (0x1 << 7)
-#define CS42888_MUTE_AOUT7 (0x1 << 6)
-#define CS42888_MUTE_AOUT6 (0x1 << 5)
-#define CS42888_MUTE_AOUT5 (0x1 << 4)
-#define CS42888_MUTE_AOUT4 (0x1 << 3)
-#define CS42888_MUTE_AOUT3 (0x1 << 2)
-#define CS42888_MUTE_AOUT2 (0x1 << 1)
-#define CS42888_MUTE_AOUT1 (0x1 << 0)
-#define CS42888_MUTE_ALL (CS42888_MUTE_AOUT1 | CS42888_MUTE_AOUT2 | \
- CS42888_MUTE_AOUT3 | CS42888_MUTE_AOUT4 | \
- CS42888_MUTE_AOUT5 | CS42888_MUTE_AOUT6 | \
- CS42888_MUTE_AOUT7 | CS42888_MUTE_AOUT8)
-
-#define DIF_LEFT_J 0
-#define DIF_I2S 1
-#define DIF_RIGHT_J 2
-#define DIF_TDM 6
-
-
-#endif
diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c
new file mode 100644
index 000000000000..657dce27eade
--- /dev/null
+++ b/sound/soc/codecs/cs42xx8-i2c.c
@@ -0,0 +1,64 @@
+/*
+ * Cirrus Logic CS42448/CS42888 Audio CODEC DAI I2C driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <Guangyu.Chen@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+
+#include "cs42xx8.h"
+
+static int cs42xx8_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ u32 ret = cs42xx8_probe(&i2c->dev,
+ devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config));
+ if (ret)
+ return ret;
+
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
+
+ return 0;
+}
+
+static int cs42xx8_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+ pm_runtime_disable(&i2c->dev);
+
+ return 0;
+}
+
+static struct i2c_device_id cs42xx8_i2c_id[] = {
+ {"cs42448", (kernel_ulong_t)&cs42448_data},
+ {"cs42888", (kernel_ulong_t)&cs42888_data},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
+
+static struct i2c_driver cs42xx8_i2c_driver = {
+ .driver = {
+ .name = "cs42xx8",
+ .owner = THIS_MODULE,
+ .pm = &cs42xx8_pm,
+ },
+ .probe = cs42xx8_i2c_probe,
+ .remove = cs42xx8_i2c_remove,
+ .id_table = cs42xx8_i2c_id,
+};
+
+module_i2c_driver(cs42xx8_i2c_driver);
+
+MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec I2C Driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c
new file mode 100644
index 000000000000..082299a4e2fa
--- /dev/null
+++ b/sound/soc/codecs/cs42xx8.c
@@ -0,0 +1,602 @@
+/*
+ * Cirrus Logic CS42448/CS42888 Audio CODEC Digital Audio Interface (DAI) driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <Guangyu.Chen@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "cs42xx8.h"
+
+#define CS42XX8_NUM_SUPPLIES 4
+static const char *const cs42xx8_supply_names[CS42XX8_NUM_SUPPLIES] = {
+ "VA",
+ "VD",
+ "VLS",
+ "VLC",
+};
+
+#define CS42XX8_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+/* codec private data */
+struct cs42xx8_priv {
+ struct regulator_bulk_data supplies[CS42XX8_NUM_SUPPLIES];
+ const struct cs42xx8_driver_data *drvdata;
+ struct regmap *regmap;
+ struct clk *clk;
+
+ bool slave_mode;
+ unsigned long sysclk;
+};
+
+/* -127.5dB to 0dB with step of 0.5dB */
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
+/* -64dB to 24dB with step of 0.5dB */
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -6400, 50, 0);
+
+static const char *const cs42xx8_adc_single[] = { "Differential", "Single-Ended" };
+static const char *const cs42xx8_szc[] = { "Immediate Change", "Zero Cross",
+ "Soft Ramp", "Soft Ramp on Zero Cross" };
+
+static const struct soc_enum adc1_single_enum =
+ SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 4, 2, cs42xx8_adc_single);
+static const struct soc_enum adc2_single_enum =
+ SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 3, 2, cs42xx8_adc_single);
+static const struct soc_enum adc3_single_enum =
+ SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 2, 2, cs42xx8_adc_single);
+static const struct soc_enum dac_szc_enum =
+ SOC_ENUM_SINGLE(CS42XX8_TXCTL, 5, 4, cs42xx8_szc);
+static const struct soc_enum adc_szc_enum =
+ SOC_ENUM_SINGLE(CS42XX8_TXCTL, 0, 4, cs42xx8_szc);
+
+static const struct snd_kcontrol_new cs42xx8_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("DAC1 Playback Volume", CS42XX8_VOLAOUT1,
+ CS42XX8_VOLAOUT2, 0, 0xff, 1, dac_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Playback Volume", CS42XX8_VOLAOUT3,
+ CS42XX8_VOLAOUT4, 0, 0xff, 1, dac_tlv),
+ SOC_DOUBLE_R_TLV("DAC3 Playback Volume", CS42XX8_VOLAOUT5,
+ CS42XX8_VOLAOUT6, 0, 0xff, 1, dac_tlv),
+ SOC_DOUBLE_R_TLV("DAC4 Playback Volume", CS42XX8_VOLAOUT7,
+ CS42XX8_VOLAOUT8, 0, 0xff, 1, dac_tlv),
+ SOC_DOUBLE_R_S_TLV("ADC1 Capture Volume", CS42XX8_VOLAIN1,
+ CS42XX8_VOLAIN2, 0, -0x80, 0x30, 7, 0, adc_tlv),
+ SOC_DOUBLE_R_S_TLV("ADC2 Capture Volume", CS42XX8_VOLAIN3,
+ CS42XX8_VOLAIN4, 0, -0x80, 0x30, 7, 0, adc_tlv),
+ SOC_DOUBLE("DAC1 Invert Switch", CS42XX8_DACINV, 0, 1, 1, 0),
+ SOC_DOUBLE("DAC2 Invert Switch", CS42XX8_DACINV, 2, 3, 1, 0),
+ SOC_DOUBLE("DAC3 Invert Switch", CS42XX8_DACINV, 4, 5, 1, 0),
+ SOC_DOUBLE("DAC4 Invert Switch", CS42XX8_DACINV, 6, 7, 1, 0),
+ SOC_DOUBLE("ADC1 Invert Switch", CS42XX8_ADCINV, 0, 1, 1, 0),
+ SOC_DOUBLE("ADC2 Invert Switch", CS42XX8_ADCINV, 2, 3, 1, 0),
+ SOC_SINGLE("ADC High-Pass Filter Switch", CS42XX8_ADCCTL, 7, 1, 1),
+ SOC_SINGLE("DAC De-emphasis Switch", CS42XX8_ADCCTL, 5, 1, 0),
+ SOC_ENUM("ADC1 Single Ended Mode Switch", adc1_single_enum),
+ SOC_ENUM("ADC2 Single Ended Mode Switch", adc2_single_enum),
+ SOC_SINGLE("DAC Single Volume Control Switch", CS42XX8_TXCTL, 7, 1, 0),
+ SOC_ENUM("DAC Soft Ramp & Zero Cross Control Switch", dac_szc_enum),
+ SOC_SINGLE("DAC Auto Mute Switch", CS42XX8_TXCTL, 4, 1, 0),
+ SOC_SINGLE("Mute ADC Serial Port Switch", CS42XX8_TXCTL, 3, 1, 0),
+ SOC_SINGLE("ADC Single Volume Control Switch", CS42XX8_TXCTL, 2, 1, 0),
+ SOC_ENUM("ADC Soft Ramp & Zero Cross Control Switch", adc_szc_enum),
+};
+
+static const struct snd_kcontrol_new cs42xx8_adc3_snd_controls[] = {
+ SOC_DOUBLE_R_S_TLV("ADC3 Capture Volume", CS42XX8_VOLAIN5,
+ CS42XX8_VOLAIN6, 0, -0x80, 0x30, 7, 0, adc_tlv),
+ SOC_DOUBLE("ADC3 Invert Switch", CS42XX8_ADCINV, 4, 5, 1, 0),
+ SOC_ENUM("ADC3 Single Ended Mode Switch", adc3_single_enum),
+};
+
+static const struct snd_soc_dapm_widget cs42xx8_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("DAC1", "Playback", CS42XX8_PWRCTL, 1, 1),
+ SND_SOC_DAPM_DAC("DAC2", "Playback", CS42XX8_PWRCTL, 2, 1),
+ SND_SOC_DAPM_DAC("DAC3", "Playback", CS42XX8_PWRCTL, 3, 1),
+ SND_SOC_DAPM_DAC("DAC4", "Playback", CS42XX8_PWRCTL, 4, 1),
+
+ SND_SOC_DAPM_OUTPUT("AOUT1L"),
+ SND_SOC_DAPM_OUTPUT("AOUT1R"),
+ SND_SOC_DAPM_OUTPUT("AOUT2L"),
+ SND_SOC_DAPM_OUTPUT("AOUT2R"),
+ SND_SOC_DAPM_OUTPUT("AOUT3L"),
+ SND_SOC_DAPM_OUTPUT("AOUT3R"),
+ SND_SOC_DAPM_OUTPUT("AOUT4L"),
+ SND_SOC_DAPM_OUTPUT("AOUT4R"),
+
+ SND_SOC_DAPM_ADC("ADC1", "Capture", CS42XX8_PWRCTL, 5, 1),
+ SND_SOC_DAPM_ADC("ADC2", "Capture", CS42XX8_PWRCTL, 6, 1),
+
+ SND_SOC_DAPM_INPUT("AIN1L"),
+ SND_SOC_DAPM_INPUT("AIN1R"),
+ SND_SOC_DAPM_INPUT("AIN2L"),
+ SND_SOC_DAPM_INPUT("AIN2R"),
+
+ SND_SOC_DAPM_SUPPLY("PWR", CS42XX8_PWRCTL, 0, 1, NULL, 0),
+};
+
+static const struct snd_soc_dapm_widget cs42xx8_adc3_dapm_widgets[] = {
+ SND_SOC_DAPM_ADC("ADC3", "Capture", CS42XX8_PWRCTL, 7, 1),
+
+ SND_SOC_DAPM_INPUT("AIN3L"),
+ SND_SOC_DAPM_INPUT("AIN3R"),
+};
+
+static const struct snd_soc_dapm_route cs42xx8_dapm_routes[] = {
+ /* Playback */
+ { "AOUT1L", NULL, "DAC1" },
+ { "AOUT1R", NULL, "DAC1" },
+ { "DAC1", NULL, "PWR" },
+
+ { "AOUT2L", NULL, "DAC2" },
+ { "AOUT2R", NULL, "DAC2" },
+ { "DAC2", NULL, "PWR" },
+
+ { "AOUT3L", NULL, "DAC3" },
+ { "AOUT3R", NULL, "DAC3" },
+ { "DAC3", NULL, "PWR" },
+
+ { "AOUT4L", NULL, "DAC4" },
+ { "AOUT4R", NULL, "DAC4" },
+ { "DAC4", NULL, "PWR" },
+
+ /* Capture */
+ { "ADC1", NULL, "AIN1L" },
+ { "ADC1", NULL, "AIN1R" },
+ { "ADC1", NULL, "PWR" },
+
+ { "ADC2", NULL, "AIN2L" },
+ { "ADC2", NULL, "AIN2R" },
+ { "ADC2", NULL, "PWR" },
+};
+
+static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = {
+ /* Capture */
+ { "ADC3", NULL, "AIN3L" },
+ { "ADC3", NULL, "AIN3R" },
+ { "ADC3", NULL, "PWR" },
+};
+
+struct cs42xx8_ratios {
+ unsigned int ratio;
+ unsigned char speed;
+ unsigned char mclk;
+};
+
+static const struct cs42xx8_ratios cs42xx8_ratios[] = {
+ { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) },
+ { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) },
+ { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) },
+ { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) },
+ { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) },
+ { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) },
+ { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) },
+ { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) },
+ { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) }
+};
+
+static int cs42xx8_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 cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+
+ cs42xx8->sysclk = freq;
+
+ return 0;
+}
+
+static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int format)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+ u32 val;
+
+ /* Set DAI format */
+ switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_LEFT_J:
+ val = CS42XX8_INTF_DAC_DIF_LEFTJ | CS42XX8_INTF_ADC_DIF_LEFTJ;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ val = CS42XX8_INTF_DAC_DIF_I2S | CS42XX8_INTF_ADC_DIF_I2S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported dai format\n");
+ return -EINVAL;
+ }
+
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_INTF,
+ CS42XX8_INTF_DAC_DIF_MASK |
+ CS42XX8_INTF_ADC_DIF_MASK, val);
+
+ /* Set master/slave audio interface */
+ switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ cs42xx8->slave_mode = true;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ cs42xx8->slave_mode = false;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported master/slave mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ u32 ratio = cs42xx8->sysclk / params_rate(params);
+ u32 i, fm, val, mask;
+
+ for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
+ if (cs42xx8_ratios[i].ratio == ratio)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(cs42xx8_ratios)) {
+ dev_err(codec->dev, "unsupported sysclk ratio\n");
+ return -EINVAL;
+ }
+
+ mask = CS42XX8_FUNCMOD_MFREQ_MASK;
+ val = cs42xx8_ratios[i].mclk;
+
+ fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed;
+
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
+ CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask,
+ CS42XX8_FUNCMOD_xC_FM(tx, fm) | val);
+
+ return 0;
+}
+
+static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+
+ regmap_update_bits(cs42xx8->regmap, CS42XX8_DACMUTE,
+ CS42XX8_DACMUTE_ALL, mute ? CS42XX8_DACMUTE_ALL : 0);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops cs42xx8_dai_ops = {
+ .set_fmt = cs42xx8_set_dai_fmt,
+ .set_sysclk = cs42xx8_set_dai_sysclk,
+ .hw_params = cs42xx8_hw_params,
+ .digital_mute = cs42xx8_digital_mute,
+};
+
+static struct snd_soc_dai_driver cs42xx8_dai = {
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = CS42XX8_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = CS42XX8_FORMATS,
+ },
+ .ops = &cs42xx8_dai_ops,
+};
+
+static const struct reg_default cs42xx8_reg[] = {
+ { 0x01, 0x01 }, /* Chip I.D. and Revision Register */
+ { 0x02, 0x00 }, /* Power Control */
+ { 0x03, 0xF0 }, /* Functional Mode */
+ { 0x04, 0x46 }, /* Interface Formats */
+ { 0x05, 0x00 }, /* ADC Control & DAC De-Emphasis */
+ { 0x06, 0x10 }, /* Transition Control */
+ { 0x07, 0x00 }, /* DAC Channel Mute */
+ { 0x08, 0x00 }, /* Volume Control AOUT1 */
+ { 0x09, 0x00 }, /* Volume Control AOUT2 */
+ { 0x0a, 0x00 }, /* Volume Control AOUT3 */
+ { 0x0b, 0x00 }, /* Volume Control AOUT4 */
+ { 0x0c, 0x00 }, /* Volume Control AOUT5 */
+ { 0x0d, 0x00 }, /* Volume Control AOUT6 */
+ { 0x0e, 0x00 }, /* Volume Control AOUT7 */
+ { 0x0f, 0x00 }, /* Volume Control AOUT8 */
+ { 0x10, 0x00 }, /* DAC Channel Invert */
+ { 0x11, 0x00 }, /* Volume Control AIN1 */
+ { 0x12, 0x00 }, /* Volume Control AIN2 */
+ { 0x13, 0x00 }, /* Volume Control AIN3 */
+ { 0x14, 0x00 }, /* Volume Control AIN4 */
+ { 0x15, 0x00 }, /* Volume Control AIN5 */
+ { 0x16, 0x00 }, /* Volume Control AIN6 */
+ { 0x17, 0x00 }, /* ADC Channel Invert */
+ { 0x18, 0x00 }, /* Status Control */
+ { 0x1a, 0x00 }, /* Status Mask */
+ { 0x1b, 0x00 }, /* MUTEC Pin Control */
+};
+
+static bool cs42xx8_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42XX8_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs42xx8_writeable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42XX8_CHIPID:
+ case CS42XX8_STATUS:
+ return false;
+ default:
+ return true;
+ }
+}
+
+const struct regmap_config cs42xx8_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CS42XX8_LASTREG,
+ .reg_defaults = cs42xx8_reg,
+ .num_reg_defaults = ARRAY_SIZE(cs42xx8_reg),
+ .volatile_reg = cs42xx8_volatile_register,
+ .writeable_reg = cs42xx8_writeable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs42xx8_regmap_config);
+
+static int cs42xx8_codec_probe(struct snd_soc_codec *codec)
+{
+ struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ switch (cs42xx8->drvdata->num_adcs) {
+ case 3:
+ snd_soc_add_codec_controls(codec, cs42xx8_adc3_snd_controls,
+ ARRAY_SIZE(cs42xx8_adc3_snd_controls));
+ snd_soc_dapm_new_controls(dapm, cs42xx8_adc3_dapm_widgets,
+ ARRAY_SIZE(cs42xx8_adc3_dapm_widgets));
+ snd_soc_dapm_add_routes(dapm, cs42xx8_adc3_dapm_routes,
+ ARRAY_SIZE(cs42xx8_adc3_dapm_routes));
+ break;
+ default:
+ break;
+ }
+
+ /* Mute all DAC channels */
+ regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE, CS42XX8_DACMUTE_ALL);
+
+ return 0;
+}
+
+static const struct snd_soc_codec_driver cs42xx8_driver = {
+ .probe = cs42xx8_codec_probe,
+ .idle_bias_off = true,
+
+ .controls = cs42xx8_snd_controls,
+ .num_controls = ARRAY_SIZE(cs42xx8_snd_controls),
+ .dapm_widgets = cs42xx8_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets),
+ .dapm_routes = cs42xx8_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes),
+};
+
+const struct cs42xx8_driver_data cs42448_data = {
+ .name = "cs42448",
+ .num_adcs = 3,
+};
+EXPORT_SYMBOL_GPL(cs42448_data);
+
+const struct cs42xx8_driver_data cs42888_data = {
+ .name = "cs42888",
+ .num_adcs = 2,
+};
+EXPORT_SYMBOL_GPL(cs42888_data);
+
+const struct of_device_id cs42xx8_of_match[] = {
+ { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
+ { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
+EXPORT_SYMBOL_GPL(cs42xx8_of_match);
+
+int cs42xx8_probe(struct device *dev, struct regmap *regmap)
+{
+ const struct of_device_id *of_id = of_match_device(cs42xx8_of_match, dev);
+ struct cs42xx8_priv *cs42xx8;
+ int ret, val, i;
+
+ cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL);
+ if (cs42xx8 == NULL)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, cs42xx8);
+
+ if (of_id)
+ cs42xx8->drvdata = of_id->data;
+
+ if (!cs42xx8->drvdata) {
+ dev_err(dev, "failed to find driver data\n");
+ return -EINVAL;
+ }
+
+ cs42xx8->clk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(cs42xx8->clk)) {
+ dev_err(dev, "failed to get the clock: %ld\n",
+ PTR_ERR(cs42xx8->clk));
+ return -EINVAL;
+ }
+
+ cs42xx8->sysclk = clk_get_rate(cs42xx8->clk);
+
+ for (i = 0; i < ARRAY_SIZE(cs42xx8->supplies); i++)
+ cs42xx8->supplies[i].supply = cs42xx8_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev,
+ ARRAY_SIZE(cs42xx8->supplies), cs42xx8->supplies);
+ if (ret) {
+ dev_err(dev, "failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+ if (ret) {
+ dev_err(dev, "failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ /* Make sure hardware reset done */
+ msleep(5);
+
+ cs42xx8->regmap = regmap;
+ if (IS_ERR(cs42xx8->regmap)) {
+ ret = PTR_ERR(cs42xx8->regmap);
+ dev_err(dev, "failed to allocate regmap: %d\n", ret);
+ goto err_enable;
+ }
+
+ /*
+ * We haven't marked the chip revision as volatile due to
+ * sharing a register with the right input volume; explicitly
+ * bypass the cache to read it.
+ */
+ regcache_cache_bypass(cs42xx8->regmap, true);
+
+ /* Validate the chip ID */
+ regmap_read(cs42xx8->regmap, CS42XX8_CHIPID, &val);
+ if (val < 0) {
+ dev_err(dev, "failed to get device ID: %x", val);
+ ret = -EINVAL;
+ goto err_enable;
+ }
+
+ /* The top four bits of the chip ID should be 0000 */
+ if ((val & CS42XX8_CHIPID_CHIP_ID_MASK) != 0x00) {
+ dev_err(dev, "unmatched chip ID: %d\n",
+ val & CS42XX8_CHIPID_CHIP_ID_MASK);
+ ret = -EINVAL;
+ goto err_enable;
+ }
+
+ dev_info(dev, "found device, revision %X\n",
+ val & CS42XX8_CHIPID_REV_ID_MASK);
+
+ regcache_cache_bypass(cs42xx8->regmap, false);
+
+ cs42xx8_dai.name = cs42xx8->drvdata->name;
+
+ /* Each adc supports stereo input */
+ cs42xx8_dai.capture.channels_max = cs42xx8->drvdata->num_adcs * 2;
+
+ ret = snd_soc_register_codec(dev, &cs42xx8_driver, &cs42xx8_dai, 1);
+ if (ret) {
+ dev_err(dev, "failed to register codec:%d\n", ret);
+ goto err_enable;
+ }
+
+ regcache_cache_only(cs42xx8->regmap, true);
+
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cs42xx8_probe);
+
+#ifdef CONFIG_PM_RUNTIME
+static int cs42xx8_runtime_resume(struct device *dev)
+{
+ struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(cs42xx8->clk);
+ if (ret) {
+ dev_err(dev, "failed to enable mclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+ if (ret) {
+ dev_err(dev, "failed to enable supplies: %d\n", ret);
+ goto err_clk;
+ }
+
+ /* Make sure hardware reset done */
+ msleep(5);
+
+ regcache_cache_only(cs42xx8->regmap, false);
+
+ ret = regcache_sync(cs42xx8->regmap);
+ if (ret) {
+ dev_err(dev, "failed to sync regmap: %d\n", ret);
+ goto err_bulk;
+ }
+
+ return 0;
+
+err_bulk:
+ regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+err_clk:
+ clk_disable_unprepare(cs42xx8->clk);
+
+ return ret;
+}
+
+static int cs42xx8_runtime_suspend(struct device *dev)
+{
+ struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev);
+
+ regcache_cache_only(cs42xx8->regmap, true);
+
+ regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies),
+ cs42xx8->supplies);
+
+ clk_disable_unprepare(cs42xx8->clk);
+
+ return 0;
+}
+#endif
+
+const struct dev_pm_ops cs42xx8_pm = {
+ SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL)
+};
+EXPORT_SYMBOL_GPL(cs42xx8_pm);
+
+MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec Driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h
new file mode 100644
index 000000000000..da0b94aee419
--- /dev/null
+++ b/sound/soc/codecs/cs42xx8.h
@@ -0,0 +1,238 @@
+/*
+ * cs42xx8.h - Cirrus Logic CS42448/CS42888 Audio CODEC driver header file
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <Guangyu.Chen@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef _CS42XX8_H
+#define _CS42XX8_H
+
+struct cs42xx8_driver_data {
+ char name[32];
+ int num_adcs;
+};
+
+extern const struct dev_pm_ops cs42xx8_pm;
+extern const struct cs42xx8_driver_data cs42448_data;
+extern const struct cs42xx8_driver_data cs42888_data;
+extern const struct regmap_config cs42xx8_regmap_config;
+int cs42xx8_probe(struct device *dev, struct regmap *regmap);
+
+/* CS42888 register map */
+#define CS42XX8_CHIPID 0x01 /* Chip ID */
+#define CS42XX8_PWRCTL 0x02 /* Power Control */
+#define CS42XX8_FUNCMOD 0x03 /* Functional Mode */
+#define CS42XX8_INTF 0x04 /* Interface Formats */
+#define CS42XX8_ADCCTL 0x05 /* ADC Control */
+#define CS42XX8_TXCTL 0x06 /* Transition Control */
+#define CS42XX8_DACMUTE 0x07 /* DAC Mute Control */
+#define CS42XX8_VOLAOUT1 0x08 /* Volume Control AOUT1 */
+#define CS42XX8_VOLAOUT2 0x09 /* Volume Control AOUT2 */
+#define CS42XX8_VOLAOUT3 0x0A /* Volume Control AOUT3 */
+#define CS42XX8_VOLAOUT4 0x0B /* Volume Control AOUT4 */
+#define CS42XX8_VOLAOUT5 0x0C /* Volume Control AOUT5 */
+#define CS42XX8_VOLAOUT6 0x0D /* Volume Control AOUT6 */
+#define CS42XX8_VOLAOUT7 0x0E /* Volume Control AOUT7 */
+#define CS42XX8_VOLAOUT8 0x0F /* Volume Control AOUT8 */
+#define CS42XX8_DACINV 0x10 /* DAC Channel Invert */
+#define CS42XX8_VOLAIN1 0x11 /* Volume Control AIN1 */
+#define CS42XX8_VOLAIN2 0x12 /* Volume Control AIN2 */
+#define CS42XX8_VOLAIN3 0x13 /* Volume Control AIN3 */
+#define CS42XX8_VOLAIN4 0x14 /* Volume Control AIN4 */
+#define CS42XX8_VOLAIN5 0x15 /* Volume Control AIN5 */
+#define CS42XX8_VOLAIN6 0x16 /* Volume Control AIN6 */
+#define CS42XX8_ADCINV 0x17 /* ADC Channel Invert */
+#define CS42XX8_STATUSCTL 0x18 /* Status Control */
+#define CS42XX8_STATUS 0x19 /* Status */
+#define CS42XX8_STATUSM 0x1A /* Status Mask */
+#define CS42XX8_MUTEC 0x1B /* MUTEC Pin Control */
+
+#define CS42XX8_FIRSTREG CS42XX8_CHIPID
+#define CS42XX8_LASTREG CS42XX8_MUTEC
+#define CS42XX8_NUMREGS (CS42XX8_LASTREG - CS42XX8_FIRSTREG + 1)
+#define CS42XX8_I2C_INCR 0x80
+
+/* Chip I.D. and Revision Register (Address 01h) */
+#define CS42XX8_CHIPID_CHIP_ID_MASK 0xF0
+#define CS42XX8_CHIPID_REV_ID_MASK 0x0F
+
+/* Power Control (Address 02h) */
+#define CS42XX8_PWRCTL_PDN_ADC3_SHIFT 7
+#define CS42XX8_PWRCTL_PDN_ADC3_MASK (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC3 (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC2_SHIFT 6
+#define CS42XX8_PWRCTL_PDN_ADC2_MASK (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC2 (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC1_SHIFT 5
+#define CS42XX8_PWRCTL_PDN_ADC1_MASK (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT)
+#define CS42XX8_PWRCTL_PDN_ADC1 (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC4_SHIFT 4
+#define CS42XX8_PWRCTL_PDN_DAC4_MASK (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC4 (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC3_SHIFT 3
+#define CS42XX8_PWRCTL_PDN_DAC3_MASK (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC3 (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC2_SHIFT 2
+#define CS42XX8_PWRCTL_PDN_DAC2_MASK (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC2 (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC1_SHIFT 1
+#define CS42XX8_PWRCTL_PDN_DAC1_MASK (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT)
+#define CS42XX8_PWRCTL_PDN_DAC1 (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT)
+#define CS42XX8_PWRCTL_PDN_SHIFT 0
+#define CS42XX8_PWRCTL_PDN_MASK (1 << CS42XX8_PWRCTL_PDN_SHIFT)
+#define CS42XX8_PWRCTL_PDN (1 << CS42XX8_PWRCTL_PDN_SHIFT)
+
+/* Functional Mode (Address 03h) */
+#define CS42XX8_FUNCMOD_DAC_FM_SHIFT 6
+#define CS42XX8_FUNCMOD_DAC_FM_WIDTH 2
+#define CS42XX8_FUNCMOD_DAC_FM_MASK (((1 << CS42XX8_FUNCMOD_DAC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_DAC_FM_SHIFT)
+#define CS42XX8_FUNCMOD_DAC_FM(v) ((v) << CS42XX8_FUNCMOD_DAC_FM_SHIFT)
+#define CS42XX8_FUNCMOD_ADC_FM_SHIFT 4
+#define CS42XX8_FUNCMOD_ADC_FM_WIDTH 2
+#define CS42XX8_FUNCMOD_ADC_FM_MASK (((1 << CS42XX8_FUNCMOD_ADC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_ADC_FM_SHIFT)
+#define CS42XX8_FUNCMOD_ADC_FM(v) ((v) << CS42XX8_FUNCMOD_ADC_FM_SHIFT)
+#define CS42XX8_FUNCMOD_xC_FM_MASK(x) ((x) ? CS42XX8_FUNCMOD_DAC_FM_MASK : CS42XX8_FUNCMOD_ADC_FM_MASK)
+#define CS42XX8_FUNCMOD_xC_FM(x, v) ((x) ? CS42XX8_FUNCMOD_DAC_FM(v) : CS42XX8_FUNCMOD_ADC_FM(v))
+#define CS42XX8_FUNCMOD_MFREQ_SHIFT 1
+#define CS42XX8_FUNCMOD_MFREQ_WIDTH 3
+#define CS42XX8_FUNCMOD_MFREQ_MASK (((1 << CS42XX8_FUNCMOD_MFREQ_WIDTH) - 1) << CS42XX8_FUNCMOD_MFREQ_SHIFT)
+#define CS42XX8_FUNCMOD_MFREQ_256(s) ((0 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+#define CS42XX8_FUNCMOD_MFREQ_384(s) ((1 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+#define CS42XX8_FUNCMOD_MFREQ_512(s) ((2 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+#define CS42XX8_FUNCMOD_MFREQ_768(s) ((3 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+#define CS42XX8_FUNCMOD_MFREQ_1024(s) ((4 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1))
+
+#define CS42XX8_FM_SINGLE 0
+#define CS42XX8_FM_DOUBLE 1
+#define CS42XX8_FM_QUAD 2
+#define CS42XX8_FM_AUTO 3
+
+/* Interface Formats (Address 04h) */
+#define CS42XX8_INTF_FREEZE_SHIFT 7
+#define CS42XX8_INTF_FREEZE_MASK (1 << CS42XX8_INTF_FREEZE_SHIFT)
+#define CS42XX8_INTF_FREEZE (1 << CS42XX8_INTF_FREEZE_SHIFT)
+#define CS42XX8_INTF_AUX_DIF_SHIFT 6
+#define CS42XX8_INTF_AUX_DIF_MASK (1 << CS42XX8_INTF_AUX_DIF_SHIFT)
+#define CS42XX8_INTF_AUX_DIF (1 << CS42XX8_INTF_AUX_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_SHIFT 3
+#define CS42XX8_INTF_DAC_DIF_WIDTH 3
+#define CS42XX8_INTF_DAC_DIF_MASK (((1 << CS42XX8_INTF_DAC_DIF_WIDTH) - 1) << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_LEFTJ (0 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_I2S (1 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_SHIFT 0
+#define CS42XX8_INTF_ADC_DIF_WIDTH 3
+#define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_LEFTJ (0 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_I2S (1 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT)
+#define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT)
+
+/* ADC Control & DAC De-Emphasis (Address 05h) */
+#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7
+#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_MASK (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT)
+#define CS42XX8_ADCCTL_ADC_HPF_FREEZE (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT)
+#define CS42XX8_ADCCTL_DAC_DEM_SHIFT 5
+#define CS42XX8_ADCCTL_DAC_DEM_MASK (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT)
+#define CS42XX8_ADCCTL_DAC_DEM (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT)
+#define CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT 4
+#define CS42XX8_ADCCTL_ADC1_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC1_SINGLE (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT 3
+#define CS42XX8_ADCCTL_ADC2_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC2_SINGLE (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT 2
+#define CS42XX8_ADCCTL_ADC3_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_ADC3_SINGLE (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT)
+#define CS42XX8_ADCCTL_AIN5_MUX_SHIFT 1
+#define CS42XX8_ADCCTL_AIN5_MUX_MASK (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT)
+#define CS42XX8_ADCCTL_AIN5_MUX (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT)
+#define CS42XX8_ADCCTL_AIN6_MUX_SHIFT 0
+#define CS42XX8_ADCCTL_AIN6_MUX_MASK (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT)
+#define CS42XX8_ADCCTL_AIN6_MUX (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT)
+
+/* Transition Control (Address 06h) */
+#define CS42XX8_TXCTL_DAC_SNGVOL_SHIFT 7
+#define CS42XX8_TXCTL_DAC_SNGVOL_MASK (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT)
+#define CS42XX8_TXCTL_DAC_SNGVOL (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_SHIFT 5
+#define CS42XX8_TXCTL_DAC_SZC_WIDTH 2
+#define CS42XX8_TXCTL_DAC_SZC_MASK (((1 << CS42XX8_TXCTL_DAC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_IC (0 << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_ZC (1 << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_SR (2 << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_DAC_SZC_SRZC (3 << CS42XX8_TXCTL_DAC_SZC_SHIFT)
+#define CS42XX8_TXCTL_AMUTE_SHIFT 4
+#define CS42XX8_TXCTL_AMUTE_MASK (1 << CS42XX8_TXCTL_AMUTE_SHIFT)
+#define CS42XX8_TXCTL_AMUTE (1 << CS42XX8_TXCTL_AMUTE_SHIFT)
+#define CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT 3
+#define CS42XX8_TXCTL_MUTE_ADC_SP_MASK (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT)
+#define CS42XX8_TXCTL_MUTE_ADC_SP (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT)
+#define CS42XX8_TXCTL_ADC_SNGVOL_SHIFT 2
+#define CS42XX8_TXCTL_ADC_SNGVOL_MASK (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT)
+#define CS42XX8_TXCTL_ADC_SNGVOL (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_SHIFT 0
+#define CS42XX8_TXCTL_ADC_SZC_MASK (((1 << CS42XX8_TXCTL_ADC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_IC (0 << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_ZC (1 << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_SR (2 << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+#define CS42XX8_TXCTL_ADC_SZC_SRZC (3 << CS42XX8_TXCTL_ADC_SZC_SHIFT)
+
+/* DAC Channel Mute (Address 07h) */
+#define CS42XX8_DACMUTE_AOUT(n) (0x1 << n)
+#define CS42XX8_DACMUTE_ALL 0xff
+
+/* Status Control (Address 18h)*/
+#define CS42XX8_STATUSCTL_INI_SHIFT 2
+#define CS42XX8_STATUSCTL_INI_WIDTH 2
+#define CS42XX8_STATUSCTL_INI_MASK (((1 << CS42XX8_STATUSCTL_INI_WIDTH) - 1) << CS42XX8_STATUSCTL_INI_SHIFT)
+#define CS42XX8_STATUSCTL_INT_ACTIVE_HIGH (0 << CS42XX8_STATUSCTL_INI_SHIFT)
+#define CS42XX8_STATUSCTL_INT_ACTIVE_LOW (1 << CS42XX8_STATUSCTL_INI_SHIFT)
+#define CS42XX8_STATUSCTL_INT_OPEN_DRAIN (2 << CS42XX8_STATUSCTL_INI_SHIFT)
+
+/* Status (Address 19h)*/
+#define CS42XX8_STATUS_DAC_CLK_ERR_SHIFT 4
+#define CS42XX8_STATUS_DAC_CLK_ERR_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_SHIFT)
+#define CS42XX8_STATUS_ADC_CLK_ERR_SHIFT 3
+#define CS42XX8_STATUS_ADC_CLK_ERR_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_SHIFT)
+#define CS42XX8_STATUS_ADC3_OVFL_SHIFT 2
+#define CS42XX8_STATUS_ADC3_OVFL_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_SHIFT)
+#define CS42XX8_STATUS_ADC2_OVFL_SHIFT 1
+#define CS42XX8_STATUS_ADC2_OVFL_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_SHIFT)
+#define CS42XX8_STATUS_ADC1_OVFL_SHIFT 0
+#define CS42XX8_STATUS_ADC1_OVFL_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_SHIFT)
+
+/* Status Mask (Address 1Ah) */
+#define CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT 4
+#define CS42XX8_STATUS_DAC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT)
+#define CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT 3
+#define CS42XX8_STATUS_ADC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT)
+#define CS42XX8_STATUS_ADC3_OVFL_M_SHIFT 2
+#define CS42XX8_STATUS_ADC3_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_M_SHIFT)
+#define CS42XX8_STATUS_ADC2_OVFL_M_SHIFT 1
+#define CS42XX8_STATUS_ADC2_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_M_SHIFT)
+#define CS42XX8_STATUS_ADC1_OVFL_M_SHIFT 0
+#define CS42XX8_STATUS_ADC1_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_M_SHIFT)
+
+/* MUTEC Pin Control (Address 1Bh) */
+#define CS42XX8_MUTEC_MCPOLARITY_SHIFT 1
+#define CS42XX8_MUTEC_MCPOLARITY_MASK (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT)
+#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_LOW (0 << CS42XX8_MUTEC_MCPOLARITY_SHIFT)
+#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_HIGH (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT)
+#define CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT 0
+#define CS42XX8_MUTEC_MUTEC_ACTIVE_MASK (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT)
+#define CS42XX8_MUTEC_MUTEC_ACTIVE (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT)
+#endif /* _CS42XX8_H */
diff --git a/sound/soc/fsl/imx-cs42888.c b/sound/soc/fsl/imx-cs42888.c
index 3750cd917465..357933ecf989 100644
--- a/sound/soc/fsl/imx-cs42888.c
+++ b/sound/soc/fsl/imx-cs42888.c
@@ -132,9 +132,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"AIN2L", NULL, "Line In Jack"},
{"AIN2R", NULL, "Line In Jack"},
{"esai-Playback", NULL, "asrc-Playback"},
- {"codec-Playback", NULL, "esai-Playback"},/* dai route for be and fe */
+ {"Playback", NULL, "esai-Playback"},/* dai route for be and fe */
{"asrc-Capture", NULL, "esai-Capture"},
- {"esai-Capture", NULL, "codec-Capture"},
+ {"esai-Capture", NULL, "Capture"},
};
static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -158,7 +158,7 @@ static struct snd_soc_dai_link imx_cs42888_dai[] = {
{
.name = "HiFi",
.stream_name = "HiFi",
- .codec_dai_name = "CS42888",
+ .codec_dai_name = "cs42888",
.ops = &imx_cs42888_surround_ops,
},
{
@@ -171,7 +171,7 @@ static struct snd_soc_dai_link imx_cs42888_dai[] = {
{
.name = "HiFi-ASRC-BE",
.stream_name = "HiFi-ASRC-BE",
- .codec_dai_name = "CS42888",
+ .codec_dai_name = "cs42888",
.platform_name = "snd-soc-dummy",
.no_pcm = 1,
.ops = &imx_cs42888_surround_ops_be,