asoc: tegra: Add support for K3.10 audio
Manoj Gangwal [Tue, 3 Sep 2013 07:03:50 +0000 (12:03 +0530)]
1) Add support for K3.10 audio
2) Register dai as a component

Bug 1310452

Change-Id: I4c09f6b84632ab4adc0748fca807254dba3d19c5
Signed-off-by: Manoj Gangwal <mgangwal@nvidia.com>
Reviewed-on: http://git-master/r/269377
Reviewed-by: Eric Miao <emiao@nvidia.com>
Tested-by: Eric Miao <emiao@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

13 files changed:
sound/soc/tegra/tegra30_ahub.c
sound/soc/tegra/tegra30_ahub.h
sound/soc/tegra/tegra30_dam.c
sound/soc/tegra/tegra30_dam.h
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra30_i2s.h
sound/soc/tegra/tegra30_spdif.c
sound/soc/tegra/tegra_asoc_utils.c
sound/soc/tegra/tegra_asoc_utils.h
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_pcm.h
sound/soc/tegra/tegra_rt5639.c
sound/soc/tegra/tegra_rt5640.c

index b8c5e69..d57280e 100644 (file)
@@ -102,6 +102,19 @@ void tegra30_ahub_clock_set_rate(int rate)
 {
        clk_set_rate(ahub->clk_d_audio, rate);
 }
+EXPORT_SYMBOL_GPL(tegra30_ahub_clock_set_rate);
+
+void tegra30_ahub_enable_clocks(void)
+{
+       pm_runtime_get_sync(ahub->dev);
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_enable_clocks);
+
+void tegra30_ahub_disable_clocks(void)
+{
+       pm_runtime_put(ahub->dev);
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_disable_clocks);
 
 static int tegra30_ahub_soft_reset_rx_channel(int channel)
 {
@@ -149,8 +162,11 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
        reg = TEGRA30_AHUB_CHANNEL_CTRL +
              (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
        val = tegra30_apbif_read(reg);
-       val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK);
-       val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT);
+       val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK |
+                TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK);
+       val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT) |
+              TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN |
+              TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16;
        tegra30_apbif_write(reg, val);
 
        reg = TEGRA30_AHUB_CIF_RX_CTRL +
@@ -158,6 +174,8 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
        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);
 
@@ -174,6 +192,7 @@ int tegra30_ahub_rx_fifo_is_enabled(int i2s_id)
        val &= mask;
        return val;
 }
+EXPORT_SYMBOL_GPL(tegra30_ahub_rx_fifo_is_enabled);
 
 int tegra30_ahub_tx_fifo_is_enabled(int i2s_id)
 {
@@ -185,6 +204,7 @@ int tegra30_ahub_tx_fifo_is_enabled(int i2s_id)
 
        return val;
 }
+EXPORT_SYMBOL_GPL(tegra30_ahub_tx_fifo_is_enabled);
 
 
 int tegra30_ahub_rx_fifo_is_empty(int i2s_id)
@@ -220,6 +240,7 @@ int tegra30_ahub_dam_ch0_is_enabled(int dam_id)
 
        return val;
 }
+EXPORT_SYMBOL_GPL(tegra30_ahub_dam_ch0_is_enabled);
 
 int tegra30_ahub_dam_ch1_is_enabled(int dam_id)
 {
@@ -232,6 +253,7 @@ int tegra30_ahub_dam_ch1_is_enabled(int dam_id)
 
        return val;
 }
+EXPORT_SYMBOL_GPL(tegra30_ahub_dam_ch1_is_enabled);
 
 int tegra30_ahub_dam_tx_is_enabled(int dam_id)
 {
@@ -244,6 +266,7 @@ int tegra30_ahub_dam_tx_is_enabled(int dam_id)
 
        return val;
 }
+EXPORT_SYMBOL_GPL(tegra30_ahub_dam_tx_is_enabled);
 
 
 int tegra30_ahub_dam_ch0_is_empty(int dam_id)
@@ -304,6 +327,7 @@ int tegra30_ahub_set_rx_fifo_pack_mode(enum tegra30_ahub_rxcif rxcif,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_fifo_pack_mode);
 
 int tegra30_ahub_set_tx_fifo_pack_mode(enum tegra30_ahub_txcif txcif,
                                                        unsigned int pack_mode)
@@ -326,6 +350,7 @@ int tegra30_ahub_set_tx_fifo_pack_mode(enum tegra30_ahub_txcif txcif,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(tegra30_ahub_set_tx_fifo_pack_mode);
 
 int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
 {
@@ -391,8 +416,11 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
        reg = TEGRA30_AHUB_CHANNEL_CTRL +
              (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
        val = tegra30_apbif_read(reg);
-       val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK);
-       val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT);
+       val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK |
+                TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK);
+       val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT) |
+              TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN |
+              TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16;
        tegra30_apbif_write(reg, val);
 
        reg = TEGRA30_AHUB_CIF_TX_CTRL +
@@ -400,6 +428,8 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
        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);
 
@@ -474,6 +504,107 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
 
+int tegra30_ahub_set_rx_cif_channels(enum tegra30_ahub_rxcif rxcif,
+                                    unsigned int audio_ch,
+                                    unsigned int client_ch)
+{
+       int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
+       unsigned int reg, val;
+
+       reg = TEGRA30_AHUB_CIF_RX_CTRL +
+             (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
+       val = tegra30_apbif_read(reg);
+       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
+               TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
+       val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+             ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
+       tegra30_apbif_write(reg, val);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_channels);
+
+int tegra30_ahub_set_rx_cif_stereo_conv(enum tegra30_ahub_rxcif rxcif)
+{
+       int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
+       unsigned int reg, val;
+
+       tegra30_ahub_enable_clocks();
+
+       reg = TEGRA30_AHUB_CIF_RX_CTRL +
+             (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
+       val = tegra30_apbif_read(reg);
+       val &= ~TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_MASK;
+       val |= TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG;
+       tegra30_apbif_write(reg, val);
+
+       tegra30_ahub_disable_clocks();
+
+       return 0;
+}
+
+int tegra30_ahub_set_tx_cif_channels(enum tegra30_ahub_txcif txcif,
+                                    unsigned int audio_ch,
+                                    unsigned int client_ch)
+{
+       int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
+       unsigned int reg, val;
+
+       reg = TEGRA30_AHUB_CIF_TX_CTRL +
+             (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
+       val = tegra30_apbif_read(reg);
+       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
+               TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
+       val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+             ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
+
+       tegra30_apbif_write(reg, val);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_set_tx_cif_channels);
+
+int tegra30_ahub_set_rx_cif_bits(enum tegra30_ahub_rxcif rxcif,
+                                    unsigned int audio_bits,
+                                    unsigned int client_bits)
+{
+       int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
+       unsigned int reg, val;
+
+       reg = TEGRA30_AHUB_CIF_RX_CTRL +
+             (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
+       val = tegra30_apbif_read(reg);
+       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK |
+               TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK);
+       val |= ((audio_bits) << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
+             ((client_bits) << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
+       tegra30_apbif_write(reg, val);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_bits);
+
+int tegra30_ahub_set_tx_cif_bits(enum tegra30_ahub_txcif txcif,
+                                    unsigned int audio_bits,
+                                    unsigned int client_bits)
+{
+       int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
+       unsigned int reg, val;
+
+       reg = TEGRA30_AHUB_CIF_TX_CTRL +
+             (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
+       val = tegra30_apbif_read(reg);
+       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK |
+               TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK);
+       val |= ((audio_bits) << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
+             ((client_bits) << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
+
+       tegra30_apbif_write(reg, val);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_set_tx_cif_bits);
+
 static const char * const configlink_clocks[] = {
        "i2s0",
        "i2s1",
@@ -483,7 +614,10 @@ static const char * const configlink_clocks[] = {
        "dam0",
        "dam1",
        "dam2",
+/*No SPDIF in 14x*/
+#ifndef CONFIG_ARCH_TEGRA_14x_SOC
        "spdif_in",
+#endif
 };
 
 struct of_dev_auxdata ahub_auxdata[] = {
@@ -625,104 +759,6 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-int tegra30_ahub_set_rx_cif_channels(enum tegra30_ahub_rxcif rxcif,
-                                    unsigned int audio_ch,
-                                    unsigned int client_ch)
-{
-       int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
-       unsigned int reg, val;
-
-       reg = TEGRA30_AHUB_CIF_RX_CTRL +
-             (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
-       val = tegra30_apbif_read(reg);
-       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
-               TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
-       val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
-             ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
-       tegra30_apbif_write(reg, val);
-
-       return 0;
-}
-
-int tegra30_ahub_set_rx_cif_stereo_conv(enum tegra30_ahub_rxcif rxcif)
-{
-       int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
-       unsigned int reg, val;
-
-       tegra30_ahub_enable_clocks();
-
-       reg = TEGRA30_AHUB_CIF_RX_CTRL +
-             (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
-       val = tegra30_apbif_read(reg);
-       val &= ~TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_MASK;
-       val |= TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG;
-       tegra30_apbif_write(reg, val);
-
-       tegra30_ahub_disable_clocks();
-
-       return 0;
-}
-
-int tegra30_ahub_set_tx_cif_channels(enum tegra30_ahub_txcif txcif,
-                                    unsigned int audio_ch,
-                                    unsigned int client_ch)
-{
-       int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
-       unsigned int reg, val;
-
-       reg = TEGRA30_AHUB_CIF_TX_CTRL +
-             (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
-       val = tegra30_apbif_read(reg);
-       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
-               TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
-       val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
-             ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
-
-       tegra30_apbif_write(reg, val);
-
-       return 0;
-}
-
-int tegra30_ahub_set_rx_cif_bits(enum tegra30_ahub_rxcif rxcif,
-                                    unsigned int audio_bits,
-                                    unsigned int client_bits)
-{
-       int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
-       unsigned int reg, val;
-
-       reg = TEGRA30_AHUB_CIF_RX_CTRL +
-             (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
-       val = tegra30_apbif_read(reg);
-       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK |
-               TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK);
-       val |= ((audio_bits) << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
-             ((client_bits) << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
-       tegra30_apbif_write(reg, val);
-
-       return 0;
-}
-
-int tegra30_ahub_set_tx_cif_bits(enum tegra30_ahub_txcif txcif,
-                                    unsigned int audio_bits,
-                                    unsigned int client_bits)
-{
-       int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
-       unsigned int reg, val;
-
-       reg = TEGRA30_AHUB_CIF_TX_CTRL +
-             (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
-       val = tegra30_apbif_read(reg);
-       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK |
-               TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK);
-       val |= ((audio_bits) << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
-             ((client_bits) << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
-
-       tegra30_apbif_write(reg, val);
-
-       return 0;
-}
-
-
 static int tegra30_ahub_probe(struct platform_device *pdev)
 {
        struct clk *clk;
@@ -730,8 +766,8 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
        struct resource *res0, *res1, *region;
        u32 of_dma[2];
        void __iomem *regs_apbif, *regs_ahub;
-       int ret = 0;
        int clkm_rate;
+       int ret = 0;
 
        if (ahub)
                return -ENODEV;
@@ -784,15 +820,19 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
                goto err_clk_put_d_audio;
        }
 
-       if (of_property_read_u32_array(pdev->dev.of_node,
-                               "nvidia,dma-request-selector",
-                               of_dma, 2) < 0) {
-               dev_err(&pdev->dev,
-                       "Missing property nvidia,dma-request-selector\n");
-               ret = -ENODEV;
-               goto err_clk_put_d_audio;
+       if (!(pdev->dev.of_node))
+               ahub->dma_sel = 1;
+       else {
+               if (of_property_read_u32_array(pdev->dev.of_node,
+                                       "nvidia,dma-request-selector",
+                                       of_dma, 2) < 0) {
+                       dev_err(&pdev->dev,
+                               "Missing property nvidia,dma-request-selector\n");
+                       ret = -ENODEV;
+                       goto err_clk_put_d_audio;
+               }
+               ahub->dma_sel = of_dma[1];
        }
-       ahub->dma_sel = of_dma[1];
 
        res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res0) {
@@ -866,8 +906,9 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
                        goto err_pm_disable;
        }
 
-       of_platform_populate(pdev->dev.of_node, NULL, ahub_auxdata,
-                            &pdev->dev);
+       if (pdev->dev.of_node)
+               of_platform_populate(pdev->dev.of_node, NULL, ahub_auxdata,
+                                    &pdev->dev);
 
        return 0;
 
index c28faf6..142d5b0 100644 (file)
@@ -234,7 +234,7 @@ defined(CONFIG_ARCH_TEGRA_14x_SOC))
 #define TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_SHIFT                        16
 #define TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_MASK_US              0xfff
 #define TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_MASK                 (TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_MASK_US << TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_SHIFT)
-#define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_SHIFT                   4
+#define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_SHIFT                   5
 #define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_MASK_US                 0xfff
 #define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_MASK                    (TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_MASK_US << TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_SHIFT)
 #define TEGRA30_AHUB_CONFIG_LINK_CTRL_CG_EN                            (1 << 2)
@@ -245,7 +245,7 @@ defined(CONFIG_ARCH_TEGRA_14x_SOC))
 
 #define TEGRA30_AHUB_MISC_CTRL                         0x84
 #define TEGRA30_AHUB_MISC_CTRL_AUDIO_ACTIVE            (1 << 31)
-#define TEGRA30_AHUB_MISC_CTRL_AUDIO_CG_EN             (1 << 8)
+#define TEGRA30_AHUB_MISC_CTRL_AUDIO_CG_EN             (1 << 9)
 #define TEGRA30_AHUB_MISC_CTRL_AUDIO_OBS_SEL_SHIFT     0
 #define TEGRA30_AHUB_MISC_CTRL_AUDIO_OBS_SEL_MASK      (0x1f << TEGRA30_AHUB_MISC_CTRL_AUDIO_OBS_SEL_SHIFT)
 
@@ -524,6 +524,8 @@ enum tegra30_ahub_rxcif {
        TEGRA30_AHUB_AUDIO_RX_COUNT,
 };
 
+extern void tegra30_ahub_enable_clocks(void);
+extern void tegra30_ahub_disable_clocks(void);
 extern void tegra30_ahub_clock_set_rate(int rate);
 
 extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
@@ -587,6 +589,7 @@ struct tegra30_ahub {
        struct regmap *regmap_ahub;
        DECLARE_BITMAP(rx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
        DECLARE_BITMAP(tx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
+       struct dentry *debug;
 };
 
 #endif
index 31becc5..724283b 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/pm_runtime.h>
 #include <sound/soc.h>
 #include "tegra30_dam.h"
 #include "tegra30_ahub.h"
 
 static struct tegra30_dam_context      *dams_cont_info[TEGRA30_NR_DAM_IFC];
 
+/*
+Static Tables used by DAM driver
+*/
+
 enum {
        dam_ch_in0 = 0x0,
        dam_ch_in1,
@@ -47,7 +52,7 @@ enum {
 } tegra30_dam_chtype;
 
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
-struct tegra30_dam_src_step_table  step_table[] = {
+static struct tegra30_dam_src_step_table  step_table[] = {
        { 8000, 44100, 80 },
        { 8000, 48000, 1 },
        { 16000, 44100, 160 },
@@ -57,10 +62,8 @@ struct tegra30_dam_src_step_table  step_table[] = {
        { 44100, 16000, 441 },
        { 48000, 16000, 0 },
 };
-#endif
-
-#ifndef CONFIG_ARCH_TEGRA_3x_SOC
-int coefRam16To44[64] = {
+#else
+static int coefRam16To44[64] = {
                                0x156105, // IIR Filter + interpolation
                                0x0000d649,
                                0x00e87afb, 0xff5f69d0, 0x003df3cf,
@@ -96,7 +99,7 @@ int coefRam16To44[64] = {
                                0,0,0,0,0,0
 };
 
-int coefRam8To48[64] = {
+static int coefRam8To48[64] = {
                                0x156105, // interpolation + FIlter
                                0x0000d649,
                                0x00e87afb, 0xff5f69d0, 0x003df3cf,
@@ -120,7 +123,7 @@ int coefRam8To48[64] = {
                                0
 };
 
-int coefRam16To48[64] = {
+static int coefRam16To48[64] = {
                                0x00a105, // interpolation + Filter
                                1924,
                                13390190,-13855175,5952947,
@@ -146,7 +149,7 @@ int coefRam16To48[64] = {
                                0,0
 };
 
-int coefRam44To16[64] = {
+static int coefRam44To16[64] = {
                                0x126104, // IIR Filter + interp0lation
                                2802,
                                5762750,-14772125,6628868,
@@ -180,7 +183,7 @@ int coefRam44To16[64] = {
                                0,0,0,0
 };
 
-int coefRam44To8[64] = {
+static int coefRam44To8[64] = {
                                0x120104, // IIR Filter
                                2802,
                                5762750,-14772125,6628868,
@@ -214,7 +217,7 @@ int coefRam44To8[64] = {
                                0,0
 };
 
-int coefRam48To16[64] = {
+static int coefRam48To16[64] = {
                                0x009105, // IIR FIlter + Decimation
                                1924,
                                13390190,-13855175,5952947,
@@ -232,7 +235,7 @@ int coefRam48To16[64] = {
                                0,0,0,0,0,0,0,0
 };
 
-int coefRam48To8[64] = {
+static int coefRam48To8[64] = {
                                0x0c9102,       //IIR Filter + decimation
                                0x00000e00,
                                0x00e2e000,0xff6e1a00,0x002aaa00,
@@ -256,7 +259,7 @@ int coefRam48To8[64] = {
                                0
 };
 
-int coefRam8To44[64] = {
+static int coefRam8To44[64] = {
                                0x0156105, // IIR filter +interpllation
                                0x0000d649,
                                0x00e87afb, 0xff5f69d0, 0x003df3cf,
@@ -289,7 +292,7 @@ int coefRam8To44[64] = {
                                0,0,0,0,0,0
 };
 
-int coefRam8To16[64] = {
+static int coefRam8To16[64] = {
                                0x00006105, // interpolation + IIR Filter
                                0x0000d649, // input gain
                                0x00e87afb, 0xff5f69d0, 0x003df3cf,
@@ -301,7 +304,7 @@ int coefRam8To16[64] = {
                                0x00000002, // ouptut gain
 };
 
-int coefRam16To8[64] = {
+static int coefRam16To8[64] = {
                                0x00005105,   //IIR Filter + Decimator
                                0x0000d649, //input gain
                                0x00e87afb, 0xff5f69d0, 0x003df3cf,
@@ -314,86 +317,111 @@ int coefRam16To8[64] = {
 };
 #endif
 
-static void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
-               int fsout);
-static void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam,
-               int fsin);
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-static int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
-               int insample, int outsample);
-static void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step);
-#endif
+/*
+Internally used helper (static) function prototypes
+*/
 
 static inline void tegra30_dam_writel(struct tegra30_dam_context *dam,
-                       u32 val, u32 reg)
-{
-#ifdef CONFIG_PM
-       dam->reg_cache[reg >> 2] = val;
+                       u32 val, u32 reg);
+static inline u32 tegra30_dam_readl(struct tegra30_dam_context *dam,
+                                                                                                                       u32 reg);
+static void tegra30_dam_set_output_samplerate(
+                                               struct tegra30_dam_context *dam, int fsout);
+static void tegra30_dam_set_input_samplerate(
+                                               struct tegra30_dam_context *dam, int fsin);
+static int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
+                                                                               int insample, int outsample);
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+static void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam,
+                                                                                                                       int step);
+#else
+static void tegra30_dam_write_coeff_ram(struct tegra30_dam_context *dam,
+                                                                                               int fsin, int fsout);
+static void tegra30_dam_set_farrow_param(
+                               struct tegra30_dam_context *dam, int fsin, int fsout);
+static void tegra30_dam_set_biquad_fixed_coef(
+                                                                       struct tegra30_dam_context *dam);
+static void tegra30_dam_enable_coeff_ram(
+                                                                       struct tegra30_dam_context *dam);
+static void tegra30_dam_set_filter_stages(
+                               struct tegra30_dam_context *dam, int fsin, int fsout);
 #endif
-       __raw_writel(val, dam->damregs + reg);
-}
 
-static inline u32 tegra30_dam_readl(struct tegra30_dam_context *dam, u32 reg)
-{
-       u32 val = __raw_readl(dam->damregs + reg);
 
-       return val;
-}
+/*
+Regmap and Runtime PM callback function
+*/
 
-#ifdef CONFIG_PM
-int tegra30_dam_resume(int ifc)
+static bool tegra30_dam_wr_rd_reg(struct device *dev, unsigned int reg)
 {
-       int i = 0;
-       struct tegra30_dam_context *dam;
-
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return -EINVAL;
-
-       dam = dams_cont_info[ifc];
-
-       if (dam->in_use) {
-               tegra30_dam_enable_clock(ifc);
-
-               for (i = 0; i <= TEGRA30_DAM_CTRL_REGINDEX; i++) {
-                       if ((i == TEGRA30_DAM_CTRL_RSVD_6) ||
-                               (i == TEGRA30_DAM_CTRL_RSVD_10))
-                               continue;
-
-                       tegra30_dam_writel(dam, dam->reg_cache[i],
-                                               (i << 2));
-               }
-
-               tegra30_dam_disable_clock(ifc);
-       }
-
-       return 0;
+       switch (reg) {
+       case TEGRA30_DAM_CTRL:
+       case TEGRA30_DAM_CLIP:
+       case TEGRA30_DAM_CLIP_THRESHOLD:
+       case TEGRA30_DAM_AUDIOCIF_OUT_CTRL:
+       case TEGRA30_DAM_CH0_CTRL:
+       case TEGRA30_DAM_CH0_CONV:
+       case TEGRA30_DAM_AUDIOCIF_CH0_CTRL:
+       case TEGRA30_DAM_CH1_CTRL:
+       case TEGRA30_DAM_CH1_CONV:
+       case TEGRA30_DAM_AUDIOCIF_CH1_CTRL:
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+       case TEGRA30_DAM_CH0_BIQUAD_FIXED_COEF_0:
+       case TEGRA30_DAM_FARROW_PARAM_0:
+       case TEGRA30_DAM_AUDIORAMCTL_DAM_CTRL_0:
+       case TEGRA30_DAM_AUDIORAMCTL_DAM_DATA_0:
+#endif
+               return true;
+       default:
+               return false;
+       };
 }
+
+static const struct regmap_config tegra30_dam_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+       .max_register = TEGRA30_DAM_AUDIORAMCTL_DAM_DATA_0,
+#else
+       .max_register = TEGRA30_DAM_AUDIOCIF_CH1_CTRL,
 #endif
+       .writeable_reg = tegra30_dam_wr_rd_reg,
+       .readable_reg = tegra30_dam_wr_rd_reg,
+       .cache_type = REGCACHE_RBTREE,
+};
 
-void tegra30_dam_disable_clock(int ifc)
+static int tegra30_dam_runtime_suspend(struct device *dev)
 {
-       struct tegra30_dam_context *dam;
+       struct tegra30_dam_context *dam = dev_get_drvdata(dev);
 
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return;
+       tegra30_ahub_disable_clocks();
+       regcache_cache_only(dam->regmap, true);
+       clk_disable_unprepare(dam->dam_clk);
 
-       dam =  dams_cont_info[ifc];
-       clk_disable(dam->dam_clk);
+       return 0;
 }
 
-int tegra30_dam_enable_clock(int ifc)
+static int tegra30_dam_runtime_resume(struct device *dev)
 {
-       struct tegra30_dam_context *dam;
-
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return -EINVAL;
+       struct tegra30_dam_context *dam = dev_get_drvdata(dev);
+       int ret;
 
-       dam =  dams_cont_info[ifc];
-       clk_enable(dam->dam_clk);
+       tegra30_ahub_enable_clocks();
+       ret = clk_prepare_enable(dam->dam_clk);
+       if (ret) {
+               dev_err(dev, "clk_enable failed: %d\n", ret);
+               return ret;
+       }
+       regcache_cache_only(dam->regmap, false);
 
        return 0;
 }
 
+/*
+DebugFs callback functions
+*/
+
 #ifdef CONFIG_DEBUG_FS
 static int tegra30_dam_show(struct seq_file *s, void *unused)
 {
@@ -469,110 +497,24 @@ static inline void tegra30_dam_debug_remove(struct tegra30_dam_context *dam)
 }
 #endif
 
-int tegra30_dam_allocate_controller()
-{
-       int i = 0;
-       struct tegra30_dam_context *dam = NULL;
-
-       for (i = 0; i < TEGRA30_NR_DAM_IFC; i++) {
-
-               dam =  dams_cont_info[i];
-
-               if (!dam->in_use) {
-                       dam->in_use = true;
-                       return i;
-               }
-       }
-
-       return -ENOENT;
-}
-
-int tegra30_dam_allocate_channel(int ifc, int chid)
-{
-       struct tegra30_dam_context *dam = NULL;
-
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC) ||
-               (chid < dam_ch_in0) || (chid > dam_ch_in1))
-               return -EINVAL;
-
-       dam =  dams_cont_info[ifc];
-
-       if (!dam->ch_alloc[chid]) {
-               dam->ch_alloc[chid] = true;
-               return 0;
-       }
-
-       return -ENOENT;
-}
-
-int tegra30_dam_free_channel(int ifc, int chid)
-{
-       struct tegra30_dam_context *dam = NULL;
-
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC) ||
-               (chid < dam_ch_in0) || (chid > dam_ch_in1))
-               return -EINVAL;
-
-       dam =  dams_cont_info[ifc];
-
-       if (dam->ch_alloc[chid]) {
-               dam->ch_alloc[chid] = false;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-int tegra30_dam_free_controller(int ifc)
+/*
+Internally used helper (static) functions
+*/
+static inline void tegra30_dam_writel(struct tegra30_dam_context *dam,
+                       u32 val, u32 reg)
 {
-       struct tegra30_dam_context *dam = NULL;
-
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return -EINVAL;
-
-       dam =  dams_cont_info[ifc];
-
-       if (!dam->ch_alloc[dam_ch_in0] &&
-               !dam->ch_alloc[dam_ch_in1]) {
-               dam->in_use = false;
-               return 0;
-       }
-
-       return -EINVAL;
+       regmap_write(dam->regmap, reg, val);
 }
 
-void tegra30_dam_set_samplerate(int ifc, int chid, int samplerate)
+static inline u32 tegra30_dam_readl(struct tegra30_dam_context *dam, u32 reg)
 {
-       struct tegra30_dam_context *dam;
-
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return;
-
-       dam = dams_cont_info[ifc];
+       u32 val;
 
-       switch (chid) {
-       case dam_ch_in0:
-               tegra30_dam_set_input_samplerate(dam, samplerate);
-               dam->ch_insamplerate[dam_ch_in0] = samplerate;
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-               tegra30_dam_set_step_reset(dam, samplerate, dam->outsamplerate);
-#endif
-               break;
-       case dam_ch_in1:
-               if (samplerate != dam->outsamplerate)
-                       return;
-               dam->ch_insamplerate[dam_ch_in1] = samplerate;
-               break;
-       case dam_ch_out:
-               tegra30_dam_set_output_samplerate(dam, samplerate);
-               dam->outsamplerate = samplerate;
-               break;
-       default:
-               break;
-       }
+       regmap_read(dam->regmap, reg, &val);
+       return val;
 }
 
-void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
+static void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
                                        int fsout)
 {
        u32 val;
@@ -600,7 +542,8 @@ void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
        tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL);
 }
 
-void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam, int fsin)
+static void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam,
+       int fsin)
 {
        u32 val;
 
@@ -627,10 +570,10 @@ void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam, int fsin)
        tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
 }
 
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
+static int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
                int insample, int outsample)
 {
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
        int step_reset = 0;
        int i = 0;
 
@@ -641,11 +584,19 @@ int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
        }
 
        tegra30_dam_ch0_set_step(dam, step_reset);
+#else
+       tegra30_dam_write_coeff_ram(dam, insample, outsample);
+       tegra30_dam_set_farrow_param(dam, insample, outsample);
+       tegra30_dam_set_biquad_fixed_coef(dam);
+       tegra30_dam_enable_coeff_ram(dam);
+       tegra30_dam_set_filter_stages(dam, insample, outsample);
+#endif
 
        return 0;
 }
 
-void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step)
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+static void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step)
 {
        u32 val;
 
@@ -654,95 +605,13 @@ void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step)
        val |= step << TEGRA30_DAM_CH0_CTRL_STEP_SHIFT;
        tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
 }
-#endif
-
-int tegra30_dam_set_gain(int ifc, int chid, int gain)
-{
-
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return -EINVAL;
-
-       switch (chid) {
-       case dam_ch_in0:
-               tegra30_dam_writel(dams_cont_info[ifc], gain,
-                       TEGRA30_DAM_CH0_CONV);
-               break;
-       case dam_ch_in1:
-               tegra30_dam_writel(dams_cont_info[ifc], gain,
-                       TEGRA30_DAM_CH1_CONV);
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-int tegra30_dam_set_acif(int ifc, int chid, unsigned int audio_channels,
-       unsigned int audio_bits, unsigned int client_channels,
-       unsigned int client_bits)
-{
-       unsigned int reg;
-       unsigned int value = 0;
-
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return -EINVAL;
-
-#ifndef CONFIG_ARCH_TEGRA_3x_SOC
-       /*ch0 takes input as mono always*/
-       if ((chid == dam_ch_in0) &&
-               ((client_channels != 1)))
-               return -EINVAL;
-       /*as per dam spec file chout is fixed to 32 bits*/
-       /*so accept ch0, ch1 and chout as 32bit always*/
-       if (client_bits != 32)
-               return -EINVAL;
 #else
-       /*ch0 takes input as mono/16bit always*/
-       if ((chid == dam_ch_in0) &&
-               ((client_channels != 1) || (client_bits != 16)))
-               return -EINVAL;
-#endif
-
-       value |= TEGRA30_CIF_MONOCONV_COPY;
-       value |= TEGRA30_CIF_STEREOCONV_CH0;
-       value |= (audio_channels-1)  << TEGRA30_AUDIO_CHANNELS_SHIFT;
-       value |= (((audio_bits>>2)-1)<<TEGRA30_AUDIO_BITS_SHIFT);
-       value |= (client_channels-1)  << TEGRA30_CLIENT_CHANNELS_SHIFT;
-       value |= (((client_bits>>2)-1)<<TEGRA30_CLIENT_BITS_SHIFT);
-
-       switch (chid) {
-       case dam_ch_out:
-               value |= TEGRA30_CIF_DIRECTION_TX;
-               reg = TEGRA30_DAM_AUDIOCIF_OUT_CTRL;
-               break;
-       case dam_ch_in0:
-               value |= TEGRA30_CIF_DIRECTION_RX;
-               reg = TEGRA30_DAM_AUDIOCIF_CH0_CTRL;
-               break;
-       case dam_ch_in1:
-               value |= TEGRA30_CIF_DIRECTION_RX;
-               reg = TEGRA30_DAM_AUDIOCIF_CH1_CTRL;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       tegra30_dam_writel(dams_cont_info[ifc], value, reg);
-
-       return 0;
-}
-
-#ifndef CONFIG_ARCH_TEGRA_3x_SOC
-void tegra30_dam_write_coeff_ram(int ifc, int fsin, int fsout)
+static void tegra30_dam_write_coeff_ram(struct tegra30_dam_context *dam, int fsin, int fsout)
 {
        u32 val;
        int i, *coefRam = NULL;
 
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return;
-
-       tegra30_dam_writel(dams_cont_info[ifc], 0x00002000,
+       tegra30_dam_writel(dam, 0x00002000,
                        TEGRA30_DAM_AUDIORAMCTL_DAM_CTRL_0);
 
        switch(fsin) {
@@ -782,23 +651,20 @@ void tegra30_dam_write_coeff_ram(int ifc, int fsin, int fsout)
                        break;
        }
 
-       tegra30_dam_writel(dams_cont_info[ifc], 0x00005000,
+       tegra30_dam_writel(dam, 0x00005000,
                        TEGRA30_DAM_AUDIORAMCTL_DAM_CTRL_0);
 
        for (i = 0; i < 64; i++) {
-               val = coefRam[i];\r
-               tegra30_dam_writel(dams_cont_info[ifc], val,
+               val = coefRam[i];
+               tegra30_dam_writel(dam, val,
                                TEGRA30_DAM_AUDIORAMCTL_DAM_DATA_0);
        }
 }
 
-void tegra30_dam_set_farrow_param(int ifc, int fsin, int fsout)
+static void tegra30_dam_set_farrow_param(struct tegra30_dam_context *dam, int fsin, int fsout)
 {
        u32 val = TEGRA30_FARROW_PARAM_RESET;
 
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return;
-
        switch(fsin) {
                case TEGRA30_AUDIO_SAMPLERATE_8000:
                        if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
@@ -836,43 +702,34 @@ void tegra30_dam_set_farrow_param(int ifc, int fsin, int fsout)
                        break;
        }
 
-       tegra30_dam_writel(dams_cont_info[ifc], val,
+       tegra30_dam_writel(dam, val,
                        TEGRA30_DAM_FARROW_PARAM_0);
 }
 
-void tegra30_dam_set_biquad_fixed_coef(int ifc)
+static void tegra30_dam_set_biquad_fixed_coef(struct tegra30_dam_context *dam)
 {
        u32 val = TEGRA30_DAM_CH0_BIQUAD_FIXED_COEF_0_VAL;
 
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return;
-
-       tegra30_dam_writel(dams_cont_info[ifc], val,
+       tegra30_dam_writel(dam, val,
                        TEGRA30_DAM_CH0_BIQUAD_FIXED_COEF_0);
 }
 
-void tegra30_dam_enable_coeff_ram(int ifc)
+static void tegra30_dam_enable_coeff_ram(struct tegra30_dam_context *dam)
 {
        u32 val;
 
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return;
-
-       val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CH0_CTRL);
+       val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
        val |= TEGRA30_DAM_CH0_CTRL_COEFF_RAM_ENABLE;
 
-       tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CH0_CTRL);
+       tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
 }
 
-void tegra30_dam_set_filter_stages(int ifc, int fsin, int fsout)
+static void tegra30_dam_set_filter_stages(struct tegra30_dam_context *dam, int fsin, int fsout)
 {
        u32 val;
        int filt_stages = 0;
 
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
-               return;
-
-       val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CH0_CTRL);
+       val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
 
        switch(fsin) {
                case TEGRA30_AUDIO_SAMPLERATE_8000:
@@ -913,23 +770,211 @@ void tegra30_dam_set_filter_stages(int ifc, int fsin, int fsout)
 
        val |= filt_stages << TEGRA30_DAM_CH0_CTRL_FILT_STAGES_SHIFT;
 
-       tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CH0_CTRL);
+       tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
 }
+#endif
 
-void tegra30_dam_enable_stereo_mixing(int ifc)
+/*
+DAM Driver API's
+*/
+
+int tegra30_dam_allocate_controller()
 {
-       u32 val;
+       int i = 0;
+       struct tegra30_dam_context *dam = NULL;
+
+       for (i = 0; i < TEGRA30_NR_DAM_IFC; i++) {
+
+               dam =  dams_cont_info[i];
+
+               if (!dam->in_use) {
+                       dam->in_use = true;
+                       return i;
+               }
+       }
+
+       return -ENOENT;
+}
+
+void tegra30_dam_disable_clock(int ifc)
+{
+       struct tegra30_dam_context *dam;
+
+       if (ifc >= TEGRA30_NR_DAM_IFC)
+               return;
+
+       dam =  dams_cont_info[ifc];
+       pm_runtime_put(dam->dev);
+}
+
+int tegra30_dam_enable_clock(int ifc)
+{
+       struct tegra30_dam_context *dam;
+
+       if (ifc >= TEGRA30_NR_DAM_IFC)
+               return -EINVAL;
+
+       dam =  dams_cont_info[ifc];
+       pm_runtime_get_sync(dam->dev);
 
-       if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC))
+       return 0;
+}
+
+int tegra30_dam_allocate_channel(int ifc, int chid)
+{
+       struct tegra30_dam_context *dam = NULL;
+
+       if (ifc >= TEGRA30_NR_DAM_IFC)
+               return -EINVAL;
+
+       dam =  dams_cont_info[ifc];
+
+       if (!dam->ch_alloc[chid]) {
+               dam->ch_alloc[chid] = true;
+               return 0;
+       }
+
+       return -ENOENT;
+}
+
+int tegra30_dam_free_channel(int ifc, int chid)
+{
+       struct tegra30_dam_context *dam = NULL;
+
+       if (ifc >= TEGRA30_NR_DAM_IFC)
+               return -EINVAL;
+
+       dam =  dams_cont_info[ifc];
+
+       if (dam->ch_alloc[chid]) {
+               dam->ch_alloc[chid] = false;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+int tegra30_dam_free_controller(int ifc)
+{
+       struct tegra30_dam_context *dam = NULL;
+
+       if (ifc >= TEGRA30_NR_DAM_IFC)
+               return -EINVAL;
+
+       dam =  dams_cont_info[ifc];
+
+       if (!dam->ch_alloc[dam_ch_in0] &&
+               !dam->ch_alloc[dam_ch_in1]) {
+               dam->in_use = false;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+void tegra30_dam_set_samplerate(int ifc, int chid, int samplerate)
+{
+       struct tegra30_dam_context *dam = dams_cont_info[ifc];
+
+       if (ifc >= TEGRA30_NR_DAM_IFC)
                return;
 
-       val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CTRL);
-       val |= TEGRA30_DAM_CTRL_STEREO_MIXING_ENABLE;
+       switch (chid) {
+       case dam_ch_in0:
+               tegra30_dam_set_input_samplerate(dam, samplerate);
+               dam->ch_insamplerate[dam_ch_in0] = samplerate;
+               tegra30_dam_set_step_reset(dam, samplerate, dam->outsamplerate);
+               break;
+       case dam_ch_in1:
+               if (samplerate != dam->outsamplerate)
+                       return;
+               dam->ch_insamplerate[dam_ch_in1] = samplerate;
+               break;
+       case dam_ch_out:
+               tegra30_dam_set_output_samplerate(dam, samplerate);
+               dam->outsamplerate = samplerate;
+               break;
+       default:
+               break;
+       }
+}
+
+int tegra30_dam_set_gain(int ifc, int chid, int gain)
+{
+       if (ifc >= TEGRA30_NR_DAM_IFC)
+               return -EINVAL;
+
+       switch (chid) {
+       case dam_ch_in0:
+               tegra30_dam_writel(dams_cont_info[ifc], gain,
+                       TEGRA30_DAM_CH0_CONV);
+               break;
+       case dam_ch_in1:
+               tegra30_dam_writel(dams_cont_info[ifc], gain,
+                       TEGRA30_DAM_CH1_CONV);
+               break;
+       default:
+               break;
+       }
 
-       tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CTRL);
+       return 0;
 }
+
+int tegra30_dam_set_acif(int ifc, int chid, unsigned int audio_channels,
+       unsigned int audio_bits, unsigned int client_channels,
+       unsigned int client_bits)
+{
+       unsigned int reg;
+       unsigned int value = 0;
+
+       if (ifc >= TEGRA30_NR_DAM_IFC)
+               return -EINVAL;
+
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+       /*ch0 takes input as mono always*/
+       if ((chid == dam_ch_in0) &&
+               ((client_channels != 1)))
+               return -EINVAL;
+       /*as per dam spec file chout is fixed to 32 bits*/
+       /*so accept ch0, ch1 and chout as 32bit always*/
+       if (client_bits != 32)
+               return -EINVAL;
+#else
+       /*ch0 takes input as mono/16bit always*/
+       if ((chid == dam_ch_in0) &&
+               ((client_channels != 1) || (client_bits != 16)))
+               return -EINVAL;
 #endif
 
+       value |= TEGRA30_CIF_MONOCONV_COPY;
+       value |= TEGRA30_CIF_STEREOCONV_CH0;
+       value |= (audio_channels-1)  << TEGRA30_AUDIO_CHANNELS_SHIFT;
+       value |= (((audio_bits>>2)-1)<<TEGRA30_AUDIO_BITS_SHIFT);
+       value |= (client_channels-1)  << TEGRA30_CLIENT_CHANNELS_SHIFT;
+       value |= (((client_bits>>2)-1)<<TEGRA30_CLIENT_BITS_SHIFT);
+
+       switch (chid) {
+       case dam_ch_out:
+               value |= TEGRA30_CIF_DIRECTION_TX;
+               reg = TEGRA30_DAM_AUDIOCIF_OUT_CTRL;
+               break;
+       case dam_ch_in0:
+               value |= TEGRA30_CIF_DIRECTION_RX;
+               reg = TEGRA30_DAM_AUDIOCIF_CH0_CTRL;
+               break;
+       case dam_ch_in1:
+               value |= TEGRA30_CIF_DIRECTION_RX;
+               reg = TEGRA30_DAM_AUDIOCIF_CH1_CTRL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       tegra30_dam_writel(dams_cont_info[ifc], value, reg);
+
+       return 0;
+}
+
 void tegra30_dam_enable(int ifc, int on, int chid)
 {
        u32 old_val, val, enreg;
@@ -1069,14 +1114,16 @@ int tegra30_dam_set_acif_stereo_conv(int ifc, int chtype, int conv)
        return 0;
 }
 
+
+/*
+DAM Driver probe and remove functions
+*/
+
 static int tegra30_dam_probe(struct platform_device *pdev)
 {
        struct resource *res,  *region;
        struct tegra30_dam_context *dam;
        int ret = 0;
-#ifdef CONFIG_PM
-       int i;
-#endif
        int clkm_rate;
        u32 val32;
 
@@ -1100,7 +1147,10 @@ static int tegra30_dam_probe(struct platform_device *pdev)
                ret = -ENOMEM;
                goto exit;
        }
+       dams_cont_info[pdev->id]->dev = &pdev->dev;
+
        dam = dams_cont_info[pdev->id];
+       dev_set_drvdata(&pdev->dev, dam);
 
        dam->dam_clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(dam->dam_clk)) {
@@ -1136,28 +1186,28 @@ static int tegra30_dam_probe(struct platform_device *pdev)
                goto err_clk_put_dam;
        }
 
-#ifdef CONFIG_PM
-       /* cache the POR values of DAM regs*/
-       tegra30_dam_enable_clock(pdev->id);
-
-       for (i = 0; i <= TEGRA30_DAM_CTRL_REGINDEX; i++) {
-               if ((i == TEGRA30_DAM_CTRL_RSVD_6) ||
-                       (i == TEGRA30_DAM_CTRL_RSVD_10))
-                       continue;
-
-                       dam->reg_cache[i] =
-                               tegra30_dam_readl(dam, i << 2);
+       dam->regmap = devm_regmap_init_mmio(&pdev->dev, dam->damregs,
+                                   &tegra30_dam_regmap_config);
+       if (IS_ERR(dam->regmap)) {
+               dev_err(&pdev->dev, "regmap init failed\n");
+               ret = PTR_ERR(dam->regmap);
+               goto err_clk_put_dam;
        }
+       regcache_cache_only(dam->regmap, true);
 
-       tegra30_dam_disable_clock(pdev->id);
-#endif
-
-       platform_set_drvdata(pdev, dam);
+       pm_runtime_enable(&pdev->dev);
+       if (!pm_runtime_enabled(&pdev->dev)) {
+               ret = tegra30_dam_runtime_resume(&pdev->dev);
+               if (ret)
+                       goto err_pm_disable;
+       }
 
        tegra30_dam_debug_add(dam, pdev->id);
 
        return 0;
 
+err_pm_disable:
+       pm_runtime_disable(&pdev->dev);
 err_clk_put_dam:
        clk_put(dam->dam_clk);
 err_free:
@@ -1170,6 +1220,10 @@ static int tegra30_dam_remove(struct platform_device *pdev)
 {
        struct tegra30_dam_context *dam;
 
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev))
+               tegra30_dam_runtime_suspend(&pdev->dev);
+
        dam = platform_get_drvdata(pdev);
        clk_put(dam->dam_clk);
        tegra30_dam_debug_remove(dam);
@@ -1178,26 +1232,27 @@ static int tegra30_dam_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id tegra30_dam_of_match[] = {
+       { .compatible = "nvidia,tegra30-dam",},
+       {},
+};
+
+static const struct dev_pm_ops tegra30_dam_pm_ops = {
+       SET_RUNTIME_PM_OPS(tegra30_dam_runtime_suspend,
+                          tegra30_dam_runtime_resume, NULL)
+};
+
 static struct platform_driver tegra30_dam_driver = {
-       .probe = tegra30_dam_probe,
-       .remove = tegra30_dam_remove,
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
+               .of_match_table = tegra30_dam_of_match,
+               .pm = &tegra30_dam_pm_ops,
        },
+       .probe = tegra30_dam_probe,
+       .remove = tegra30_dam_remove,
 };
-
-static int __init tegra30_dam_modinit(void)
-{
-       return platform_driver_register(&tegra30_dam_driver);
-}
-module_init(tegra30_dam_modinit);
-
-static void __exit tegra30_dam_modexit(void)
-{
-       platform_driver_unregister(&tegra30_dam_driver);
-}
-module_exit(tegra30_dam_modexit);
+module_platform_driver(tegra30_dam_driver);
 
 MODULE_AUTHOR("Nikesh Oswal <noswal@nvidia.com>");
 MODULE_DESCRIPTION("Tegra 30 DAM driver");
index 0e9733c..d23bd60 100644 (file)
@@ -2,7 +2,7 @@
  * tegra30_dam.h - Tegra 30 DAM driver.
  *
  * Author: Nikesh Oswal <noswal@nvidia.com>
- * Copyright (C) 2011 - NVIDIA, Inc.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #define TEGRA30_DAM_DISABLE                            0
 
 struct tegra30_dam_context {
+       struct device *dev;
        int                     outsamplerate;
        bool                    ch_alloc[TEGRA30_DAM_NUM_INPUT_CHANNELS];
        int                     ch_enable_refcnt[TEGRA30_DAM_NUM_INPUT_CHANNELS];
        int                     ch_insamplerate[TEGRA30_DAM_NUM_INPUT_CHANNELS];
-#ifdef CONFIG_PM
-       int                     reg_cache[TEGRA30_DAM_CTRL_REGINDEX + 1];
-#endif
        struct clk              *dam_clk;
        bool                    in_use;
        void __iomem            *damregs;
        struct dentry           *debug;
+       struct regmap *regmap;
 };
 
 struct tegra30_dam_src_step_table {
@@ -174,9 +173,6 @@ struct tegra30_dam_src_step_table {
        int stepreset;
 };
 
-#ifdef CONFIG_PM
-int tegra30_dam_resume(int ifc);
-#endif
 void tegra30_dam_disable_clock(int ifc);
 int tegra30_dam_enable_clock(int ifc);
 int tegra30_dam_allocate_controller(void);
@@ -193,11 +189,6 @@ int tegra30_dam_set_acif_stereo_conv(int ifc, int chtype, int conv);
 void tegra30_dam_ch0_set_datasync(int ifc, int datasync);
 void tegra30_dam_ch1_set_datasync(int ifc, int datasync);
 #ifndef CONFIG_ARCH_TEGRA_3x_SOC
-void tegra30_dam_write_coeff_ram(int ifc, int fsin, int fsout);
-void tegra30_dam_set_farrow_param(int ifc, int fsin, int fsout);
-void tegra30_dam_set_biquad_fixed_coef(int ifc);
-void tegra30_dam_enable_coeff_ram(int ifc);
-void tegra30_dam_set_filter_stages(int ifc, int fsin, int fsout);
 void tegra30_dam_enable_stereo_mixing(int ifc);
 #endif
 
index 0e9991e..1a1ea32 100644 (file)
@@ -2,13 +2,13 @@
  * tegra30_i2s.c - Tegra30 I2S driver
  *
  * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * Based on code copyright/by:
  *
- * Copyright (c) 2009-2013, NVIDIA Corporation.
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2009-2013, NVIDIA CORPORATION. All rights reserved.
  * Scott Peterson <speterson@nvidia.com>
+ * Manoj Gangwal <mgangwal@nvidia.com>
  *
  * Copyright (C) 2010 Google, Inc.
  * Iliyan Malchev <malchev@google.com>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <mach/tegra_asoc_pdata.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <asm/delay.h>
+#include <mach/tegra_asoc_pdata.h>
 
 #include "tegra30_ahub.h"
 #include "tegra30_dam.h"
@@ -48,8 +49,7 @@
 
 #define DRV_NAME "tegra30-i2s"
 
-static struct tegra30_i2s  i2scont[TEGRA30_NR_I2S_IFC];
-
+static struct tegra30_i2s *i2scont[TEGRA30_NR_I2S_IFC];
 #if defined(CONFIG_ARCH_TEGRA_14x_SOC)
 static struct tegra30_i2s bbc1cont;
 #endif
@@ -58,6 +58,8 @@ static int tegra30_i2s_runtime_suspend(struct device *dev)
 {
        struct tegra30_i2s *i2s = dev_get_drvdata(dev);
 
+       tegra30_ahub_disable_clocks();
+
        regcache_cache_only(i2s->regmap, true);
 
        clk_disable_unprepare(i2s->clk_i2s);
@@ -70,6 +72,8 @@ static int tegra30_i2s_runtime_resume(struct device *dev)
        struct tegra30_i2s *i2s = dev_get_drvdata(dev);
        int ret;
 
+       tegra30_ahub_enable_clocks();
+
        ret = clk_prepare_enable(i2s->clk_i2s);
        if (ret) {
                dev_err(dev, "clk_enable failed: %d\n", ret);
@@ -98,8 +102,9 @@ int tegra30_i2s_startup(struct snd_pcm_substream *substream,
                i2s->playback_dma_data.width = 32;
 
                if (!i2s->is_dam_used)
-                       tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif,
-                                                      i2s->playback_fifo_cif);
+                       tegra30_ahub_set_rx_cif_source(
+                               i2s->playback_i2s_cif,
+                               i2s->playback_fifo_cif);
        } else {
                i2s->capture_ref_count++;
                ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif,
@@ -121,34 +126,65 @@ void tegra30_i2s_shutdown(struct snd_pcm_substream *substream,
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                if (i2s->playback_ref_count == 1)
-                       tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif);
+                       tegra30_ahub_unset_rx_cif_source(
+                               i2s->playback_i2s_cif);
 
                /* free the apbif dma channel*/
                tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
-               i2s->txcif = -1;
+               i2s->playback_fifo_cif = -1;
 
                /* decrement the playback ref count */
                i2s->playback_ref_count--;
        } else {
                if (i2s->capture_ref_count == 1)
                        tegra30_ahub_unset_rx_cif_source(i2s->capture_fifo_cif);
+
+               /* free the apbif dma channel*/
                tegra30_ahub_free_rx_fifo(i2s->capture_fifo_cif);
+
+               /* decrement the capture ref count */
                i2s->capture_ref_count--;
        }
 }
 
+static int tegra30_i2s_set_dai_sysclk(struct snd_soc_dai *dai,
+               int clk_id, unsigned int freq, int dir)
+{
+       struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+       i2s->i2s_bit_clk = freq;
+
+       return 0;
+}
+
 static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        unsigned int mask, val;
 
+       mask = TEGRA30_I2S_CH_CTRL_EGDE_CTRL_MASK |
+               TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_MASK;
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
+               val = TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
+               if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK)
+                       == SND_SOC_DAIFMT_DSP_A) {
+                       val = TEGRA30_I2S_CH_CTRL_EGDE_CTRL_NEG_EDGE |
+                               TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_ON_HALF_BIT_CLK;
+               }
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               val = TEGRA30_I2S_CH_CTRL_EGDE_CTRL_NEG_EDGE;
+               if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK)
+                       == SND_SOC_DAIFMT_DSP_A) {
+                       val = TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
+               }
                break;
        default:
                return -EINVAL;
        }
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_CH_CTRL, mask, val);
 
        mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -156,6 +192,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
+               val = 0;
                break;
        default:
                return -EINVAL;
@@ -163,41 +200,33 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
 
        mask |= TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
                TEGRA30_I2S_CTRL_LRCK_MASK;
-       i2s->reg_ch_ctrl &= ~TEGRA30_I2S_CH_CTRL_EGDE_CTRL_MASK;
        i2s->daifmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
        switch (i2s->daifmt) {
        case SND_SOC_DAIFMT_DSP_A:
-               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
-               val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
-               i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_NEG_EDGE;
+               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC |
+                     TEGRA30_I2S_CTRL_LRCK_R_LOW;
                break;
        case SND_SOC_DAIFMT_DSP_B:
-               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
-               val |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
-               i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
+               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC |
+                     TEGRA30_I2S_CTRL_LRCK_R_LOW;
                break;
        case SND_SOC_DAIFMT_I2S:
-               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
-               val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
-               i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
+               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK |
+                     TEGRA30_I2S_CTRL_LRCK_L_LOW;
                break;
        case SND_SOC_DAIFMT_RIGHT_J:
-               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
-               val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
-               i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
+               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK |
+                     TEGRA30_I2S_CTRL_LRCK_R_LOW;
                break;
        case SND_SOC_DAIFMT_LEFT_J:
-               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
-               val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
-               i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
+               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK |
+                     TEGRA30_I2S_CTRL_LRCK_R_LOW;
                break;
        default:
                return -EINVAL;
        }
 
-       pm_runtime_get_sync(dai->dev);
        regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
-       pm_runtime_put(dai->dev);
 
        return 0;
 }
@@ -206,61 +235,79 @@ static void tegra30_i2s_set_channel_bit_count(struct tegra30_i2s *i2s,
                                int i2sclock, int srate)
 {
        int sym_bitclk, bitcnt;
-       u32 val;
+       unsigned int mask, val;
 
        bitcnt = (i2sclock / (2 * srate)) - 1;
        sym_bitclk = !(i2sclock % (2 * srate));
 
+       mask = TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK;
        val = bitcnt << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
 
+       mask |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
        if (!sym_bitclk)
                val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
 
-       regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val);
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_TIMING, mask, val);
 }
 
 static void tegra30_i2s_set_data_offset(struct tegra30_i2s *i2s)
 {
-       u32 val;
+       unsigned int mask, val;
        int rx_data_offset = i2s->dsp_config.rx_data_offset;
        int tx_data_offset = i2s->dsp_config.tx_data_offset;
 
-       val = (rx_data_offset <<
-                               TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
-                       (tx_data_offset <<
-                               TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
+       mask = TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_MASK |
+              TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_MASK;
+       val = (rx_data_offset << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
+             (tx_data_offset << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
 
-       regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val);
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_OFFSET, mask, val);
 }
 
 static void tegra30_i2s_set_slot_control(struct tegra30_i2s *i2s, int stream)
 {
-       u32 mask, val = 0;
+       unsigned int mask, val;
        int tx_mask = i2s->dsp_config.tx_mask;
        int rx_mask = i2s->dsp_config.rx_mask;
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+               mask = TEGRA30_I2S_SLOT_CTRL2_TX_SLOT_ENABLES_MASK;
+               val = (tx_mask << TEGRA30_I2S_SLOT_CTRL2_TX_SLOT_ENABLES_SHIFT);
+#else
                mask = TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_MASK;
-               val |= (tx_mask << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT);
+               val = (tx_mask << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT);
+#endif
        } else {
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+               mask = TEGRA30_I2S_SLOT_CTRL2_RX_SLOT_ENABLES_MASK;
+               val = (rx_mask << TEGRA30_I2S_SLOT_CTRL2_RX_SLOT_ENABLES_SHIFT);
+#else
                mask = TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_MASK;
-               val |= (rx_mask << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT);
+               val = (rx_mask << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT);
+#endif
        }
-
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_SLOT_CTRL2, mask, val);
+       mask = TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK;
+       val = (i2s->dsp_config.num_slots - 1) <<
+              TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT;
+#else
        mask |= TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK;
-       val |= (i2s->dsp_config.num_slots - 1)
-                       << TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT;
-
+       val |= (i2s->dsp_config.num_slots - 1) <<
+              TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT;
+#endif
        regmap_update_bits(i2s->regmap, TEGRA30_I2S_SLOT_CTRL, mask, val);
 }
 
 static int tegra30_i2s_tdm_setup_clocks(struct device *dev,
                                struct tegra30_i2s *i2s, int *i2sclock)
 {
+       unsigned int val;
        int ret;
 
-       if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_MASTER_ENABLE) {
-
+       regmap_read(i2s->regmap, TEGRA30_I2S_CTRL, &val);
+       if (val & TEGRA30_I2S_CTRL_MASTER_ENABLE) {
                ret = clk_set_parent(i2s->clk_i2s, i2s->clk_pll_a_out0);
                if (ret) {
                        dev_err(dev, "Can't set parent of I2S clock\n");
@@ -273,7 +320,6 @@ static int tegra30_i2s_tdm_setup_clocks(struct device *dev,
                        return ret;
                }
        } else {
-
                ret = clk_set_rate(i2s->clk_i2s_sync, *i2sclock);
                if (ret) {
                        dev_err(dev, "Can't set I2S sync clock rate\n");
@@ -281,7 +327,7 @@ static int tegra30_i2s_tdm_setup_clocks(struct device *dev,
                }
 
                ret = clk_set_parent(clk_get_parent(i2s->clk_audio_2x),
-                                               i2s->clk_i2s_sync);
+                                                   i2s->clk_i2s_sync);
                if (ret) {
                        dev_err(dev, "Can't set parent of audio2x clock\n");
                        return ret;
@@ -309,7 +355,7 @@ static int tegra30_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
 {
        struct device *dev = substream->pcm->card->dev;
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       u32 val;
+       unsigned int mask, val;
        int i2s_client_ch, i2s_audio_ch;
        int i2s_audio_bits = 0, i2s_client_bits = 0;
        int i2sclock, srate;
@@ -318,8 +364,8 @@ static int tegra30_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
        srate = params_rate(params);
 
        i2sclock = srate *
-                               i2s->dsp_config.num_slots *
-                               i2s->dsp_config.slot_width;
+                  i2s->dsp_config.num_slots *
+                  i2s->dsp_config.slot_width;
 
        ret = tegra30_i2s_tdm_setup_clocks(dev, i2s, &i2sclock);
        if (ret)
@@ -333,37 +379,45 @@ static int tegra30_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
        i2s_client_ch = i2s->dsp_config.num_slots;
        i2s_audio_ch = i2s->dsp_config.num_slots;
 
-       i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
+       mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
        switch (i2s->dsp_config.slot_width) {
        case 16:
                i2s_audio_bits = TEGRA30_AUDIOCIF_BITS_16;
                i2s_client_bits = TEGRA30_AUDIOCIF_BITS_16;
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16;
+               val = TEGRA30_I2S_CTRL_BIT_SIZE_16;
                break;
        case 32:
                i2s_audio_bits = TEGRA30_AUDIOCIF_BITS_32;
                i2s_client_bits = TEGRA30_AUDIOCIF_BITS_32;
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_32;
+               val = TEGRA30_I2S_CTRL_BIT_SIZE_32;
                break;
        default:
                dev_err(dev, "unknown slot_width %d\n",
                                i2s->dsp_config.slot_width);
                return -EINVAL;
        }
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
 
+       mask = TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK |
+              TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
+              TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK |
+              TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK |
+              TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK |
+              TEGRA30_AUDIOCIF_CTRL_DIRECTION_MASK;
        val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
-                       ((i2s_audio_ch - 1) <<
-                        TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
-                       ((i2s_client_ch - 1) <<
-                        TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
-                       (i2s_audio_bits <<
-                        TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
-                       (i2s_client_bits <<
-                        TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
+             ((i2s_audio_ch - 1) <<
+             TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+             ((i2s_client_ch - 1) <<
+             TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
+             (i2s_audio_bits <<
+             TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
+             (i2s_client_bits <<
+             TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
-               tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val);
+               regmap_update_bits(i2s->regmap, TEGRA30_I2S_CIF_RX_CTRL,
+                                  mask, val);
 
                tegra30_ahub_set_tx_cif_channels(i2s->playback_fifo_cif,
                                                i2s_audio_ch,
@@ -375,7 +429,8 @@ static int tegra30_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
 
        } else {
                val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
-               tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val);
+               regmap_update_bits(i2s->regmap, TEGRA30_I2S_CIF_TX_CTRL,
+                                  mask, val);
 
                tegra30_ahub_set_rx_cif_channels(i2s->capture_fifo_cif,
                                                i2s_audio_ch,
@@ -390,10 +445,10 @@ static int tegra30_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
 
        tegra30_i2s_set_data_offset(i2s);
 
-       i2s->reg_ch_ctrl &= ~TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_MASK;
-       i2s->reg_ch_ctrl |= (i2s->dsp_config.slot_width - 1) <<
+       mask = TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_MASK;
+       val = (i2s->dsp_config.slot_width - 1) <<
                        TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_SHIFT;
-       tegra30_i2s_write(i2s, TEGRA30_I2S_CH_CTRL, i2s->reg_ch_ctrl);
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_CH_CTRL, mask, val);
 
        return 0;
 }
@@ -404,14 +459,14 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
 {
        struct device *dev = dai->dev;
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val, reg, i;
+       unsigned int mask, val, reg, reg_ctrl, i;
        int ret, sample_size, srate, i2sclock, bitcnt, sym_bitclk;
        int i2s_client_ch;
 
        mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_8;
+               val = TEGRA30_I2S_CTRL_BIT_SIZE_8;
                sample_size = 8;
                break;
        case SNDRV_PCM_FORMAT_S16_LE:
@@ -419,36 +474,38 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
                sample_size = 16;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_24;
+               val = TEGRA30_I2S_CTRL_BIT_SIZE_24;
                sample_size = 24;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_32;
+               val = TEGRA30_I2S_CTRL_BIT_SIZE_32;
                sample_size = 32;
                break;
        default:
                return -EINVAL;
        }
-
-       regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
-
        bitcnt = sample_size;
        i = 0;
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
 
+       regmap_read(i2s->regmap, TEGRA30_I2S_CTRL, &reg_ctrl);
        /* TDM mode */
-       if ((i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) &&
+       if ((reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) &&
                (i2s->dsp_config.slot_width > 2))
                return tegra30_i2s_tdm_hw_params(substream, params, dai);
 
        srate = params_rate(params);
 
-       if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_MASTER_ENABLE) {
+       if (reg_ctrl & TEGRA30_I2S_CTRL_MASTER_ENABLE) {
                i2sclock = srate * params_channels(params) * sample_size;
 
                /* Additional "* 4" is needed for FSYNC mode */
-               if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
+               if (reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
                        i2sclock *= 4;
 
+               if (i2s->i2s_bit_clk != 0)
+                       i2sclock = i2s->i2s_bit_clk;
+
                ret = clk_set_parent(i2s->clk_i2s, i2s->clk_pll_a_out0);
                if (ret) {
                        dev_err(dev, "Can't set parent of I2S clock\n");
@@ -461,32 +518,14 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
                        return ret;
                }
 
-               if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) {
+               if (reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) {
                        bitcnt = (i2sclock / srate) - 1;
                        sym_bitclk = !(i2sclock % srate);
-#ifndef CONFIG_ARCH_TEGRA_3x_SOC
-                       val = tegra30_i2s_read(i2s, TEGRA30_I2S_SLOT_CTRL2);
-
-                       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                               val &=
-                                 ~TEGRA30_I2S_SLOT_CTRL2_TX_SLOT_ENABLES_MASK;
-                               val |= ((1 << params_channels(params)) - 1) <<
-                                 TEGRA30_I2S_SLOT_CTRL2_TX_SLOT_ENABLES_SHIFT;
-                       } else {
-                               val &=
-                                 ~TEGRA30_I2S_SLOT_CTRL2_RX_SLOT_ENABLES_MASK;
-                               val |= ((1 << params_channels(params)) - 1) <<
-                                 TEGRA30_I2S_SLOT_CTRL2_RX_SLOT_ENABLES_SHIFT;
-                       }
-                       tegra30_i2s_write(i2s, TEGRA30_I2S_SLOT_CTRL2, val);
-#endif
                } else {
                        bitcnt = (i2sclock / (2 * srate)) - 1;
                        sym_bitclk = !(i2sclock % (2 * srate));
-                       i2s_client_ch = 2;
                }
                val = bitcnt << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
-
                if (!sym_bitclk)
                        val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
 
@@ -495,7 +534,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
                i2sclock = srate * params_channels(params) * sample_size;
 
                /* Additional "* 2" is needed for FSYNC mode */
-               if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
+               if (reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
                        i2sclock *= 2;
 
                ret = clk_set_rate(i2s->clk_i2s_sync, i2sclock);
@@ -522,9 +561,10 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
                        dev_err(dev, "Can't set parent of audio2x clock\n");
                        return ret;
                }
+
        }
 
-       i2s_client_ch = (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) ?
+       i2s_client_ch = (reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) ?
                        params_channels(params) : 2;
 
        switch (sample_size) {
@@ -615,7 +655,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
                }
        } else {
                val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
-               reg = TEGRA30_I2S_CIF_TX_CTRL;
+               reg = TEGRA30_I2S_CIF_TX_CTRL, val;
 
                tegra30_ahub_set_rx_cif_channels(i2s->capture_fifo_cif,
                                                 params_channels(params),
@@ -653,7 +693,6 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
                        break;
                }
        }
-
        regmap_write(i2s->regmap, reg, val);
 
        switch (i2s->daifmt) {
@@ -673,46 +712,67 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
        default:
                return -EINVAL;
        }
+
        val = (val << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
-                 (val << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
+             (val << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
+
        regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val);
 
-       tegra30_i2s_write(i2s, TEGRA30_I2S_CH_CTRL, i2s->reg_ch_ctrl);
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+       if (reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) {
+               regmap_read(i2s->regmap, TEGRA30_I2S_SLOT_CTRL2, &val);
+
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       val &=
+                               ~TEGRA30_I2S_SLOT_CTRL2_TX_SLOT_ENABLES_MASK;
+                       val |= ((1 << params_channels(params)) - 1) <<
+                               TEGRA30_I2S_SLOT_CTRL2_TX_SLOT_ENABLES_SHIFT;
+               } else {
+                       val &=
+                               ~TEGRA30_I2S_SLOT_CTRL2_RX_SLOT_ENABLES_MASK;
+                       val |= ((1 << params_channels(params)) - 1) <<
+                               TEGRA30_I2S_SLOT_CTRL2_RX_SLOT_ENABLES_SHIFT;
+               }
+               regmap_write(i2s->regmap, TEGRA30_I2S_SLOT_CTRL2, val);
+       }
 
        val = 0;
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+       mask = TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK;
+       if (reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
+               val = (params_channels(params) - 1) <<
+                       TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT;
+#else
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                mask = TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_MASK;
-               val |= (1 << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT);
+               val = (1 << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT);
        } else {
                mask = TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_MASK;
-               val |= (1 << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT);
+               val = (1 << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT);
        }
-       regmap_update_bits(i2s->regmap, TEGRA30_I2S_SLOT_CTRL, mask, val);
-#else
-       if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
-               val = params_channels(params) - 1;
-       regmap_write(i2s->regmap, TEGRA30_I2S_SLOT_CTRL, val);
 #endif
 
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_SLOT_CTRL, mask, val);
+
        return 0;
 }
 
 static int tegra30_i2s_soft_reset(struct tegra30_i2s *i2s)
 {
        int dcnt = 10;
+       unsigned int val;
 
-       i2s->reg_ctrl |= TEGRA30_I2S_CTRL_SOFT_RESET;
-       tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
+               TEGRA30_I2S_CTRL_SOFT_RESET, TEGRA30_I2S_CTRL_SOFT_RESET);
 
-       while ((tegra30_i2s_read(i2s, TEGRA30_I2S_CTRL) &
-                      TEGRA30_I2S_CTRL_SOFT_RESET) && dcnt--)
+       do {
                udelay(100);
+               regmap_read(i2s->regmap, TEGRA30_I2S_CTRL, &val);
+       } while ((val & TEGRA30_I2S_CTRL_SOFT_RESET) && dcnt--);
 
        /* Restore reg_ctrl to ensure if a concurrent playback/capture
           session was active it continues after SOFT_RESET */
-       i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_SOFT_RESET;
-       tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
+               TEGRA30_I2S_CTRL_SOFT_RESET, 0);
 
        return (dcnt < 0) ? -ETIMEDOUT : 0;
 }
@@ -735,6 +795,7 @@ static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
        if (i2s->playback_ref_count == 1) {
                regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
                                   TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
+
                while (tegra30_ahub_tx_fifo_is_enabled(i2s->id) && dcnt--)
                        udelay(100);
 
@@ -758,7 +819,7 @@ static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
 static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
 {
        tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif);
-       if (!i2s->is_call_mode_rec && (i2s->capture_ref_count == 1))
+       if (!i2s->is_call_mode_rec)
                regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
                                   TEGRA30_I2S_CTRL_XFER_EN_RX,
                                   TEGRA30_I2S_CTRL_XFER_EN_RX);
@@ -767,6 +828,7 @@ static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
 static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
 {
        int dcnt = 10;
+
        if (!i2s->is_call_mode_rec && (i2s->capture_ref_count == 1)) {
                regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
                                   TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
@@ -788,7 +850,7 @@ static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
                               dcnt--)
                                udelay(100);
                }
-               tegra30_ahub_disable_rx_fifo(i2s->rxcif);
+               tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif);
        }
 }
 
@@ -858,59 +920,42 @@ int tegra30_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
        return 0;
 }
 
-#ifdef CONFIG_PM
-int tegra30_i2s_resume(struct snd_soc_dai *cpu_dai)
-{
-       struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
-       int ret = 0;
-
-       //tegra30_ahub_apbif_resume();
-
-       if (i2s->dam_ch_refcount)
-               ret = tegra30_dam_resume(i2s->dam_ifc);
-
-       return ret;
-}
-#else
-#define tegra30_i2s_resume NULL
-#endif
-
 static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
        .startup        = tegra30_i2s_startup,
        .shutdown       = tegra30_i2s_shutdown,
        .set_fmt        = tegra30_i2s_set_fmt,
        .hw_params      = tegra30_i2s_hw_params,
        .trigger        = tegra30_i2s_trigger,
-       .set_tdm_slot = tegra30_i2s_set_tdm_slot,
+       .set_tdm_slot   = tegra30_i2s_set_tdm_slot,
+       .set_sysclk     = tegra30_i2s_set_dai_sysclk,
 };
 
-static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
+static struct snd_soc_dai_driver tegra30_i2s_dai_template = {
        .probe = tegra30_i2s_probe,
-       .resume = tegra30_i2s_resume,
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
                .channels_max = 16,
                .rates = SNDRV_PCM_RATE_8000_96000,
-               .formats = SNDRV_PCM_FMTBIT_S8 |
-                          SNDRV_PCM_FMTBIT_S16_LE |
-                          SNDRV_PCM_FMTBIT_S24_LE |
-                          SNDRV_PCM_FMTBIT_S32_LE,
+               .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
        },
        .capture = {
                .stream_name = "Capture",
                .channels_min = 1,
                .channels_max = 16,
                .rates = SNDRV_PCM_RATE_8000_96000,
-               .formats = SNDRV_PCM_FMTBIT_S8 |
-                          SNDRV_PCM_FMTBIT_S16_LE |
-                          SNDRV_PCM_FMTBIT_S24_LE |
-                          SNDRV_PCM_FMTBIT_S32_LE,
+               .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
        },
        .ops = &tegra30_i2s_dai_ops,
        .symmetric_rates = 1,
 };
 
+static const struct snd_soc_component_driver tegra30_i2s_component = {
+       .name           = DRV_NAME,
+};
+
 static bool tegra30_i2s_wr_rd_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
@@ -936,6 +981,9 @@ static bool tegra30_i2s_wr_rd_reg(struct device *dev, unsigned int reg)
        case TEGRA30_I2S_LCOEF_2_4_0:
        case TEGRA30_I2S_LCOEF_2_4_1:
        case TEGRA30_I2S_LCOEF_2_4_2:
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+       case TEGRA30_I2S_SLOT_CTRL2:
+#endif
                return true;
        default:
                return false;
@@ -959,7 +1007,11 @@ static const struct regmap_config tegra30_i2s_regmap_config = {
        .reg_bits = 32,
        .reg_stride = 4,
        .val_bits = 32,
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+       .max_register = TEGRA30_I2S_SLOT_CTRL2,
+#else
        .max_register = TEGRA30_I2S_LCOEF_2_4_2,
+#endif
        .writeable_reg = tegra30_i2s_wr_rd_reg,
        .readable_reg = tegra30_i2s_wr_rd_reg,
        .volatile_reg = tegra30_i2s_volatile_reg,
@@ -973,17 +1025,17 @@ int tegra30_i2s_set_cif_channels(struct tegra30_i2s  *i2s,
 {
        unsigned int val;
 
-       tegra30_i2s_enable_clocks(i2s);
+       pm_runtime_get_sync(i2s->dev);
 
-       val = tegra30_i2s_read(i2s, cif_reg);
+       regmap_read(i2s->regmap, cif_reg, &val);
        val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
                TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
        val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
              ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
 
-       tegra30_i2s_write(i2s, cif_reg, val);
+       regmap_write(i2s->regmap, cif_reg, val);
 
-       tegra30_i2s_disable_clocks(i2s);
+       pm_runtime_put(i2s->dev);
 
        return 0;
 }
@@ -995,17 +1047,17 @@ int tegra30_i2s_set_cif_bits(struct tegra30_i2s  *i2s,
 {
        unsigned int val;
 
-       tegra30_i2s_enable_clocks(i2s);
+       pm_runtime_get_sync(i2s->dev);
 
-       val = tegra30_i2s_read(i2s, cif_reg);
+       regmap_read(i2s->regmap, cif_reg, &val);
        val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK |
                TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK);
        val |= ((audio_bits) << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
              ((client_bits) << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
 
-       tegra30_i2s_write(i2s, cif_reg, val);
+       regmap_write(i2s->regmap, cif_reg, val);
 
-       tegra30_i2s_disable_clocks(i2s);
+       pm_runtime_put(i2s->dev);
 
        return 0;
 }
@@ -1016,15 +1068,15 @@ int tegra30_i2s_set_cif_stereo_conv(struct tegra30_i2s  *i2s,
 {
        unsigned int val;
 
-       tegra30_i2s_enable_clocks(i2s);
+       pm_runtime_get_sync(i2s->dev);
 
-       val = tegra30_i2s_read(i2s, cif_reg);
+       regmap_read(i2s->regmap, cif_reg, &val);
        val &= ~TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_MASK;
        val |= conv;
 
-       tegra30_i2s_write(i2s, cif_reg, val);
+       regmap_write(i2s->regmap, cif_reg, val);
 
-       tegra30_i2s_disable_clocks(i2s);
+       pm_runtime_put(i2s->dev);
 
        return 0;
 }
@@ -1032,20 +1084,16 @@ int tegra30_i2s_set_cif_stereo_conv(struct tegra30_i2s  *i2s,
 static int configure_baseband_i2s(struct tegra30_i2s  *i2s, int is_i2smaster,
                int i2s_mode, int channels, int rate, int bitsize, int bit_clk)
 {
-       u32 val;
        int i2sclock, bitcnt, ret, is_formatdsp;
-#ifndef CONFIG_ARCH_TEGRA_3x_SOC
-       u32  i;
-#endif
+       unsigned int mask, mask1, val, val1;
 
        is_formatdsp = (i2s_mode == TEGRA_DAIFMT_DSP_A) ||
                                        (i2s_mode == TEGRA_DAIFMT_DSP_B);
-
        if (bit_clk) {
                i2sclock = bit_clk;
        } else {
-           i2sclock = rate * channels * bitsize * 2;
-           /* additional 8 for baseband */
+               i2sclock = rate * channels * bitsize * 2;
+               /* additional 8 for baseband */
                if (is_formatdsp)
                        i2sclock *= 8;
        }
@@ -1082,60 +1130,58 @@ static int configure_baseband_i2s(struct tegra30_i2s  *i2s, int is_i2smaster,
                }
        }
 
-       i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
-                                       TEGRA30_I2S_CTRL_LRCK_MASK |
-                                       TEGRA30_I2S_CTRL_MASTER_ENABLE);
-       i2s->reg_ch_ctrl &= ~TEGRA30_I2S_CH_CTRL_EGDE_CTRL_MASK;
+       pm_runtime_get_sync(i2s->dev);
 
-       i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16;
+       mask = (TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
+              TEGRA30_I2S_CTRL_LRCK_MASK |
+              TEGRA30_I2S_CTRL_MASTER_ENABLE);
+       mask1 = TEGRA30_I2S_CH_CTRL_EGDE_CTRL_MASK;
 
+       val = TEGRA30_I2S_CTRL_BIT_SIZE_16;
        if (is_i2smaster)
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
 
        if (i2s_mode == TEGRA_DAIFMT_DSP_A) {
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
-               i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_NEG_EDGE;
+               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
+               val |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
+               val1 = TEGRA30_I2S_CH_CTRL_EGDE_CTRL_NEG_EDGE;
        } else if (i2s_mode == TEGRA_DAIFMT_DSP_B) {
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
-               i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
+               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
+               val |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
+               val1 = TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
        } else {
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
-               i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
-               i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
+               val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
+               val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
+               val1 = TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
        }
-
-       tegra30_i2s_write(i2s, TEGRA30_I2S_CH_CTRL, i2s->reg_ch_ctrl);
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_CH_CTRL, mask1, val1);
 
 #ifndef CONFIG_ARCH_TEGRA_3x_SOC
-       val = 0;
-       for (i = 0; i < channels; i++)
-               val |= (1 << i);
-
-       val |= val <<
-         TEGRA30_I2S_SLOT_CTRL2_TX_SLOT_ENABLES_SHIFT;
-       val |= val <<
-         TEGRA30_I2S_SLOT_CTRL2_RX_SLOT_ENABLES_SHIFT;
-       tegra30_i2s_write(i2s, TEGRA30_I2S_SLOT_CTRL2, val);
+       regmap_read(i2s->regmap, TEGRA30_I2S_SLOT_CTRL2, &val);
+       val &= ~TEGRA30_I2S_SLOT_CTRL2_TX_SLOT_ENABLES_MASK;
+       val |= ((1 << channels) - 1) <<
+               TEGRA30_I2S_SLOT_CTRL2_TX_SLOT_ENABLES_SHIFT;
+       val &= ~TEGRA30_I2S_SLOT_CTRL2_RX_SLOT_ENABLES_MASK;
+       val |= ((1 << channels) - 1) <<
+               TEGRA30_I2S_SLOT_CTRL2_RX_SLOT_ENABLES_SHIFT;
+       regmap_write(i2s->regmap, TEGRA30_I2S_SLOT_CTRL2, val);
 
        val = 0;
-       if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
-               val = channels  - 1;
-
-       tegra30_i2s_write(i2s, TEGRA30_I2S_SLOT_CTRL, val);
+       mask = TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK;
+       if (is_formatdsp)
+               val = (channels - 1) <<
+                       TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT;
 #else
-       val = tegra30_i2s_read(i2s, TEGRA30_I2S_SLOT_CTRL);
-       val &= ~(TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_MASK |
-               TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_MASK);
-       val |= (1 << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT |
-               1 << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT);
-       tegra30_i2s_write(i2s, TEGRA30_I2S_SLOT_CTRL, val);
+       mask = (TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_MASK |
+              TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_MASK);
+       val = (1 << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT |
+             1 << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT);
 #endif
+       regmap_update_bits(i2s->regmap, TEGRA30_I2S_SLOT_CTRL, mask, val);
 
        val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
              (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
-       tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val);
+       regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val);
 
        if (is_formatdsp) {
                bitcnt = (i2sclock/rate) - 1;
@@ -1148,8 +1194,7 @@ static int configure_baseband_i2s(struct tegra30_i2s  *i2s, int is_i2smaster,
                if (i2sclock % (2*rate))
                        val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
        }
-
-       tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val);
+       regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val);
 
        /* configure the i2s cif*/
        val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
@@ -1158,11 +1203,13 @@ static int configure_baseband_i2s(struct tegra30_i2s  *i2s, int is_i2smaster,
              TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
              TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16;
        val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
-       tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val);
+       regmap_write(i2s->regmap, TEGRA30_I2S_CIF_RX_CTRL, val);
 
        val &= ~TEGRA30_AUDIOCIF_CTRL_DIRECTION_MASK;
        val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
-       tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val);
+       regmap_write(i2s->regmap, TEGRA30_I2S_CIF_TX_CTRL, val);
+
+       pm_runtime_put(i2s->dev);
 
        return 0;
 }
@@ -1197,29 +1244,23 @@ static int configure_dam(struct tegra30_i2s  *i2s, int out_channel,
                        out_channel, out_bitsize, out_channel, out_bitsize);
 #endif
 
-#ifndef CONFIG_ARCH_TEGRA_3x_SOC
-       if (in_rate != out_rate) {
-               tegra30_dam_write_coeff_ram(i2s->dam_ifc, in_rate, out_rate);
-               tegra30_dam_set_farrow_param(i2s->dam_ifc, in_rate, out_rate);
-               tegra30_dam_set_biquad_fixed_coef(i2s->dam_ifc);
-               tegra30_dam_enable_coeff_ram(i2s->dam_ifc);
-               tegra30_dam_set_filter_stages(i2s->dam_ifc, in_rate, out_rate);
-       } else {
-               tegra30_dam_enable_stereo_mixing(i2s->dam_ifc);
-       }
-#endif
-
        return 0;
 }
 
-
 #if defined(CONFIG_ARCH_TEGRA_14x_SOC)
 int t14x_make_bt_voice_call_connections(struct codec_config *codec_info,
                                struct ahub_bbc1_config *bb_info,
                                int uses_voice_codec)
 {
-       struct tegra30_i2s *codec_i2s = &i2scont[codec_info->i2s_id];
-       struct tegra30_i2s *bb_i2s = &bbc1cont;
+       struct tegra30_i2s  *codec_i2s;
+       struct tegra30_i2s  *bb_i2s;
+       unsigned int val;
+
+       codec_i2s = i2scont[codec_info->i2s_id];
+       bb_i2s = &bbc1cont;
+
+       if (codec_i2s == NULL || bb_i2s == NULL)
+               return -ENOENT;
 
        /* increment the codec i2s playback ref count */
        codec_i2s->playback_ref_count++;
@@ -1227,6 +1268,8 @@ int t14x_make_bt_voice_call_connections(struct codec_config *codec_info,
        codec_i2s->capture_ref_count++;
        bb_i2s->capture_ref_count++;
 
+       pm_runtime_get_sync(codec_i2s->dev);
+
        /* Configure codec i2s */
        configure_baseband_i2s(codec_i2s, codec_info->is_i2smaster,
                codec_info->i2s_mode, codec_info->channels,
@@ -1270,10 +1313,8 @@ int t14x_make_bt_voice_call_connections(struct codec_config *codec_info,
        tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
                TEGRA30_DAM_CHIN0_SRC);
 
-       codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
-       codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
-               codec_i2s->reg_ctrl);
+       val = TEGRA30_I2S_CTRL_XFER_EN_TX | TEGRA30_I2S_CTRL_XFER_EN_RX;
+       regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL, val, val);
 
        return 0;
 }
@@ -1282,15 +1323,14 @@ int t14x_break_bt_voice_call_connections(struct codec_config *codec_info,
                                struct ahub_bbc1_config *bb_info,
                                int uses_voice_codec)
 {
-       struct tegra30_i2s *codec_i2s = &i2scont[codec_info->i2s_id];
+       struct tegra30_i2s *codec_i2s = i2scont[codec_info->i2s_id];
        struct tegra30_i2s *bb_i2s = &bbc1cont;
        int dcnt = 10;
 
        /* Disable Codec I2S RX (TX to ahub) */
        if (codec_i2s->capture_ref_count == 1)
-               codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
-
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+               regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL,
+                                  TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
 
        while (!tegra30_ahub_rx_fifo_is_empty(codec_i2s->id) && dcnt--)
                udelay(100);
@@ -1299,9 +1339,8 @@ int t14x_break_bt_voice_call_connections(struct codec_config *codec_info,
 
        /* Disable Codec I2S TX (RX from ahub) */
        if (codec_i2s->playback_ref_count == 1)
-                       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
-
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+               regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL,
+                                  TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
 
        while (!tegra30_ahub_tx_fifo_is_empty(codec_i2s->id) && dcnt--)
                udelay(100);
@@ -1349,18 +1388,10 @@ int t14x_break_bt_voice_call_connections(struct codec_config *codec_info,
        bb_i2s->capture_ref_count--;
 
        /* Soft reset */
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
-               codec_i2s->reg_ctrl | TEGRA30_I2S_CTRL_SOFT_RESET);
-
-       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
-       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_SOFT_RESET;
-
-       while ((tegra30_i2s_read(codec_i2s, TEGRA30_I2S_CTRL) &
-                       TEGRA30_I2S_CTRL_SOFT_RESET)  && dcnt--)
-               udelay(100);
+       tegra30_i2s_soft_reset(codec_i2s);
 
        /* Disable the clocks */
-       tegra30_i2s_disable_clocks(codec_i2s);
+       pm_runtime_put(codec_i2s->dev);
 
        return 0;
 }
@@ -1369,8 +1400,9 @@ int t14x_make_voice_call_connections(struct codec_config *codec_info,
                                struct ahub_bbc1_config *bb_info,
                                int uses_voice_codec)
 {
-       struct tegra30_i2s *codec_i2s = &i2scont[codec_info->i2s_id];
+       struct tegra30_i2s *codec_i2s = i2scont[codec_info->i2s_id];
        struct tegra30_i2s *bb_i2s = &bbc1cont;
+       unsigned int val;
 
        /* increment the codec i2s playback ref count */
        codec_i2s->playback_ref_count++;
@@ -1421,7 +1453,7 @@ int t14x_make_voice_call_connections(struct codec_config *codec_info,
                        (codec_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_BBC1_TX0);
 
        tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
-               (codec_i2s->dam_ifc*2), codec_i2s->txcif);
+               (codec_i2s->dam_ifc*2), codec_i2s->playback_i2s_cif);
 
        tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_BBC1_RX0,
                        TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
@@ -1438,10 +1470,8 @@ int t14x_make_voice_call_connections(struct codec_config *codec_info,
        tegra30_dam_enable(codec_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
                        TEGRA30_DAM_CHIN1);
 
-       codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
-       codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
-               codec_i2s->reg_ctrl);
+       val = TEGRA30_I2S_CTRL_XFER_EN_TX | TEGRA30_I2S_CTRL_XFER_EN_RX;
+       regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL, val, val);
 
        return 0;
 }
@@ -1450,15 +1480,18 @@ int t14x_break_voice_call_connections(struct codec_config *codec_info,
                                struct ahub_bbc1_config *bb_info,
                                int uses_voice_codec)
 {
-       struct tegra30_i2s *codec_i2s = &i2scont[codec_info->i2s_id];
+       struct tegra30_i2s *codec_i2s = i2scont[codec_info->i2s_id];
        struct tegra30_i2s *bb_i2s = &bbc1cont;
        int dcnt = 10;
+       unsigned int reg_ctrl;
+
+       if (codec_i2s == NULL || bb_i2s == NULL)
+               return -ENOENT;
 
        /* Disable Codec I2S RX (TX to ahub) */
        if (codec_i2s->capture_ref_count == 1)
-               codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
-
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+               regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL,
+                       TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
 
        while (!tegra30_ahub_rx_fifo_is_empty(codec_i2s->id) && dcnt--)
                udelay(100);
@@ -1467,9 +1500,8 @@ int t14x_break_voice_call_connections(struct codec_config *codec_info,
 
        /* Disable Codec I2S TX (RX from ahub) */
        if (codec_i2s->playback_ref_count == 1)
-               codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
-
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+               regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL,
+                       TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
 
        while (!tegra30_ahub_tx_fifo_is_empty(codec_i2s->id) && dcnt--)
                udelay(100);
@@ -1512,33 +1544,38 @@ int t14x_break_voice_call_connections(struct codec_config *codec_info,
        bb_i2s->capture_ref_count--;
 
        /* Soft reset */
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
-               codec_i2s->reg_ctrl | TEGRA30_I2S_CTRL_SOFT_RESET);
-
-       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
-       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_SOFT_RESET;
+       regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL,
+               TEGRA30_I2S_CTRL_SOFT_RESET, TEGRA30_I2S_CTRL_SOFT_RESET);
 
-       while ((tegra30_i2s_read(codec_i2s, TEGRA30_I2S_CTRL) &
-                       TEGRA30_I2S_CTRL_SOFT_RESET)  && dcnt--)
+       do {
                udelay(100);
+               regmap_read(codec_i2s->regmap, TEGRA30_I2S_CTRL, &reg_ctrl);
+       } while ((reg_ctrl & TEGRA30_I2S_CTRL_SOFT_RESET) && dcnt--);
+
+       dcnt = 10;
 
        /* Disable the clocks */
-       tegra30_i2s_disable_clocks(codec_i2s);
+       pm_runtime_put(codec_i2s->dev);
+       tegra30_dam_disable_clock(codec_i2s->dam_ifc);
+       tegra30_dam_disable_clock(bb_i2s->dam_ifc);
 
        return 0;
 }
 #endif
 
 int tegra30_make_voice_call_connections(struct codec_config *codec_info,
-                               struct codec_config *bb_info,
-                               int uses_voice_codec)
+                       struct codec_config *bb_info, int uses_voice_codec)
 {
        struct tegra30_i2s  *codec_i2s;
        struct tegra30_i2s  *bb_i2s;
-       int reg;
+       unsigned int val;
+       unsigned int en_flwcntrl = 0;
 
-       codec_i2s = &i2scont[codec_info->i2s_id];
-       bb_i2s = &i2scont[bb_info->i2s_id];
+       codec_i2s = i2scont[codec_info->i2s_id];
+       bb_i2s = i2scont[bb_info->i2s_id];
+
+       if (codec_i2s == NULL || bb_i2s == NULL)
+               return -ENOENT;
 
        /* increment the codec i2s playback ref count */
        codec_i2s->playback_ref_count++;
@@ -1546,25 +1583,20 @@ int tegra30_make_voice_call_connections(struct codec_config *codec_info,
        codec_i2s->capture_ref_count++;
        bb_i2s->capture_ref_count++;
 
-       /* Make sure i2s is disabled during the configiration */
-       tegra30_i2s_enable_clocks(codec_i2s);
-       reg = codec_i2s->reg_ctrl;
-       reg &= ~TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
-       reg &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
-       reg &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
-               codec_i2s->reg_ctrl);
-       tegra30_i2s_disable_clocks(codec_i2s);
-
-       tegra30_i2s_enable_clocks(bb_i2s);
-       reg = bb_i2s->reg_ctrl;
-       reg &= ~TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
-       reg &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
-       reg &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
-       tegra30_i2s_write(bb_i2s, TEGRA30_I2S_CTRL,
-               bb_i2s->reg_ctrl);
-       tegra30_i2s_disable_clocks(bb_i2s);
+       pm_runtime_get_sync(codec_i2s->dev);
+       pm_runtime_get_sync(bb_i2s->dev);
 
+       /* Make sure i2s is disabled during the configiration */
+       regmap_read(codec_i2s->regmap, TEGRA30_I2S_CTRL, &val);
+       val &= ~(TEGRA30_I2S_CTRL_TX_FLOWCTL_EN |
+               TEGRA30_I2S_CTRL_XFER_EN_TX |
+               TEGRA30_I2S_CTRL_XFER_EN_RX);
+       regmap_write(codec_i2s->regmap, TEGRA30_I2S_CTRL, val);
+       regmap_read(bb_i2s->regmap, TEGRA30_I2S_CTRL, &val);
+       val &= ~(TEGRA30_I2S_CTRL_TX_FLOWCTL_EN |
+               TEGRA30_I2S_CTRL_XFER_EN_TX |
+               TEGRA30_I2S_CTRL_XFER_EN_RX);
+       regmap_write(bb_i2s->regmap, TEGRA30_I2S_CTRL, val);
        msleep(20);
 
        /*Configure codec i2s*/
@@ -1590,45 +1622,46 @@ int tegra30_make_voice_call_connections(struct codec_config *codec_info,
                            codec_info->i2s_id, TEGRA30_AHUB_TXCIF_I2S0_TX0 +
                            bb_info->i2s_id);
                if (!(codec_info->is_i2smaster && bb_info->is_i2smaster)) {
-                       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_FLOWCTL,
+                       regmap_write(codec_i2s->regmap, TEGRA30_I2S_FLOWCTL,
                                TEGRA30_I2S_FILTER_QUAD);
-                       tegra30_i2s_write(bb_i2s, TEGRA30_I2S_FLOWCTL,
+                       regmap_write(bb_i2s->regmap, TEGRA30_I2S_FLOWCTL,
                                TEGRA30_I2S_FILTER_QUAD);
-                       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_TX_STEP, 4);
-                       tegra30_i2s_write(bb_i2s, TEGRA30_I2S_TX_STEP, 4);
-                       codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
-                       bb_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
+                       regmap_write(codec_i2s->regmap, TEGRA30_I2S_TX_STEP, 4);
+                       regmap_write(bb_i2s->regmap, TEGRA30_I2S_TX_STEP, 4);
+                       en_flwcntrl = 1;
                }
        } else {
-
                /*configure codec dam*/
                configure_dam(codec_i2s, codec_info->channels,
-                  codec_info->rate, codec_info->bitsize, bb_info->channels,
-                  bb_info->rate, bb_info->bitsize);
+                       codec_info->rate, codec_info->bitsize,
+                       bb_info->channels, bb_info->rate,
+                       bb_info->bitsize);
 
                /*configure bb dam*/
                configure_dam(bb_i2s, bb_info->channels,
-                       bb_info->rate, bb_info->bitsize, codec_info->channels,
-                       codec_info->rate, codec_info->bitsize);
+                       bb_info->rate, bb_info->bitsize,
+                       codec_info->channels, codec_info->rate,
+                       codec_info->bitsize);
 
                /*make ahub connections*/
 
-               /*if this is the only user of i2s tx, make i2s rx connection*/
+               /* if this is the only user of i2s tx then make
+               ahub i2s rx connection*/
                if (codec_i2s->playback_ref_count == 1) {
                        tegra30_ahub_set_rx_cif_source(
-                         TEGRA30_AHUB_RXCIF_I2S0_RX0 + codec_info->i2s_id,
-                         TEGRA30_AHUB_TXCIF_DAM0_TX0 + codec_i2s->dam_ifc);
+                       TEGRA30_AHUB_RXCIF_I2S0_RX0 + codec_info->i2s_id,
+                       TEGRA30_AHUB_TXCIF_DAM0_TX0 + codec_i2s->dam_ifc);
                }
 
-               tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
-                               bb_info->i2s_id, TEGRA30_AHUB_TXCIF_DAM0_TX0 +
-                               bb_i2s->dam_ifc);
-               tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
-                       (codec_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_I2S0_TX0 +
-                       bb_info->i2s_id);
-               tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
-                       (bb_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_I2S0_TX0 +
-                       codec_info->i2s_id);
+               tegra30_ahub_set_rx_cif_source(
+               TEGRA30_AHUB_RXCIF_I2S0_RX0 + bb_info->i2s_id,
+               TEGRA30_AHUB_TXCIF_DAM0_TX0 + bb_i2s->dam_ifc);
+               tegra30_ahub_set_rx_cif_source(
+               TEGRA30_AHUB_RXCIF_DAM0_RX0 + (codec_i2s->dam_ifc*2),
+               TEGRA30_AHUB_TXCIF_I2S0_TX0 + bb_info->i2s_id);
+               tegra30_ahub_set_rx_cif_source(
+               TEGRA30_AHUB_RXCIF_DAM0_RX0 + (bb_i2s->dam_ifc*2),
+               TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
 
                /*enable dam and i2s*/
                tegra30_dam_enable(codec_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
@@ -1637,39 +1670,36 @@ int tegra30_make_voice_call_connections(struct codec_config *codec_info,
                        TEGRA30_DAM_CHIN0_SRC);
        }
 
-       msleep(20);
-
-       codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
-       codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
-               codec_i2s->reg_ctrl);
+       val = TEGRA30_I2S_CTRL_XFER_EN_TX | TEGRA30_I2S_CTRL_XFER_EN_RX;
+       if (en_flwcntrl)
+               val |= TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
 
        msleep(20);
-
-       bb_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
-       bb_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
-       tegra30_i2s_write(bb_i2s, TEGRA30_I2S_CTRL,
-               bb_i2s->reg_ctrl);
+       regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL, val, val);
+       msleep(20);
+       regmap_update_bits(bb_i2s->regmap, TEGRA30_I2S_CTRL, val, val);
 
        return 0;
 }
 
 int tegra30_break_voice_call_connections(struct codec_config *codec_info,
-                               struct codec_config *bb_info,
-                               int uses_voice_codec)
+                       struct codec_config *bb_info, int uses_voice_codec)
 {
        struct tegra30_i2s  *codec_i2s;
        struct tegra30_i2s  *bb_i2s;
        int dcnt = 10;
+       unsigned int reg_ctrl;
+
+       codec_i2s = i2scont[codec_info->i2s_id];
+       bb_i2s = i2scont[bb_info->i2s_id];
 
-       codec_i2s = &i2scont[codec_info->i2s_id];
-       bb_i2s = &i2scont[bb_info->i2s_id];
+       if (codec_i2s == NULL || bb_i2s == NULL)
+               return -ENOENT;
 
        /*Disable Codec I2S RX (TX to ahub)*/
        if (codec_i2s->capture_ref_count == 1)
-               codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
-
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+               regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL,
+                                  TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
 
        while (!tegra30_ahub_rx_fifo_is_empty(codec_i2s->id) && dcnt--)
                udelay(100);
@@ -1677,8 +1707,8 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
        dcnt = 10;
 
        /*Disable baseband I2S TX (RX from ahub)*/
-       bb_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
-       tegra30_i2s_write(bb_i2s, TEGRA30_I2S_CTRL, bb_i2s->reg_ctrl);
+       regmap_update_bits(bb_i2s->regmap, TEGRA30_I2S_CTRL,
+                          TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
 
        while (!tegra30_ahub_tx_fifo_is_empty(bb_i2s->id) && dcnt--)
                udelay(100);
@@ -1686,8 +1716,8 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
        dcnt = 10;
 
        /*Disable baseband I2S RX (TX to ahub)*/
-       bb_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
-       tegra30_i2s_write(bb_i2s, TEGRA30_I2S_CTRL, bb_i2s->reg_ctrl);
+       regmap_update_bits(bb_i2s->regmap, TEGRA30_I2S_CTRL,
+                          TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
 
        while (!tegra30_ahub_rx_fifo_is_empty(bb_i2s->id) && dcnt--)
                udelay(100);
@@ -1696,9 +1726,8 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
 
        /*Disable Codec I2S TX (RX from ahub)*/
        if (codec_i2s->playback_ref_count == 1)
-                       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
-
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+               regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL,
+                                  TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
 
        while (!tegra30_ahub_tx_fifo_is_empty(codec_i2s->id) && dcnt--)
                udelay(100);
@@ -1711,16 +1740,16 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
                tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
                            codec_info->i2s_id);
        } else {
-
                /*Disable baseband DAM*/
                tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_DISABLE,
-                               TEGRA30_DAM_CHIN0_SRC);
+                       TEGRA30_DAM_CHIN0_SRC);
                tegra30_dam_free_channel(bb_i2s->dam_ifc,
-                               TEGRA30_DAM_CHIN0_SRC);
+                       TEGRA30_DAM_CHIN0_SRC);
                bb_i2s->dam_ch_refcount--;
                if (!bb_i2s->dam_ch_refcount)
                        tegra30_dam_free_controller(bb_i2s->dam_ifc);
 
+
                /*Disable Codec DAM*/
                tegra30_dam_enable(codec_i2s->dam_ifc,
                        TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN0_SRC);
@@ -1735,19 +1764,19 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
                i2s rx connection */
                if (codec_i2s->playback_ref_count == 1)
                        tegra30_ahub_unset_rx_cif_source(
-                          TEGRA30_AHUB_RXCIF_I2S0_RX0 + codec_info->i2s_id);
+                               TEGRA30_AHUB_RXCIF_I2S0_RX0
+                               + codec_info->i2s_id);
 
                tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0
-                                       + bb_info->i2s_id);
+                       + bb_info->i2s_id);
                tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
-                                       + (codec_i2s->dam_ifc*2));
+                       + (codec_i2s->dam_ifc*2));
                tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
-                                       + (bb_i2s->dam_ifc*2));
+                       + (bb_i2s->dam_ifc*2));
 
                tegra30_dam_disable_clock(codec_i2s->dam_ifc);
                tegra30_dam_disable_clock(bb_i2s->dam_ifc);
        }
-
        /* Decrement the codec and bb i2s playback ref count */
        codec_i2s->playback_ref_count--;
        bb_i2s->playback_ref_count--;
@@ -1755,23 +1784,25 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
        bb_i2s->capture_ref_count--;
 
        /* Soft reset */
-       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
-               codec_i2s->reg_ctrl | TEGRA30_I2S_CTRL_SOFT_RESET);
-       tegra30_i2s_write(bb_i2s, TEGRA30_I2S_CTRL,
-               bb_i2s->reg_ctrl | TEGRA30_I2S_CTRL_SOFT_RESET);
-
-       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
-       bb_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
-       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_SOFT_RESET;
-       bb_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_SOFT_RESET;
-
-       while ((tegra30_i2s_read(codec_i2s, TEGRA30_I2S_CTRL) &
-                       TEGRA30_I2S_CTRL_SOFT_RESET)  && dcnt--)
+       regmap_update_bits(codec_i2s->regmap, TEGRA30_I2S_CTRL,
+               TEGRA30_I2S_CTRL_SOFT_RESET, TEGRA30_I2S_CTRL_SOFT_RESET);
+       do {
                udelay(100);
+               regmap_read(codec_i2s->regmap, TEGRA30_I2S_CTRL, &reg_ctrl);
+       } while ((reg_ctrl & TEGRA30_I2S_CTRL_SOFT_RESET) && dcnt--);
        dcnt = 10;
-       while ((tegra30_i2s_read(bb_i2s, TEGRA30_I2S_CTRL) &
-                       TEGRA30_I2S_CTRL_SOFT_RESET)  && dcnt--)
+
+       regmap_update_bits(bb_i2s->regmap, TEGRA30_I2S_CTRL,
+               TEGRA30_I2S_CTRL_SOFT_RESET, TEGRA30_I2S_CTRL_SOFT_RESET);
+       do {
                udelay(100);
+               regmap_read(bb_i2s->regmap, TEGRA30_I2S_CTRL, &reg_ctrl);
+       } while ((reg_ctrl & TEGRA30_I2S_CTRL_SOFT_RESET) && dcnt--);
+       dcnt = 10;
+
+       /* Disable the clocks */
+       pm_runtime_put(codec_i2s->dev);
+       pm_runtime_put(bb_i2s->dev);
 
        return 0;
 }
@@ -1784,21 +1815,34 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
        void __iomem *regs;
        int ret;
 
-       /* This needs to be updated for DT */
-       return -ENODEV;
-
-       i2s = &i2scont[pdev->id];
-       dev_set_drvdata(&pdev->dev, i2s);
-       i2s->id = pdev->id;
-
-       ret = of_property_read_u32_array(pdev->dev.of_node,
-                                        "nvidia,ahub-cif-ids", cif_ids,
-                                        ARRAY_SIZE(cif_ids));
-       if (ret < 0)
+       i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_i2s), GFP_KERNEL);
+       if (!i2s) {
+               dev_err(&pdev->dev, "Can't allocate tegra30_i2s\n");
+               ret = -ENOMEM;
                goto err;
+       }
+       dev_set_drvdata(&pdev->dev, i2s);
+       i2s->dev = &pdev->dev;
+       i2s->dai = tegra30_i2s_dai_template;
+       i2s->dai.name = dev_name(&pdev->dev);
+
+       if (pdev->dev.of_node) {
+               ret = of_property_read_u32_array(pdev->dev.of_node,
+                                                "nvidia,ahub-cif-ids", cif_ids,
+                                                ARRAY_SIZE(cif_ids));
+               if (ret < 0)
+                       goto err;
+
+               i2s->playback_i2s_cif = cif_ids[0];
+               i2s->capture_i2s_cif = cif_ids[1];
+               i2s->id = i2s->playback_i2s_cif - TEGRA30_AHUB_RXCIF_I2S0_RX0;
+       } else {
+               i2s->id = pdev->id;
+               i2s->playback_i2s_cif = TEGRA30_AHUB_RXCIF_I2S0_RX0 + pdev->id;
+               i2s->capture_i2s_cif = TEGRA30_AHUB_TXCIF_I2S0_TX0 + pdev->id;
+       }
 
-       i2s->playback_i2s_cif = cif_ids[0];
-       i2s->capture_i2s_cif = cif_ids[1];
+       i2scont[i2s->id] = i2s;
 
        i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
        if (IS_ERR(i2s->clk_i2s)) {
@@ -1806,11 +1850,12 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
                ret = PTR_ERR(i2s->clk_i2s);
                goto err;
        }
+
        i2s->clk_i2s_sync = clk_get(&pdev->dev, "ext_audio_sync");
        if (IS_ERR(i2s->clk_i2s_sync)) {
                dev_err(&pdev->dev, "Can't retrieve i2s_sync clock\n");
                ret = PTR_ERR(i2s->clk_i2s_sync);
-               goto err_i2s_clk_put;
+               goto err_clk_put;
        }
 
        i2s->clk_audio_2x = clk_get(&pdev->dev, "audio_sync_2x");
@@ -1865,7 +1910,9 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
                        goto err_pm_disable;
        }
 
-       ret = snd_soc_register_dai(&pdev->dev, NULL);
+       ret = snd_soc_register_component(&pdev->dev, &tegra30_i2s_component,
+                                        &tegra30_i2s_dai_template, 1);
+
        if (ret) {
                dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
                ret = -ENOMEM;
@@ -1881,7 +1928,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
        return 0;
 
 err_unregister_dai:
-       snd_soc_unregister_dai(&pdev->dev);
+       snd_soc_unregister_component(&pdev->dev);
 err_suspend:
        if (!pm_runtime_status_suspended(&pdev->dev))
                tegra30_i2s_runtime_suspend(&pdev->dev);
@@ -1893,7 +1940,7 @@ err_audio_2x_clk_put:
        clk_put(i2s->clk_audio_2x);
 err_i2s_sync_clk_put:
        clk_put(i2s->clk_i2s_sync);
-err_i2s_clk_put:
+err_clk_put:
        clk_put(i2s->clk_i2s);
 err:
        return ret;
@@ -1908,7 +1955,7 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev)
                tegra30_i2s_runtime_suspend(&pdev->dev);
 
        tegra_pcm_platform_unregister(&pdev->dev);
-       snd_soc_unregister_dai(&pdev->dev);
+       snd_soc_unregister_component(&pdev->dev);
 
        clk_put(i2s->clk_pll_a_out0);
        clk_put(i2s->clk_audio_2x);
index cbe5747..126ee5d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra30_i2s.h - Definitions for Tegra30 I2S driver
  *
- * Copyright (c) 2010-2013, NVIDIA Corporation.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
 /* Fields in TEGRA30_I2S_SLOT_CTRL */
 
 /* Number of slots in frame, minus 1 */
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT                0
+#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK_US      0xf
+#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK         (TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK_US << TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT)
+#else
 #define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT                16
 #define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK_US      7
 #define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK         (TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK_US << TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT)
+#endif
 
 /* TDM mode slot enable bitmask */
 #define TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT    8
@@ -248,15 +254,25 @@ struct dsp_config_t {
        int tx_data_offset;
 };
 
+struct codec_config {
+       int i2s_id;
+       int rate;
+       int channels;
+       int bitsize;
+       int is_i2smaster;
+       int i2s_mode;
+       int bit_clk;
+};
 
 struct tegra30_i2s {
-       int id;
        struct snd_soc_dai_driver dai;
+       struct device *dev;
        int cif_id;
        struct clk *clk_i2s;
        struct clk *clk_i2s_sync;
        struct clk *clk_audio_2x;
        struct clk *clk_pll_a_out0;
+       int id;
        enum tegra30_ahub_txcif capture_i2s_cif;
        enum tegra30_ahub_rxcif capture_fifo_cif;
        struct tegra_pcm_dma_params capture_dma_data;
@@ -264,12 +280,11 @@ struct tegra30_i2s {
        enum tegra30_ahub_txcif playback_fifo_cif;
        struct tegra_pcm_dma_params playback_dma_data;
        struct regmap *regmap;
-       u32 reg_ch_ctrl;
+       int daifmt;
        int dam_ifc;
        int dam_ch_refcount;
        int  playback_ref_count;
        int  capture_ref_count;
-       int daifmt;
        bool is_dam_used;
 #ifdef CONFIG_PM
        #ifdef CONFIG_ARCH_TEGRA_3x_SOC
@@ -281,18 +296,8 @@ struct tegra30_i2s {
        int call_record_dam_ifc;
        int call_record_dam_ifc2;
        int is_call_mode_rec;
-
        struct dsp_config_t dsp_config;
-};
-
-struct codec_config {
-       int i2s_id;
-       int rate;
-       int channels;
-       int bitsize;
-       int is_i2smaster;
-       int i2s_mode;
-       int bit_clk;
+       int i2s_bit_clk;
 };
 
 int tegra30_make_voice_call_connections(struct codec_config *codec_info,
index 0abb9d6..393ea41 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <mach/iomap.h>
 #include <mach/hdmi-audio.h>
 #include <mach/clk.h>
 #include <sound/core.h>
@@ -62,10 +61,12 @@ static inline u32 tegra30_spdif_read(struct tegra30_spdif *spdif, u32 reg)
 static void tegra30_spdif_enable_clocks(struct tegra30_spdif *spdif)
 {
        clk_enable(spdif->clk_spdif_out);
+       tegra30_ahub_enable_clocks();
 }
 
 static void tegra30_spdif_disable_clocks(struct tegra30_spdif *spdif)
 {
+       tegra30_ahub_disable_clocks();
        clk_disable(spdif->clk_spdif_out);
 }
 
@@ -396,11 +397,15 @@ struct snd_soc_dai_driver tegra30_spdif_dai = {
        .ops = &tegra30_spdif_dai_ops,
 };
 
+static const struct snd_soc_component_driver tegra30_spdif_component = {
+       .name           = DRV_NAME,
+};
+
 static int tegra30_spdif_platform_probe(struct platform_device *pdev)
 {
        struct tegra30_spdif *spdif;
        struct resource *mem, *memregion;
-       int ret;
+       int ret = 0;
        u32 reg_val;
 
        spdif = kzalloc(sizeof(struct tegra30_spdif), GFP_KERNEL);
@@ -453,17 +458,26 @@ static int tegra30_spdif_platform_probe(struct platform_device *pdev)
 
        tegra30_spdif_disable_clocks(spdif);
 
-       ret = snd_soc_register_dai(&pdev->dev, &tegra30_spdif_dai);
+       ret = snd_soc_register_component(&pdev->dev, &tegra30_spdif_component,
+                                        &tegra30_spdif_dai, 1);
        if (ret) {
                dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
                ret = -ENOMEM;
                goto err_unmap;
        }
 
+       ret = tegra_pcm_platform_register(&pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
+               goto err_unregister_dai;
+       }
+
        tegra30_spdif_debug_add(spdif);
 
        return 0;
 
+err_unregister_dai:
+       snd_soc_unregister_component(&pdev->dev);
 err_unmap:
        iounmap(spdif->regs);
 err_release:
@@ -481,7 +495,7 @@ static int tegra30_spdif_platform_remove(struct platform_device *pdev)
        struct tegra30_spdif *spdif = dev_get_drvdata(&pdev->dev);
        struct resource *res;
 
-       snd_soc_unregister_dai(&pdev->dev);
+       snd_soc_unregister_component(&pdev->dev);
 
        tegra30_spdif_debug_remove(spdif);
 
index 30479f6..e67a94b 100644 (file)
@@ -46,6 +46,7 @@
 #endif
 
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include "tegra_pcm.h"
 #include "tegra_asoc_utils.h"
@@ -211,11 +212,11 @@ static int tegra_get_dma_ch_id(struct snd_kcontrol *kcontrol,
 
        rtd = &card->rtd[data->avp_device_id];
        substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+
        if (!substream || !substream->runtime)
                return 0;
 
-       prtd = (struct tegra_runtime_data *)
-               snd_dmaengine_pcm_get_data(substream);
+       prtd = substream->runtime->private_data;
 
        if (!prtd)
                return 0;
@@ -223,8 +224,7 @@ static int tegra_get_dma_ch_id(struct snd_kcontrol *kcontrol,
        chan = snd_dmaengine_pcm_get_chan(substream);
 
        ucontrol->value.integer.value[0] = -1;
-       ucontrol->value.integer.value[0] =
-               tegra_dma_get_channel_id(prtd->dma_chan);
+
        return 0;
 }
 
@@ -244,14 +244,10 @@ static int tegra_set_dma_addr(struct snd_kcontrol *kcontrol,
        substream =
        rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
 
-       rtd = &card->rtd[data->avp_device_id];
-       substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
        if (!substream || !substream->runtime)
                return 0;
 
-       prtd = (struct tegra_runtime_data *)
-               snd_dmaengine_pcm_get_data(substream);
-
+       prtd = substream->runtime->private_data;
        if (!prtd)
                return 0;
 
@@ -278,16 +274,15 @@ static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
        if (!substream || !substream->runtime)
                return 0;
 
-       prtd = (struct tegra_runtime_data *)
-               snd_dmaengine_pcm_get_data(substream);
+       prtd = substream->runtime->private_data;
 
        if (!prtd)
                return 0;
 
        ucontrol->value.integer.value[0] = 0;
        ucontrol->value.integer.value[0] = prtd->avp_dma_addr ?
-                                          prtd->avp_dma_addr :
-                                          substream->runtime->dma_addr;
+                                          (long)prtd->avp_dma_addr :
+                                          (long)substream->runtime->dma_addr;
 
        return 0;
 }
@@ -385,6 +380,7 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
                clk_disable_unprepare(data->clk_pll_a);
                reenable_clock = true;
        }
+
        err = clk_set_rate(data->clk_pll_a, new_baseclock);
        if (err) {
                dev_err(data->dev, "Can't set pll_a rate: %d\n", err);
@@ -406,7 +402,6 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
        if(reenable_clock)
                clk_prepare_enable(data->clk_pll_a_out0);
 
-
        data->set_baseclock = new_baseclock;
        data->set_mclk = mclk;
 
@@ -428,7 +423,7 @@ int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data)
 {
        int err;
 
-       err = clk_enable(data->clk_cdev1);
+       err = clk_prepare_enable(data->clk_cdev1);
        if (err) {
                dev_err(data->dev, "Can't enable cdev1: %d\n", err);
                return err;
@@ -440,7 +435,7 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_enable);
 
 int tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data)
 {
-       clk_disable(data->clk_cdev1);
+       clk_disable_unprepare(data->clk_cdev1);
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_disable);
@@ -480,24 +475,40 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
        data->dev = dev;
        data->card = card;
 
+       data->clk_pll_p_out1 = clk_get_sys(NULL, "pll_p_out1");
+       if (IS_ERR(data->clk_pll_p_out1)) {
+               dev_err(data->dev, "Can't retrieve clk pll_p_out1\n");
+               ret = PTR_ERR(data->clk_pll_p_out1);
+               goto err;
+       }
+
        if (of_machine_is_compatible("nvidia,tegra20"))
                data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
        else if (of_machine_is_compatible("nvidia,tegra30"))
                data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
-       else if (!dev->of_node)
+       else if (of_machine_is_compatible("nvidia,tegra114"))
+               data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA11x;
+       else if (of_machine_is_compatible("nvidia,tegra148"))
+               data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA14x;
+       else if (of_machine_is_compatible("nvidia,tegra124"))
+               data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA12x;
+       else if (!dev->of_node) {
                /* non-DT is always Tegra20 */
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
                data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
-       else
+#elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
+               data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
+#elif defined(CONFIG_ARCH_TEGRA_11x_SOC)
+               data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA11x;
+#elif defined(CONFIG_ARCH_TEGRA_14x_SOC)
+               data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA14x;
+#elif defined(CONFIG_ARCH_TEGRA_12x_SOC)
+               data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA12x;
+#endif
+       } else
                /* DT boot, but unknown SoC */
                return -EINVAL;
 
-       data->clk_pll_p_out1 = clk_get_sys(NULL, "pll_p_out1");
-       if (IS_ERR(data->clk_pll_p_out1)) {
-               dev_err(data->dev, "Can't retrieve clk pll_p_out1\n");
-               ret = PTR_ERR(data->clk_pll_p_out1);
-               goto err;
-       }
-
        data->clk_pll_a = clk_get_sys(NULL, "pll_a");
        if (IS_ERR(data->clk_pll_a)) {
                dev_err(data->dev, "Can't retrieve clk pll_a\n");
@@ -530,43 +541,41 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
                goto err_put_pll_a_out0;
        }
 
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
-       data->clk_out1 = ERR_PTR(-ENOENT);
-#else
-       data->clk_out1 = clk_get_sys("clk_out_1", "extern1");
-       if (IS_ERR(data->clk_out1)) {
-               dev_err(data->dev, "Can't retrieve clk out1\n");
-               ret = PTR_ERR(data->clk_out1);
-               goto err_put_cdev1;
+       if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
+               data->clk_out1 = ERR_PTR(-ENOENT);
+       else {
+               data->clk_out1 = clk_get_sys("clk_out_1", "extern1");
+               if (IS_ERR(data->clk_out1)) {
+                       dev_err(data->dev, "Can't retrieve clk out1\n");
+                       ret = PTR_ERR(data->clk_out1);
+                       goto err_put_cdev1;
+               }
        }
-#endif
 
-       ret = clk_enable(data->clk_cdev1);
+       ret = clk_prepare_enable(data->clk_cdev1);
        if (ret) {
                dev_err(data->dev, "Can't enable clk cdev1/extern1");
                goto err_put_out1;
        }
 
        if (!IS_ERR(data->clk_out1)) {
-               ret = clk_enable(data->clk_out1);
+               ret = clk_prepare_enable(data->clk_out1);
                if (ret) {
                        dev_err(data->dev, "Can't enable clk out1");
                        goto err_put_out1;
                }
        }
 
-       ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100);
+       ret = tegra_asoc_utils_set_rate(data, 48000, 256 * 48000);
        if (ret)
-               goto err_put_cdev1;
+               goto err_put_out1;
 
        return 0;
 
 err_put_out1:
        if (!IS_ERR(data->clk_out1))
                clk_put(data->clk_out1);
-#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
 err_put_cdev1:
-#endif
        clk_put(data->clk_cdev1);
 err_put_pll_a_out0:
        clk_put(data->clk_pll_a_out0);
@@ -579,12 +588,14 @@ err:
 }
 EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
 
-#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
 int tegra_asoc_utils_set_parent (struct tegra_asoc_utils_data *data,
                                int is_i2s_master)
 {
        int ret = -ENODEV;
 
+       if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
+               return ret;
+
        if (is_i2s_master) {
                ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0);
                if (ret) {
@@ -605,7 +616,6 @@ int tegra_asoc_utils_set_parent (struct tegra_asoc_utils_data *data,
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_parent);
-#endif
 
 void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
 {
index f59696b..346b01a 100644 (file)
@@ -2,8 +2,7 @@
  * tegra_asoc_utils.h - Definitions for Tegra DAS driver
  *
  * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (c) 2010-12, NVIDIA CORPORATION. All rights reserved.
- *
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * version 2 as published by the Free Software Foundation.
@@ -37,12 +36,15 @@ struct device;
 enum tegra_asoc_utils_soc {
        TEGRA_ASOC_UTILS_SOC_TEGRA20,
        TEGRA_ASOC_UTILS_SOC_TEGRA30,
+       TEGRA_ASOC_UTILS_SOC_TEGRA11x,
+       TEGRA_ASOC_UTILS_SOC_TEGRA14x,
+       TEGRA_ASOC_UTILS_SOC_TEGRA12x,
 };
 
 struct tegra_asoc_utils_data {
        struct device *dev;
-       enum tegra_asoc_utils_soc soc;
        struct snd_soc_card *card;
+       enum tegra_asoc_utils_soc soc;
        struct clk *clk_pll_a;
        struct clk *clk_pll_a_out0;
        struct clk *clk_cdev1;
@@ -53,8 +55,8 @@ struct tegra_asoc_utils_data {
        int set_mclk;
        int lock_count;
        int avp_device_id;
-       unsigned int avp_dma_addr;
        int headset_plug_state;
+       dma_addr_t avp_dma_addr;
 };
 
 int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
index 2b335a7..ada00e1 100644 (file)
@@ -2,13 +2,14 @@
  * tegra_pcm.c - Tegra PCM driver
  *
  * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010,2012 - NVIDIA, Inc.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * Based on code copyright/by:
  *
- * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Copyright (c) 2009-2013, NVIDIA CORPORATION.  All rights reserved.
  * Scott Peterson <speterson@nvidia.com>
  * Vijay Mali <vmali@nvidia.com>
+ * Manoj Gangwal <mgangwal@nvidia.com>
  *
  * Copyright (C) 2010 Google, Inc.
  * Iliyan Malchev <malchev@google.com>
@@ -66,16 +67,24 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct device *dev = rtd->platform->dev;
+       struct tegra_runtime_data *prtd;
        int ret;
 
+       prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL);
+       if (prtd == NULL)
+               return -ENOMEM;
+
        /* Set HW params now that initialization is complete */
        snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
 
        /* Ensure period size is multiple of 8 */
        ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
                SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x8);
-       if (ret < 0)
-               goto err;
+       if (ret) {
+               dev_err(dev, "failed to set constraint %d\n", ret);
+               kfree(prtd);
+               return ret;
+       }
 
        ret = snd_dmaengine_pcm_open_request_chan(substream, NULL, NULL);
        if (ret) {
@@ -93,7 +102,7 @@ static int tegra_pcm_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
+int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -133,18 +142,19 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
+int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
 {
        snd_pcm_set_runtime_buffer(substream, NULL);
        return 0;
 }
 
-static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct tegra_pcm_dma_params * dmap;a
+       struct tegra_pcm_dma_params * dmap;
 
        dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
        if (!dmap)
                return 0;
 
@@ -152,12 +162,14 @@ static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+
                return snd_dmaengine_pcm_trigger(substream,
                                        SNDRV_PCM_TRIGGER_START);
 
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+
                return snd_dmaengine_pcm_trigger(substream,
                                        SNDRV_PCM_TRIGGER_STOP);
        default:
@@ -188,12 +200,11 @@ static struct snd_pcm_ops tegra_pcm_ops = {
        .mmap           = tegra_pcm_mmap,
 };
 
-static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
+                               int stream , size_t size)
 {
        struct snd_pcm_substream *substream = pcm->streams[stream].substream;
        struct snd_dma_buffer *buf = &substream->dma_buffer;
-       size_t size = tegra_pcm_hardware.buffer_bytes_max;
-
 #if TEGRA30_USE_SMMU
        unsigned char *vaddr;
        phys_addr_t paddr;
@@ -226,7 +237,7 @@ static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
        return 0;
 }
 
-static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 {
        struct snd_pcm_substream *substream;
        struct snd_dma_buffer *buf;
@@ -260,7 +271,7 @@ static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 
 static u64 tegra_dma_mask = DMA_BIT_MASK(32);
 
-static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
+int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd, size_t size)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
@@ -273,14 +284,16 @@ static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = tegra_pcm_preallocate_dma_buffer(pcm,
-                                               SNDRV_PCM_STREAM_PLAYBACK);
+                                               SNDRV_PCM_STREAM_PLAYBACK,
+                                               size);
                if (ret)
                        goto err;
        }
 
        if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
                ret = tegra_pcm_preallocate_dma_buffer(pcm,
-                                               SNDRV_PCM_STREAM_CAPTURE);
+                                               SNDRV_PCM_STREAM_CAPTURE,
+                                               size);
                if (ret)
                        goto err_free_play;
        }
@@ -293,7 +306,13 @@ err:
        return ret;
 }
 
-static void tegra_pcm_free(struct snd_pcm *pcm)
+int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+       return tegra_pcm_dma_allocate(rtd ,
+                                       tegra_pcm_hardware.buffer_bytes_max);
+}
+
+void tegra_pcm_free(struct snd_pcm *pcm)
 {
        tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
        tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
index c7020c9..3dfc08e 100644 (file)
@@ -2,11 +2,11 @@
  * tegra_pcm.h - Definitions for Tegra PCM driver
  *
  * Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010,2012 - NVIDIA, Inc.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * Based on code copyright/by:
  *
- * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Copyright (c) 2009-2010, NVIDIA CORPORATION.  All rights reserved.
  * Scott Peterson <speterson@nvidia.com>
  *
  * Copyright (C) 2010 Google, Inc.
@@ -33,6 +33,8 @@
 
 #include <linux/nvmap.h>
 
+#define MAX_DMA_REQ_COUNT 2
+
 #define TEGRA30_USE_SMMU 0
 
 struct tegra_pcm_dma_params {
@@ -49,6 +51,12 @@ struct tegra_smmu_data {
 };
 #endif
 
+struct tegra_runtime_data {
+       int running;
+       int disable_intr;
+       dma_addr_t avp_dma_addr;
+};
+
 int tegra_pcm_platform_register(struct device *dev);
 void tegra_pcm_platform_unregister(struct device *dev);
 
index d569f26..1e30a94 100644 (file)
@@ -500,10 +500,11 @@ static int tegra_rt5639_event_int_spk(struct snd_soc_dapm_widget *w,
        struct snd_soc_card *card = dapm->card;
        struct tegra_rt5639 *machine = snd_soc_card_get_drvdata(card);
        struct tegra_asoc_platform_data *pdata = machine->pdata;
+       int ret = 0;
 
        if (machine->spk_reg) {
                if (SND_SOC_DAPM_EVENT_ON(event))
-                       regulator_enable(machine->spk_reg);
+                       ret = regulator_enable(machine->spk_reg);
                else
                        regulator_disable(machine->spk_reg);
        }
@@ -541,10 +542,11 @@ static int tegra_rt5639_event_int_mic(struct snd_soc_dapm_widget *w,
        struct snd_soc_card *card = dapm->card;
        struct tegra_rt5639 *machine = snd_soc_card_get_drvdata(card);
        struct tegra_asoc_platform_data *pdata = machine->pdata;
+    int ret = 0;
 
        if (machine->dmic_reg) {
                if (SND_SOC_DAPM_EVENT_ON(event))
-                       regulator_enable(machine->dmic_reg);
+                       ret = regulator_enable(machine->dmic_reg);
                else
                        regulator_disable(machine->dmic_reg);
        }
@@ -906,7 +908,7 @@ static int tegra_rt5639_driver_probe(struct platform_device *pdev)
                if (IS_ERR(machine->codec_reg))
                        machine->codec_reg = 0;
                else
-                       regulator_enable(machine->codec_reg);
+                       ret = regulator_enable(machine->codec_reg);
        }
 
        /*
@@ -917,7 +919,7 @@ static int tegra_rt5639_driver_probe(struct platform_device *pdev)
        if (IS_ERR(machine->digital_reg))
                machine->digital_reg = 0;
        else
-               regulator_enable(machine->digital_reg);
+               ret = regulator_enable(machine->digital_reg);
 
        /*
        *analog_reg - provided the analog power for the codec and must be
@@ -927,7 +929,7 @@ static int tegra_rt5639_driver_probe(struct platform_device *pdev)
        if (IS_ERR(machine->analog_reg))
                machine->analog_reg = 0;
        else
-               regulator_enable(machine->analog_reg);
+               ret = regulator_enable(machine->analog_reg);
 
        /*
        *spk_reg - provided the speaker power and can be turned ON
index 2c14396..e40067a 100644 (file)
@@ -40,6 +40,7 @@
 #ifdef CONFIG_SWITCH
 #include <linux/switch.h>
 #endif
+#include <linux/pm_runtime.h>
 #include <mach/tegra_asoc_pdata.h>
 #include <mach/gpio-tegra.h>
 #include <mach/tegra_rt5640_pdata.h>
@@ -521,7 +522,7 @@ static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w,
 
        if (machine->spk_reg) {
                if (SND_SOC_DAPM_EVENT_ON(event)) {
-                       regulator_enable(machine->spk_reg);
+                       ret =regulator_enable(machine->spk_reg);
                }
                else {
                        regulator_disable(machine->spk_reg);
@@ -604,10 +605,11 @@ static int tegra_rt5640_event_int_mic(struct snd_soc_dapm_widget *w,
        struct snd_soc_card *card = dapm->card;
        struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
        struct tegra_asoc_platform_data *pdata = machine->pdata;
+       int ret =0;
 
        if (machine->dmic_reg) {
                if (SND_SOC_DAPM_EVENT_ON(event))
-                       regulator_enable(machine->dmic_reg);
+                       ret=regulator_enable(machine->dmic_reg);
                else
                        regulator_disable(machine->dmic_reg);
        }
@@ -872,14 +874,18 @@ void tegra_asoc_enable_clocks()
 {
        struct snd_soc_card *card = &snd_soc_tegra_rt5640;
        struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
-       int reg;
+       unsigned int reg;
+       unsigned int reg_ctrl;
        struct tegra30_i2s *i2s = i2s_tfa;
        if (!i2s || !machine)
                return;
 
-       reg = i2s->reg_ctrl | TEGRA30_I2S_CTRL_XFER_EN_TX;
-       if (!(i2s->reg_ctrl & TEGRA30_I2S_CTRL_XFER_EN_TX)) {
+       regmap_read(i2s->regmap, TEGRA30_I2S_CTRL, &reg_ctrl);
+       reg = reg_ctrl | TEGRA30_I2S_CTRL_XFER_EN_TX;
+       if (!(reg_ctrl & TEGRA30_I2S_CTRL_XFER_EN_TX)) {
                tegra_asoc_utils_clk_enable(&machine->util_data);
+               pm_runtime_get_sync(i2s->dev);
+               tegra30_ahub_enable_clocks();
                tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif);
                regmap_write(i2s->regmap, TEGRA30_I2S_CTRL, reg);
        }
@@ -890,17 +896,21 @@ void tegra_asoc_disable_clocks()
 {
        struct snd_soc_card *card = &snd_soc_tegra_rt5640;
        struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
+       unsigned int reg_ctrl;
        int dcnt = 10;
        struct tegra30_i2s *i2s = i2s_tfa;
        if (!i2s || !machine)
                return;
 
-       if (!(i2s->reg_ctrl & TEGRA30_I2S_CTRL_XFER_EN_TX)) {
-               regmap_write(i2s->regmap, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
+       regmap_read(i2s->regmap, TEGRA30_I2S_CTRL, &reg_ctrl);
+       if (!(reg_ctrl & TEGRA30_I2S_CTRL_XFER_EN_TX)) {
+               regmap_write(i2s->regmap, TEGRA30_I2S_CTRL, reg_ctrl);
                while (!tegra30_ahub_tx_fifo_is_empty(i2s->id) && dcnt--)
                        udelay(100);
 
                tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif);
+               tegra30_ahub_disable_clocks();
+               pm_runtime_put(i2s->dev);
                tegra_asoc_utils_clk_disable(&machine->util_data);
        }
 }
@@ -1008,7 +1018,7 @@ static int tegra_rt5640_driver_probe(struct platform_device *pdev)
                                        PTR_ERR(machine->cdc_en));
                        machine->cdc_en = 0;
                } else {
-                       regulator_enable(machine->cdc_en);
+                       ret = regulator_enable(machine->cdc_en);
                }
        }