]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'sound-asoc/for-next'
authorThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:36:06 +0000 (14:36 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:36:06 +0000 (14:36 +0200)
1  2 
sound/soc/atmel/atmel-pcm.c
sound/soc/codecs/mc13783.c
sound/soc/codecs/tas5086.c
sound/soc/fsl/imx-wm8962.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/tegra/tegra30_ahub.c
sound/soc/tegra/tegra30_i2s.c

index fbb87e3f10193c1077596e90b6bb7f73d8fb215c,612e5801003f018a27e3670f5a7e0a7bacac416d..8ae3fa5ac60a5fe9c59460663365c28827548163
@@@ -50,7 -50,7 +50,7 @@@ static int atmel_pcm_preallocate_dma_bu
        buf->area = dma_alloc_coherent(pcm->card->dev, size,
                        &buf->addr, GFP_KERNEL);
        pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%zu\n",
-                       (void *)buf->area, (void *)buf->addr, size);
+                       (void *)buf->area, (void *)(long)buf->addr, size);
  
        if (!buf->area)
                return -ENOMEM;
@@@ -68,15 -68,18 +68,15 @@@ int atmel_pcm_mmap(struct snd_pcm_subst
  }
  EXPORT_SYMBOL_GPL(atmel_pcm_mmap);
  
 -static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
 -
  int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
  {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
 -      int ret = 0;
 +      int ret;
  
 -      if (!card->dev->dma_mask)
 -              card->dev->dma_mask = &atmel_pcm_dmamask;
 -      if (!card->dev->coherent_dma_mask)
 -              card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 +      ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
 +      if (ret)
 +              return ret;
  
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
index 154433084708f86d3f0ce06a8e52c44121630bd5,f5472adee674821435eb46d28c3149658c77a94d..bae60164c7b7355408ab77676daa680bcb5946b0
  #include <sound/soc.h>
  #include <sound/initval.h>
  #include <sound/soc-dapm.h>
+ #include <linux/regmap.h>
  
  #include "mc13783.h"
  
- #define MC13783_AUDIO_RX0     36
- #define MC13783_AUDIO_RX1     37
- #define MC13783_AUDIO_TX      38
- #define MC13783_SSI_NETWORK   39
- #define MC13783_AUDIO_CODEC   40
- #define MC13783_AUDIO_DAC     41
  #define AUDIO_RX0_ALSPEN              (1 << 5)
  #define AUDIO_RX0_ALSPSEL             (1 << 7)
  #define AUDIO_RX0_ADDCDC              (1 << 21)
  
  struct mc13783_priv {
        struct mc13xxx *mc13xxx;
+       struct regmap *regmap;
  
        enum mc13783_ssi_port adc_ssi_port;
        enum mc13783_ssi_port dac_ssi_port;
  };
  
- static unsigned int mc13783_read(struct snd_soc_codec *codec,
-       unsigned int reg)
- {
-       struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
-       unsigned int value = 0;
-       mc13xxx_lock(priv->mc13xxx);
-       mc13xxx_reg_read(priv->mc13xxx, reg, &value);
-       mc13xxx_unlock(priv->mc13xxx);
-       return value;
- }
- static int mc13783_write(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int value)
- {
-       struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
-       int ret;
-       mc13xxx_lock(priv->mc13xxx);
-       ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
-       /* include errata fix for spi audio problems */
-       if (reg == MC13783_AUDIO_CODEC || reg == MC13783_AUDIO_DAC)
-               ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
-       mc13xxx_unlock(priv->mc13xxx);
-       return ret;
- }
  /* Mapping between sample rates and register value */
  static unsigned int mc13783_rates[] = {
        8000, 11025, 12000, 16000,
@@@ -382,7 -343,7 +343,7 @@@ static int mc13783_set_tdm_slot_dac(str
                break;
        default:
                return -EINVAL;
 -      };
 +      }
  
        snd_soc_update_bits(codec, MC13783_SSI_NETWORK, mask, val);
  
@@@ -466,6 -427,29 +427,29 @@@ static const struct snd_kcontrol_new ri
  static const struct snd_kcontrol_new samp_ctl =
        SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 3, 1, 0);
  
+ static const char * const speaker_amp_source_text[] = {
+       "CODEC", "Right"
+ };
+ static const SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4,
+                                 speaker_amp_source_text);
+ static const struct snd_kcontrol_new speaker_amp_source_mux =
+       SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source);
+ static const char * const headset_amp_source_text[] = {
+       "CODEC", "Mixer"
+ };
+ static const SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11,
+                                 headset_amp_source_text);
+ static const struct snd_kcontrol_new headset_amp_source_mux =
+       SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source);
+ static const struct snd_kcontrol_new cdcout_ctl =
+       SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 18, 1, 0);
+ static const struct snd_kcontrol_new adc_bypass_ctl =
+       SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_CODEC, 16, 1, 0);
  static const struct snd_kcontrol_new lamp_ctl =
        SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 5, 1, 0);
  
@@@ -503,12 -487,22 +487,22 @@@ static const struct snd_soc_dapm_widge
        SND_SOC_DAPM_VIRT_MUX("PGA Right Input Mux", SND_SOC_NOPM, 0, 0,
                              &right_input_mux),
  
+       SND_SOC_DAPM_MUX("Speaker Amp Source MUX", SND_SOC_NOPM, 0, 0,
+                        &speaker_amp_source_mux),
+       SND_SOC_DAPM_MUX("Headset Amp Source MUX", SND_SOC_NOPM, 0, 0,
+                        &headset_amp_source_mux),
        SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0),
  
        SND_SOC_DAPM_ADC("ADC", "Capture", MC13783_AUDIO_CODEC, 11, 0),
        SND_SOC_DAPM_SUPPLY("ADC_Reset", MC13783_AUDIO_CODEC, 15, 0, NULL, 0),
  
+       SND_SOC_DAPM_PGA("Voice CODEC PGA", MC13783_AUDIO_RX1, 0, 0, NULL, 0),
+       SND_SOC_DAPM_SWITCH("Voice CODEC Bypass", MC13783_AUDIO_CODEC, 16, 0,
+                       &adc_bypass_ctl),
  /* Output */
        SND_SOC_DAPM_SUPPLY("DAC_E", MC13783_AUDIO_DAC, 11, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("DAC_Reset", MC13783_AUDIO_DAC, 15, 0, NULL, 0),
        SND_SOC_DAPM_OUTPUT("RXOUTR"),
        SND_SOC_DAPM_OUTPUT("HSL"),
        SND_SOC_DAPM_OUTPUT("HSR"),
+       SND_SOC_DAPM_OUTPUT("LSPL"),
        SND_SOC_DAPM_OUTPUT("LSP"),
        SND_SOC_DAPM_OUTPUT("SP"),
+       SND_SOC_DAPM_OUTPUT("CDCOUT"),
  
-       SND_SOC_DAPM_SWITCH("Speaker Amp", MC13783_AUDIO_RX0, 3, 0, &samp_ctl),
+       SND_SOC_DAPM_SWITCH("CDCOUT Switch", MC13783_AUDIO_RX0, 18, 0,
+                       &cdcout_ctl),
+       SND_SOC_DAPM_SWITCH("Speaker Amp Switch", MC13783_AUDIO_RX0, 3, 0,
+                       &samp_ctl),
        SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl),
        SND_SOC_DAPM_SWITCH("Headset Amp Left", MC13783_AUDIO_RX0, 10, 0,
                        &hlamp_ctl),
@@@ -554,20 -553,28 +553,28 @@@ static struct snd_soc_dapm_route mc1378
        { "ADC", NULL, "PGA Right Input"},
        { "ADC", NULL, "ADC_Reset"},
  
+       { "Voice CODEC PGA", "Voice CODEC Bypass", "ADC" },
+       { "Speaker Amp Source MUX", "CODEC", "Voice CODEC PGA"},
+       { "Speaker Amp Source MUX", "Right", "DAC PGA"},
+       { "Headset Amp Source MUX", "CODEC", "Voice CODEC PGA"},
+       { "Headset Amp Source MUX", "Mixer", "DAC PGA"},
  /* Output */
        { "HSL", NULL, "Headset Amp Left" },
        { "HSR", NULL, "Headset Amp Right"},
        { "RXOUTL", NULL, "Line out Amp Left"},
        { "RXOUTR", NULL, "Line out Amp Right"},
-       { "SP", NULL, "Speaker Amp"},
-       { "Speaker Amp", NULL, "DAC PGA"},
-       { "LSP", NULL, "DAC PGA"},
-       { "Headset Amp Left", NULL, "DAC PGA"},
-       { "Headset Amp Right", NULL, "DAC PGA"},
+       { "SP", "Speaker Amp Switch", "Speaker Amp Source MUX"},
+       { "LSP", "Loudspeaker Amp", "Speaker Amp Source MUX"},
+       { "HSL", "Headset Amp Left", "Headset Amp Source MUX"},
+       { "HSR", "Headset Amp Right", "Headset Amp Source MUX"},
        { "Line out Amp Left", NULL, "DAC PGA"},
        { "Line out Amp Right", NULL, "DAC PGA"},
        { "DAC PGA", NULL, "DAC"},
        { "DAC", NULL, "DAC_E"},
+       { "CDCOUT", "CDCOUT Switch", "Voice CODEC PGA"},
  };
  
  static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix",
@@@ -580,15 -587,39 +587,39 @@@ static const struct soc_enum mc13783_en
  static struct snd_kcontrol_new mc13783_control_list[] = {
        SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0),
        SOC_SINGLE("PCM Playback Volume", MC13783_AUDIO_RX1, 6, 15, 0),
+       SOC_SINGLE("PCM Playback Switch", MC13783_AUDIO_RX1, 5, 1, 0),
        SOC_DOUBLE("PCM Capture Volume", MC13783_AUDIO_TX, 19, 14, 31, 0),
        SOC_ENUM("3D Control", mc13783_enum_3d_mixer),
+       SOC_SINGLE("CDCOUT Switch", MC13783_AUDIO_RX0, 18, 1, 0),
+       SOC_SINGLE("Earpiece Amp Switch", MC13783_AUDIO_RX0, 3, 1, 0),
+       SOC_DOUBLE("Headset Amp Switch", MC13783_AUDIO_RX0, 10, 9, 1, 0),
+       SOC_DOUBLE("Line out Amp Switch", MC13783_AUDIO_RX0, 16, 15, 1, 0),
+       SOC_SINGLE("PCM Capture Mixin Switch", MC13783_AUDIO_RX0, 22, 1, 0),
+       SOC_SINGLE("Line in Capture Mixin Switch", MC13783_AUDIO_RX0, 23, 1, 0),
+       SOC_SINGLE("CODEC Capture Volume", MC13783_AUDIO_RX1, 1, 15, 0),
+       SOC_SINGLE("CODEC Capture Mixin Switch", MC13783_AUDIO_RX0, 21, 1, 0),
+       SOC_SINGLE("Line in Capture Volume", MC13783_AUDIO_RX1, 12, 15, 0),
+       SOC_SINGLE("Line in Capture Switch", MC13783_AUDIO_RX1, 10, 1, 0),
+       SOC_SINGLE("MC1 Capture Bias Switch", MC13783_AUDIO_TX, 0, 1, 0),
+       SOC_SINGLE("MC2 Capture Bias Switch", MC13783_AUDIO_TX, 1, 1, 0),
  };
  
  static int mc13783_probe(struct snd_soc_codec *codec)
  {
        struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
  
-       mc13xxx_lock(priv->mc13xxx);
+       codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
  
        /* these are the reset values */
        mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893);
                mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
                                0, AUDIO_SSI_SEL);
  
-       mc13xxx_unlock(priv->mc13xxx);
        return 0;
  }
  
@@@ -621,13 -650,9 +650,9 @@@ static int mc13783_remove(struct snd_so
  {
        struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
  
-       mc13xxx_lock(priv->mc13xxx);
        /* Make sure VAUDIOON is off */
        mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_RX0, 0x3, 0);
  
-       mc13xxx_unlock(priv->mc13xxx);
        return 0;
  }
  
@@@ -717,8 -742,6 +742,6 @@@ static struct snd_soc_dai_driver mc1378
  static struct snd_soc_codec_driver soc_codec_dev_mc13783 = {
        .probe          = mc13783_probe,
        .remove         = mc13783_remove,
-       .read           = mc13783_read,
-       .write          = mc13783_write,
        .controls       = mc13783_control_list,
        .num_controls   = ARRAY_SIZE(mc13783_control_list),
        .dapm_widgets   = mc13783_dapm_widgets,
index e29cdb7ee232f803b8aac1748a2d81ef8ee4c8c7,fe4d29d885646ab4dd207a167e98a2e2997ade08..a895a5e4bdf207eee6387bc00e8452ae2385233d
@@@ -37,6 -37,7 +37,7 @@@
  #include <linux/i2c.h>
  #include <linux/regmap.h>
  #include <linux/spi/spi.h>
+ #include <linux/of.h>
  #include <linux/of_device.h>
  #include <linux/of_gpio.h>
  #include <sound/pcm.h>
@@@ -244,6 -245,8 +245,8 @@@ struct tas5086_private 
        unsigned int    mclk, sclk;
        unsigned int    format;
        bool            deemph;
+       unsigned int    charge_period;
+       unsigned int    pwm_start_mid_z;
        /* Current sample rate for de-emphasis control */
        int             rate;
        /* GPIO driving Reset pin, if any */
@@@ -429,7 -432,7 +432,7 @@@ static int tas5086_hw_params(struct snd
        default:
                dev_err(codec->dev, "Invalid bit width\n");
                return -EINVAL;
 -      };
 +      }
  
        ret = regmap_write(priv->regmap, TAS5086_SERIAL_DATA_IF, val);
        if (ret < 0)
@@@ -456,6 -459,75 +459,75 @@@ static int tas5086_mute_stream(struct s
        return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val);
  }
  
+ static void tas5086_reset(struct tas5086_private *priv)
+ {
+       if (gpio_is_valid(priv->gpio_nreset)) {
+               /* Reset codec - minimum assertion time is 400ns */
+               gpio_direction_output(priv->gpio_nreset, 0);
+               udelay(1);
+               gpio_set_value(priv->gpio_nreset, 1);
+               /* Codec needs ~15ms to wake up */
+               msleep(15);
+       }
+ }
+ /* charge period values in microseconds */
+ static const int tas5086_charge_period[] = {
+         13000,  16900,   23400,   31200,   41600,   54600,   72800,   96200,
+        130000, 156000,  234000,  312000,  416000,  546000,  728000,  962000,
+       1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
+ };
+ static int tas5086_init(struct device *dev, struct tas5086_private *priv)
+ {
+       int ret, i;
+       /*
+        * If any of the channels is configured to start in Mid-Z mode,
+        * configure 'part 1' of the PWM starts to use Mid-Z, and tell
+        * all configured mid-z channels to start start under 'part 1'.
+        */
+       if (priv->pwm_start_mid_z)
+               regmap_write(priv->regmap, TAS5086_PWM_START,
+                            TAS5086_PWM_START_MIDZ_FOR_START_1 |
+                               priv->pwm_start_mid_z);
+       /* lookup and set split-capacitor charge period */
+       if (priv->charge_period == 0) {
+               regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
+       } else {
+               i = index_in_array(tas5086_charge_period,
+                                  ARRAY_SIZE(tas5086_charge_period),
+                                  priv->charge_period);
+               if (i >= 0)
+                       regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
+                                    i + 0x08);
+               else
+                       dev_warn(dev,
+                                "Invalid split-cap charge period of %d ns.\n",
+                                priv->charge_period);
+       }
+       /* enable factory trim */
+       ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
+       if (ret < 0)
+               return ret;
+       /* start all channels */
+       ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
+       if (ret < 0)
+               return ret;
+       /* mute all channels for now */
+       ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
+                          TAS5086_SOFT_MUTE_ALL);
+       if (ret < 0)
+               return ret;
+       return 0;
+ }
  /* TAS5086 controls */
  static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);
  
@@@ -691,14 -763,39 +763,39 @@@ static struct snd_soc_dai_driver tas508
  };
  
  #ifdef CONFIG_PM
+ static int tas5086_soc_suspend(struct snd_soc_codec *codec)
+ {
+       struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
+       /* Shut down all channels */
+       ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x60);
+       if (ret < 0)
+               return ret;
+       return 0;
+ }
  static int tas5086_soc_resume(struct snd_soc_codec *codec)
  {
        struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
+       tas5086_reset(priv);
+       regcache_mark_dirty(priv->regmap);
+       ret = tas5086_init(codec->dev, priv);
+       if (ret < 0)
+               return ret;
+       ret = regcache_sync(priv->regmap);
+       if (ret < 0)
+               return ret;
  
-       /* Restore codec state */
-       return regcache_sync(priv->regmap);
+       return 0;
  }
  #else
+ #define tas5086_soc_suspend   NULL
  #define tas5086_soc_resume    NULL
  #endif /* CONFIG_PM */
  
@@@ -710,23 -807,19 +807,19 @@@ static const struct of_device_id tas508
  MODULE_DEVICE_TABLE(of, tas5086_dt_ids);
  #endif
  
- /* charge period values in microseconds */
- static const int tas5086_charge_period[] = {
-         13000,  16900,   23400,   31200,   41600,   54600,   72800,   96200,
-        130000, 156000,  234000,  312000,  416000,  546000,  728000,  962000,
-       1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
- };
  static int tas5086_probe(struct snd_soc_codec *codec)
  {
        struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
-       int charge_period = 1300000; /* hardware default is 1300 ms */
-       u8 pwm_start_mid_z = 0;
        int i, ret;
  
+       priv->pwm_start_mid_z = 0;
+       priv->charge_period = 1300000; /* hardware default is 1300 ms */
        if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) {
                struct device_node *of_node = codec->dev->of_node;
-               of_property_read_u32(of_node, "ti,charge-period", &charge_period);
+               of_property_read_u32(of_node, "ti,charge-period",
+                                    &priv->charge_period);
  
                for (i = 0; i < 6; i++) {
                        char name[25];
                                 "ti,mid-z-channel-%d", i + 1);
  
                        if (of_get_property(of_node, name, NULL) != NULL)
-                               pwm_start_mid_z |= 1 << i;
+                               priv->pwm_start_mid_z |= 1 << i;
                }
        }
  
-       /*
-        * If any of the channels is configured to start in Mid-Z mode,
-        * configure 'part 1' of the PWM starts to use Mid-Z, and tell
-        * all configured mid-z channels to start start under 'part 1'.
-        */
-       if (pwm_start_mid_z)
-               regmap_write(priv->regmap, TAS5086_PWM_START,
-                            TAS5086_PWM_START_MIDZ_FOR_START_1 |
-                               pwm_start_mid_z);
-       /* lookup and set split-capacitor charge period */
-       if (charge_period == 0) {
-               regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
-       } else {
-               i = index_in_array(tas5086_charge_period,
-                                  ARRAY_SIZE(tas5086_charge_period),
-                                  charge_period);
-               if (i >= 0)
-                       regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
-                                    i + 0x08);
-               else
-                       dev_warn(codec->dev,
-                                "Invalid split-cap charge period of %d ns.\n",
-                                charge_period);
-       }
-       /* enable factory trim */
-       ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
-       if (ret < 0)
-               return ret;
-       /* start all channels */
-       ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
+       ret = tas5086_init(codec->dev, priv);
        if (ret < 0)
                return ret;
  
        if (ret < 0)
                return ret;
  
-       /* mute all channels for now */
-       ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
-                          TAS5086_SOFT_MUTE_ALL);
-       if (ret < 0)
-               return ret;
        return 0;
  }
  
@@@ -803,6 -858,7 +858,7 @@@ static int tas5086_remove(struct snd_so
  static struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
        .probe                  = tas5086_probe,
        .remove                 = tas5086_remove,
+       .suspend                = tas5086_soc_suspend,
        .resume                 = tas5086_soc_resume,
        .controls               = tas5086_controls,
        .num_controls           = ARRAY_SIZE(tas5086_controls),
@@@ -862,17 -918,8 +918,8 @@@ static int tas5086_i2c_probe(struct i2c
                if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
                        gpio_nreset = -EINVAL;
  
-       if (gpio_is_valid(gpio_nreset)) {
-               /* Reset codec - minimum assertion time is 400ns */
-               gpio_direction_output(gpio_nreset, 0);
-               udelay(1);
-               gpio_set_value(gpio_nreset, 1);
-               /* Codec needs ~15ms to wake up */
-               msleep(15);
-       }
        priv->gpio_nreset = gpio_nreset;
+       tas5086_reset(priv);
  
        /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
        ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
index cd106aa39984f32152281a80ea7812837ea789d0,6c6066618f3bba119f32480ef59e9253be2834b5..f84ecbfd1238701326e1e69a53770148b55e3a83
@@@ -215,7 -215,7 +215,7 @@@ static int imx_wm8962_probe(struct plat
                goto fail;
        }
        codec_dev = of_find_i2c_device_by_node(codec_np);
 -      if (!codec_dev || !codec_dev->driver) {
 +      if (!codec_dev || !codec_dev->dev.driver) {
                dev_err(&pdev->dev, "failed to find codec platform device\n");
                ret = -EINVAL;
                goto fail;
        data->card.late_probe = imx_wm8962_late_probe;
        data->card.set_bias_level = imx_wm8962_set_bias_level;
  
-       ret = snd_soc_register_card(&data->card);
+       ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
        if (ret) {
                dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
                goto clk_fail;
@@@ -296,7 -296,6 +296,6 @@@ static int imx_wm8962_remove(struct pla
  
        if (!IS_ERR(data->codec_clk))
                clk_disable_unprepare(data->codec_clk);
-       snd_soc_unregister_card(&data->card);
  
        return 0;
  }
index 3814bb0374857b266747323fd973f37fa71dd4ab,55d0d9d3a9fdda319773551674b01e8bd6775e20..4af1936cf0f4fdbbaafe0bee2879872418efadd7
@@@ -29,9 -29,7 +29,7 @@@
  #define KIRKWOOD_FORMATS \
        (SNDRV_PCM_FMTBIT_S16_LE | \
         SNDRV_PCM_FMTBIT_S24_LE | \
-        SNDRV_PCM_FMTBIT_S32_LE | \
-        SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
-        SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
+        SNDRV_PCM_FMTBIT_S32_LE)
  
  static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
  {
@@@ -59,6 -57,8 +57,6 @@@ static struct snd_pcm_hardware kirkwood
        .fifo_size              = 0,
  };
  
 -static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32);
 -
  static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
  {
        struct kirkwood_dma_data *priv = dev_id;
@@@ -159,7 -159,7 +157,7 @@@ static int kirkwood_dma_open(struct snd
                 * Enable Error interrupts. We're only ack'ing them but
                 * it's useful for diagnostics
                 */
-               writel((unsigned long)-1, priv->io + KIRKWOOD_ERR_MASK);
+               writel((unsigned int)-1, priv->io + KIRKWOOD_ERR_MASK);
        }
  
        dram = mv_mbus_dram_info();
@@@ -290,9 -290,10 +288,9 @@@ static int kirkwood_dma_new(struct snd_
        struct snd_pcm *pcm = rtd->pcm;
        int ret;
  
 -      if (!card->dev->dma_mask)
 -              card->dev->dma_mask = &kirkwood_dma_dmamask;
 -      if (!card->dev->coherent_dma_mask)
 -              card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 +      ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
 +      if (ret)
 +              return ret;
  
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = kirkwood_dma_preallocate_dma_buffer(pcm,
index 805b1f399dc3eaebd3df5be9cf311724a97ba7a0,bdd19db4a08b79e630ae81b2d9c1cb3cdca5ec78..31154338c1eb742da6a1342310d81fddb1f9ecd4
@@@ -100,6 -100,7 +100,7 @@@ int tegra30_ahub_allocate_rx_fifo(enum 
  {
        int channel;
        u32 reg, val;
+       struct tegra30_ahub_cif_conf cif_conf;
  
        channel = find_first_zero_bit(ahub->rx_usage,
                                      TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
               TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16;
        tegra30_apbif_write(reg, val);
  
+       cif_conf.threshold = 0;
+       cif_conf.audio_channels = 2;
+       cif_conf.client_channels = 2;
+       cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
+       cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
+       cif_conf.expand = 0;
+       cif_conf.stereo_conv = 0;
+       cif_conf.replicate = 0;
+       cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX;
+       cif_conf.truncate = 0;
+       cif_conf.mono_conv = 0;
        reg = TEGRA30_AHUB_CIF_RX_CTRL +
              (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
-       val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
-             (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
-             (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
-             TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
-             TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
-             TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
-       tegra30_apbif_write(reg, val);
+       ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
  
        return 0;
  }
@@@ -183,6 -190,7 +190,7 @@@ int tegra30_ahub_allocate_tx_fifo(enum 
  {
        int channel;
        u32 reg, val;
+       struct tegra30_ahub_cif_conf cif_conf;
  
        channel = find_first_zero_bit(ahub->tx_usage,
                                      TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
               TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16;
        tegra30_apbif_write(reg, val);
  
+       cif_conf.threshold = 0;
+       cif_conf.audio_channels = 2;
+       cif_conf.client_channels = 2;
+       cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
+       cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
+       cif_conf.expand = 0;
+       cif_conf.stereo_conv = 0;
+       cif_conf.replicate = 0;
+       cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX;
+       cif_conf.truncate = 0;
+       cif_conf.mono_conv = 0;
        reg = TEGRA30_AHUB_CIF_TX_CTRL +
              (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
-       val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
-             (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
-             (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
-             TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
-             TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
-             TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
-       tegra30_apbif_write(reg, val);
+       ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
  
        return 0;
  }
@@@ -346,7 -360,7 +360,7 @@@ static bool tegra30_ahub_apbif_wr_rd_re
                return true;
        default:
                break;
 -      };
 +      }
  
        if (REG_IN_ARRAY(reg, CHANNEL_CTRL) ||
            REG_IN_ARRAY(reg, CHANNEL_CLEAR) ||
@@@ -381,7 -395,7 +395,7 @@@ static bool tegra30_ahub_apbif_volatile
                return true;
        default:
                break;
 -      };
 +      }
  
        if (REG_IN_ARRAY(reg, CHANNEL_CLEAR) ||
            REG_IN_ARRAY(reg, CHANNEL_STATUS) ||
@@@ -437,13 -451,21 +451,21 @@@ static const struct regmap_config tegra
  
  static struct tegra30_ahub_soc_data soc_data_tegra30 = {
        .clk_list_mask = CLK_LIST_MASK_TEGRA30,
+       .set_audio_cif = tegra30_ahub_set_cif,
  };
  
  static struct tegra30_ahub_soc_data soc_data_tegra114 = {
        .clk_list_mask = CLK_LIST_MASK_TEGRA114,
+       .set_audio_cif = tegra30_ahub_set_cif,
+ };
+ static struct tegra30_ahub_soc_data soc_data_tegra124 = {
+       .clk_list_mask = CLK_LIST_MASK_TEGRA114,
+       .set_audio_cif = tegra124_ahub_set_cif,
  };
  
  static const struct of_device_id tegra30_ahub_of_match[] = {
+       { .compatible = "nvidia,tegra124-ahub", .data = &soc_data_tegra124 },
        { .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 },
        { .compatible = "nvidia,tegra30-ahub",  .data = &soc_data_tegra30 },
        {},
@@@ -497,6 -519,7 +519,7 @@@ static int tegra30_ahub_probe(struct pl
        }
        dev_set_drvdata(&pdev->dev, ahub);
  
+       ahub->soc_data = soc_data;
        ahub->dev = &pdev->dev;
  
        ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio");
@@@ -669,6 -692,70 +692,70 @@@ static struct platform_driver tegra30_a
  };
  module_platform_driver(tegra30_ahub_driver);
  
+ void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg,
+                         struct tegra30_ahub_cif_conf *conf)
+ {
+       unsigned int value;
+       value = (conf->threshold <<
+                       TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
+               ((conf->audio_channels - 1) <<
+                       TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+               ((conf->client_channels - 1) <<
+                       TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
+               (conf->audio_bits <<
+                       TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
+               (conf->client_bits <<
+                       TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) |
+               (conf->expand <<
+                       TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) |
+               (conf->stereo_conv <<
+                       TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) |
+               (conf->replicate <<
+                       TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) |
+               (conf->direction <<
+                       TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) |
+               (conf->truncate <<
+                       TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) |
+               (conf->mono_conv <<
+                       TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT);
+       regmap_write(regmap, reg, value);
+ }
+ EXPORT_SYMBOL_GPL(tegra30_ahub_set_cif);
+ void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg,
+                          struct tegra30_ahub_cif_conf *conf)
+ {
+       unsigned int value;
+       value = (conf->threshold <<
+                       TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
+               ((conf->audio_channels - 1) <<
+                       TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+               ((conf->client_channels - 1) <<
+                       TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
+               (conf->audio_bits <<
+                       TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
+               (conf->client_bits <<
+                       TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) |
+               (conf->expand <<
+                       TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) |
+               (conf->stereo_conv <<
+                       TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) |
+               (conf->replicate <<
+                       TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) |
+               (conf->direction <<
+                       TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) |
+               (conf->truncate <<
+                       TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) |
+               (conf->mono_conv <<
+                       TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT);
+       regmap_write(regmap, reg, value);
+ }
+ EXPORT_SYMBOL_GPL(tegra124_ahub_set_cif);
  MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
  MODULE_DESCRIPTION("Tegra30 AHUB driver");
  MODULE_LICENSE("GPL v2");
index bd71145f3639410891144d2457b643b2b16e6c24,5f20b695eba2d52b7e55917816a19a9b5097ed67..231a785b3921a5bd95d87914a92e7f5f2d266a63
@@@ -30,6 -30,7 +30,7 @@@
  #include <linux/io.h>
  #include <linux/module.h>
  #include <linux/of.h>
+ #include <linux/of_device.h>
  #include <linux/platform_device.h>
  #include <linux/pm_runtime.h>
  #include <linux/regmap.h>
@@@ -179,6 -180,7 +180,7 @@@ static int tegra30_i2s_hw_params(struc
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        unsigned int mask, val, reg;
        int ret, sample_size, srate, i2sclock, bitcnt;
+       struct tegra30_ahub_cif_conf cif_conf;
  
        if (params_channels(params) != 2)
                return -EINVAL;
  
        regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val);
  
-       val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
-             (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
-             (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
-             TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
-             TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16;
+       cif_conf.threshold = 0;
+       cif_conf.audio_channels = 2;
+       cif_conf.client_channels = 2;
+       cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
+       cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
+       cif_conf.expand = 0;
+       cif_conf.stereo_conv = 0;
+       cif_conf.replicate = 0;
+       cif_conf.truncate = 0;
+       cif_conf.mono_conv = 0;
  
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
+               cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX;
                reg = TEGRA30_I2S_CIF_RX_CTRL;
        } else {
-               val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
+               cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX;
                reg = TEGRA30_I2S_CIF_TX_CTRL;
        }
  
-       regmap_write(i2s->regmap, reg, val);
+       i2s->soc_data->set_audio_cif(i2s->regmap, reg, &cif_conf);
  
        val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
              (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
@@@ -369,7 -376,7 +376,7 @@@ static bool tegra30_i2s_wr_rd_reg(struc
                return true;
        default:
                return false;
 -      };
 +      }
  }
  
  static bool tegra30_i2s_volatile_reg(struct device *dev, unsigned int reg)
                return true;
        default:
                return false;
 -      };
 +      }
  }
  
  static const struct regmap_config tegra30_i2s_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
  };
  
+ static const struct tegra30_i2s_soc_data tegra30_i2s_config = {
+       .set_audio_cif = tegra30_ahub_set_cif,
+ };
+ static const struct tegra30_i2s_soc_data tegra124_i2s_config = {
+       .set_audio_cif = tegra124_ahub_set_cif,
+ };
+ static const struct of_device_id tegra30_i2s_of_match[] = {
+       { .compatible = "nvidia,tegra124-i2s", .data = &tegra124_i2s_config },
+       { .compatible = "nvidia,tegra30-i2s", .data = &tegra30_i2s_config },
+       {},
+ };
  static int tegra30_i2s_platform_probe(struct platform_device *pdev)
  {
        struct tegra30_i2s *i2s;
+       const struct of_device_id *match;
        u32 cif_ids[2];
        struct resource *mem, *memregion;
        void __iomem *regs;
        }
        dev_set_drvdata(&pdev->dev, i2s);
  
+       match = of_match_device(tegra30_i2s_of_match, &pdev->dev);
+       if (!match) {
+               dev_err(&pdev->dev, "Error: No device match found\n");
+               ret = -ENODEV;
+               goto err;
+       }
+       i2s->soc_data = (struct tegra30_i2s_soc_data *)match->data;
        i2s->dai = tegra30_i2s_dai_template;
        i2s->dai.name = dev_name(&pdev->dev);
  
@@@ -539,11 -569,6 +569,6 @@@ static int tegra30_i2s_resume(struct de
  }
  #endif
  
- static const struct of_device_id tegra30_i2s_of_match[] = {
-       { .compatible = "nvidia,tegra30-i2s", },
-       {},
- };
  static const struct dev_pm_ops tegra30_i2s_pm_ops = {
        SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
                           tegra30_i2s_runtime_resume, NULL)