Merge remote-tracking branches 'asoc/topic/adsp', 'asoc/topic/atmel', 'asoc/topic...
authorMark Brown <broonie@linaro.org>
Thu, 16 Jan 2014 12:44:01 +0000 (12:44 +0000)
committerMark Brown <broonie@linaro.org>
Thu, 16 Jan 2014 12:44:01 +0000 (12:44 +0000)
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19 
sound/soc/codecs/ad1836.c
sound/soc/codecs/ad193x.c
sound/soc/codecs/adau1701.c
sound/soc/codecs/adav80x.c
sound/soc/codecs/arizona.h
sound/soc/codecs/da7210.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/Kconfig
sound/soc/fsl/fsl_ssi.c
sound/soc/generic/simple-card.c
sound/soc/sh/fsi.c

@@@@@@@@@@@@@@@@@@@@ -168,19 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 +168,19 @@@@@@@@@@@@@@@@@@@@ static int ad1836_hw_params(struct snd_
                        int word_len = 0;
                   
                        /* bit size */
----------------- -     switch (params_format(params)) {
----------------- -     case SNDRV_PCM_FORMAT_S16_LE:
+++++++++++++++++ +     switch (params_width(params)) {
+++++++++++++++++ +     case 16:
                                word_len = AD1836_WORD_LEN_16;
                                break;
----------------- -     case SNDRV_PCM_FORMAT_S20_3LE:
+++++++++++++++++ +     case 20:
                                word_len = AD1836_WORD_LEN_20;
                                break;
----------------- -     case SNDRV_PCM_FORMAT_S24_LE:
----------------- -     case SNDRV_PCM_FORMAT_S32_LE:
+++++++++++++++++ +     case 24:
+++++++++++++++++ +     case 32:
                                word_len = AD1836_WORD_LEN_24;
                                break;
 ++++++++++++++++++     default:
 ++++++++++++++++++             return -EINVAL;
                        }
                   
                        regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1,
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
                        return 0;
                   }
                   
- -----------------int wm_adsp2_event(struct snd_soc_dapm_widget *w,
- -----------------                struct snd_kcontrol *kcontrol, int event)
+ +++++++++++++++++static void wm_adsp2_boot_work(struct work_struct *work)
                   {
- -----------------     struct snd_soc_codec *codec = w->codec;
- -----------------     struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
- -----------------     struct wm_adsp *dsp = &dsps[w->shift];
- -----------------     struct wm_adsp_alg_region *alg_region;
- -----------------     struct wm_coeff_ctl *ctl;
- -----------------     unsigned int val;
+ +++++++++++++++++     struct wm_adsp *dsp = container_of(work,
+ +++++++++++++++++                                        struct wm_adsp,
+ +++++++++++++++++                                        boot_work);
                        int ret;
+ +++++++++++++++++     unsigned int val;
                   
- -----------------     dsp->card = codec->card;
+ +++++++++++++++++     /*
+ +++++++++++++++++      * For simplicity set the DSP clock rate to be the
+ +++++++++++++++++      * SYSCLK rate rather than making it configurable.
+ +++++++++++++++++      */
+ +++++++++++++++++     ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
+ +++++++++++++++++     if (ret != 0) {
+ +++++++++++++++++             adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
+ +++++++++++++++++             return;
+ +++++++++++++++++     }
+ +++++++++++++++++     val = (val & ARIZONA_SYSCLK_FREQ_MASK)
+ +++++++++++++++++             >> ARIZONA_SYSCLK_FREQ_SHIFT;
                   
- -----------------     switch (event) {
- -----------------     case SND_SOC_DAPM_POST_PMU:
- -----------------             /*
- -----------------              * For simplicity set the DSP clock rate to be the
- -----------------              * SYSCLK rate rather than making it configurable.
- -----------------              */
- -----------------             ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
- -----------------             if (ret != 0) {
- -----------------                     adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
- -----------------                              ret);
- -----------------                     return ret;
- -----------------             }
- -----------------             val = (val & ARIZONA_SYSCLK_FREQ_MASK)
- -----------------                     >> ARIZONA_SYSCLK_FREQ_SHIFT;
+ +++++++++++++++++     ret = regmap_update_bits_async(dsp->regmap,
+ +++++++++++++++++                                    dsp->base + ADSP2_CLOCKING,
+ +++++++++++++++++                                    ADSP2_CLK_SEL_MASK, val);
+ +++++++++++++++++     if (ret != 0) {
+ +++++++++++++++++             adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
+ +++++++++++++++++             return;
+ +++++++++++++++++     }
                   
-                               ret = regmap_update_bits_async(dsp->regmap,
-                                                              dsp->base + ADSP2_CLOCKING,
-                                                              ADSP2_CLK_SEL_MASK, val);
  -----------------             ret = regmap_update_bits(dsp->regmap,
  -----------------                                      dsp->base + ADSP2_CLOCKING,
  -----------------                                      ADSP2_CLK_SEL_MASK, val);
+ +++++++++++++++++     if (dsp->dvfs) {
+ +++++++++++++++++             ret = regmap_read(dsp->regmap,
+ +++++++++++++++++                               dsp->base + ADSP2_CLOCKING, &val);
                                if (ret != 0) {
- -----------------                     adsp_err(dsp, "Failed to set clock rate: %d\n",
- -----------------                              ret);
- -----------------                     return ret;
+ +++++++++++++++++                     dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
+ +++++++++++++++++                     return;
                                }
                   
- -----------------             if (dsp->dvfs) {
- -----------------                     ret = regmap_read(dsp->regmap,
- -----------------                                       dsp->base + ADSP2_CLOCKING, &val);
+ +++++++++++++++++             if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
+ +++++++++++++++++                     ret = regulator_enable(dsp->dvfs);
                                        if (ret != 0) {
                                                dev_err(dsp->dev,
- -----------------                                     "Failed to read clocking: %d\n", ret);
- -----------------                             return ret;
+ +++++++++++++++++                                     "Failed to enable supply: %d\n",
+ +++++++++++++++++                                     ret);
+ +++++++++++++++++                             return;
                                        }
                   
- -----------------                     if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
- -----------------                             ret = regulator_enable(dsp->dvfs);
- -----------------                             if (ret != 0) {
- -----------------                                     dev_err(dsp->dev,
- -----------------                                             "Failed to enable supply: %d\n",
- -----------------                                             ret);
- -----------------                                     return ret;
- -----------------                             }
- -----------------
- -----------------                             ret = regulator_set_voltage(dsp->dvfs,
- -----------------                                                         1800000,
- -----------------                                                         1800000);
- -----------------                             if (ret != 0) {
- -----------------                                     dev_err(dsp->dev,
- -----------------                                             "Failed to raise supply: %d\n",
- -----------------                                             ret);
- -----------------                                     return ret;
- -----------------                             }
+ +++++++++++++++++                     ret = regulator_set_voltage(dsp->dvfs,
+ +++++++++++++++++                                                 1800000,
+ +++++++++++++++++                                                 1800000);
+ +++++++++++++++++                     if (ret != 0) {
+ +++++++++++++++++                             dev_err(dsp->dev,
+ +++++++++++++++++                                     "Failed to raise supply: %d\n",
+ +++++++++++++++++                                     ret);
+ +++++++++++++++++                             return;
                                        }
                                }
+ +++++++++++++++++     }
                   
- -----------------             ret = wm_adsp2_ena(dsp);
- -----------------             if (ret != 0)
- -----------------                     return ret;
+ +++++++++++++++++     ret = wm_adsp2_ena(dsp);
+ +++++++++++++++++     if (ret != 0)
+ +++++++++++++++++             return;
                   
- -----------------             ret = wm_adsp_load(dsp);
- -----------------             if (ret != 0)
- -----------------                     goto err;
+ +++++++++++++++++     ret = wm_adsp_load(dsp);
+ +++++++++++++++++     if (ret != 0)
+ +++++++++++++++++             goto err;
                   
- -----------------             ret = wm_adsp_setup_algs(dsp);
- -----------------             if (ret != 0)
- -----------------                     goto err;
+ +++++++++++++++++     ret = wm_adsp_setup_algs(dsp);
+ +++++++++++++++++     if (ret != 0)
+ +++++++++++++++++             goto err;
                   
- -----------------             ret = wm_adsp_load_coeff(dsp);
- -----------------             if (ret != 0)
- -----------------                     goto err;
+ +++++++++++++++++     ret = wm_adsp_load_coeff(dsp);
+ +++++++++++++++++     if (ret != 0)
+ +++++++++++++++++             goto err;
                   
- -----------------             /* Initialize caches for enabled and unset controls */
- -----------------             ret = wm_coeff_init_control_caches(dsp);
- -----------------             if (ret != 0)
- -----------------                     goto err;
+ +++++++++++++++++     /* Initialize caches for enabled and unset controls */
+ +++++++++++++++++     ret = wm_coeff_init_control_caches(dsp);
+ +++++++++++++++++     if (ret != 0)
+ +++++++++++++++++             goto err;
                   
- -----------------             /* Sync set controls */
- -----------------             ret = wm_coeff_sync_controls(dsp);
- -----------------             if (ret != 0)
- -----------------                     goto err;
+ +++++++++++++++++     /* Sync set controls */
+ +++++++++++++++++     ret = wm_coeff_sync_controls(dsp);
+ +++++++++++++++++     if (ret != 0)
+ +++++++++++++++++             goto err;
+ +++++++++++++++++
+ +++++++++++++++++     ret = regmap_update_bits_async(dsp->regmap,
+ +++++++++++++++++                                    dsp->base + ADSP2_CONTROL,
+ +++++++++++++++++                                    ADSP2_CORE_ENA,
+ +++++++++++++++++                                    ADSP2_CORE_ENA);
+ +++++++++++++++++     if (ret != 0)
+ +++++++++++++++++             goto err;
+ +++++++++++++++++
+ +++++++++++++++++     dsp->running = true;
+ +++++++++++++++++
+ +++++++++++++++++     return;
+ +++++++++++++++++
+ +++++++++++++++++err:
+ +++++++++++++++++     regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+ +++++++++++++++++                        ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+ +++++++++++++++++}
+ +++++++++++++++++
+ +++++++++++++++++int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
+ +++++++++++++++++                struct snd_kcontrol *kcontrol, int event)
+ +++++++++++++++++{
+ +++++++++++++++++     struct snd_soc_codec *codec = w->codec;
+ +++++++++++++++++     struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+ +++++++++++++++++     struct wm_adsp *dsp = &dsps[w->shift];
+ +++++++++++++++++
+ +++++++++++++++++     dsp->card = codec->card;
+ +++++++++++++++++
+ +++++++++++++++++     switch (event) {
+ +++++++++++++++++     case SND_SOC_DAPM_PRE_PMU:
+ +++++++++++++++++             queue_work(system_unbound_wq, &dsp->boot_work);
+ +++++++++++++++++             break;
+ +++++++++++++++++     default:
+ +++++++++++++++++             break;
+ +++++++++++++++++     };
+ +++++++++++++++++
+ +++++++++++++++++     return 0;
+ +++++++++++++++++}
+ +++++++++++++++++EXPORT_SYMBOL_GPL(wm_adsp2_early_event);
+ +++++++++++++++++
+ +++++++++++++++++int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+ +++++++++++++++++                struct snd_kcontrol *kcontrol, int event)
+ +++++++++++++++++{
+ +++++++++++++++++     struct snd_soc_codec *codec = w->codec;
+ +++++++++++++++++     struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+ +++++++++++++++++     struct wm_adsp *dsp = &dsps[w->shift];
+ +++++++++++++++++     struct wm_adsp_alg_region *alg_region;
+ +++++++++++++++++     struct wm_coeff_ctl *ctl;
+ +++++++++++++++++     int ret;
+ +++++++++++++++++
+ +++++++++++++++++     switch (event) {
+ +++++++++++++++++     case SND_SOC_DAPM_POST_PMU:
+ +++++++++++++++++             flush_work(&dsp->boot_work);
+ +++++++++++++++++
+ +++++++++++++++++             if (!dsp->running)
+ +++++++++++++++++                     return -EIO;
                   
-                               ret = regmap_update_bits_async(dsp->regmap,
-                                                              dsp->base + ADSP2_CONTROL,
-                                                              ADSP2_CORE_ENA | ADSP2_START,
-                                                              ADSP2_CORE_ENA | ADSP2_START);
+                               ret = regmap_update_bits(dsp->regmap,
+                                                        dsp->base + ADSP2_CONTROL,
  -----------------                                      ADSP2_CORE_ENA | ADSP2_START,
  -----------------                                      ADSP2_CORE_ENA | ADSP2_START);
+ +++++++++++++++++                                      ADSP2_START,
+ +++++++++++++++++                                      ADSP2_START);
                                if (ret != 0)
                                        goto err;
- -----------------
- -----------------             dsp->running = true;
                                break;
                   
                        case SND_SOC_DAPM_PRE_PMD:
Simple merge
                        struct ccsr_ssi __iomem *ssi;
                        dma_addr_t ssi_phys;
                        unsigned int irq;
 ---- -------------     struct snd_pcm_substream *first_stream;
 ---- -------------     struct snd_pcm_substream *second_stream;
                        unsigned int fifo_depth;
                        struct snd_soc_dai_driver cpu_dai_drv;
----- -------------     struct device_attribute dev_attr;
                        struct platform_device *pdev;
                   
+++++ +++++++++++++     enum fsl_ssi_type hw_type;
                        bool new_binding;
                        bool ssi_on_imx;
                        bool imx_ac97;
                        bool use_dma;
 ++++ +++++++++++++     bool baudclk_locked;
+++++ +++++++++++++     bool irq_stats;
+++++ +++++++++++++     bool offline_config;
 ++++ +++++++++++++     u8 i2s_mode;
 ++++ +++++++++++++     spinlock_t baudclk_lock;
 ++++ +++++++++++++     struct clk *baudclk;
                        struct clk *clk;
                        struct snd_dmaengine_dai_dma_data dma_params_tx;
                        struct snd_dmaengine_dai_dma_data dma_params_rx;
@@@@@@@@@@@@@@@@@@@@ -321,46 -321,17 -321,17 -321,17 -321,17 -373,287 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 +372,287 @@@@@@@@@@@@@@@@@@@@ static irqreturn_t fsl_ssi_isr(int irq
                        return ret;
                   }
                   
+++++ +++++++++++++#if IS_ENABLED(CONFIG_DEBUG_FS)
+++++ +++++++++++++/* Show the statistics of a flag only if its interrupt is enabled.  The
+++++ +++++++++++++ * compiler will optimze this code to a no-op if the interrupt is not
+++++ +++++++++++++ * enabled.
+++++ +++++++++++++ */
+++++ +++++++++++++#define SIER_SHOW(flag, name) \
+++++ +++++++++++++     do { \
+++++ +++++++++++++             if (FSLSSI_SISR_MASK & CCSR_SSI_SIER_##flag) \
+++++ +++++++++++++                     seq_printf(s, #name "=%u\n", ssi_private->stats.name); \
+++++ +++++++++++++     } while (0)
+++++ +++++++++++++
+++++ +++++++++++++
+++++ +++++++++++++/**
+++++ +++++++++++++ * fsl_sysfs_ssi_show: display SSI statistics
+++++ +++++++++++++ *
+++++ +++++++++++++ * Display the statistics for the current SSI device.  To avoid confusion,
+++++ +++++++++++++ * we only show those counts that are enabled.
+++++ +++++++++++++ */
+++++ +++++++++++++static int fsl_ssi_stats_show(struct seq_file *s, void *unused)
+++++ +++++++++++++{
+++++ +++++++++++++     struct fsl_ssi_private *ssi_private = s->private;
+++++ +++++++++++++
+++++ +++++++++++++     SIER_SHOW(RFRC_EN, rfrc);
+++++ +++++++++++++     SIER_SHOW(TFRC_EN, tfrc);
+++++ +++++++++++++     SIER_SHOW(CMDAU_EN, cmdau);
+++++ +++++++++++++     SIER_SHOW(CMDDU_EN, cmddu);
+++++ +++++++++++++     SIER_SHOW(RXT_EN, rxt);
+++++ +++++++++++++     SIER_SHOW(RDR1_EN, rdr1);
+++++ +++++++++++++     SIER_SHOW(RDR0_EN, rdr0);
+++++ +++++++++++++     SIER_SHOW(TDE1_EN, tde1);
+++++ +++++++++++++     SIER_SHOW(TDE0_EN, tde0);
+++++ +++++++++++++     SIER_SHOW(ROE1_EN, roe1);
+++++ +++++++++++++     SIER_SHOW(ROE0_EN, roe0);
+++++ +++++++++++++     SIER_SHOW(TUE1_EN, tue1);
+++++ +++++++++++++     SIER_SHOW(TUE0_EN, tue0);
+++++ +++++++++++++     SIER_SHOW(TFS_EN, tfs);
+++++ +++++++++++++     SIER_SHOW(RFS_EN, rfs);
+++++ +++++++++++++     SIER_SHOW(TLS_EN, tls);
+++++ +++++++++++++     SIER_SHOW(RLS_EN, rls);
+++++ +++++++++++++     SIER_SHOW(RFF1_EN, rff1);
+++++ +++++++++++++     SIER_SHOW(RFF0_EN, rff0);
+++++ +++++++++++++     SIER_SHOW(TFE1_EN, tfe1);
+++++ +++++++++++++     SIER_SHOW(TFE0_EN, tfe0);
+++++ +++++++++++++
+++++ +++++++++++++     return 0;
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++static int fsl_ssi_stats_open(struct inode *inode, struct file *file)
+++++ +++++++++++++{
+++++ +++++++++++++     return single_open(file, fsl_ssi_stats_show, inode->i_private);
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++static const struct file_operations fsl_ssi_stats_ops = {
+++++ +++++++++++++     .open = fsl_ssi_stats_open,
+++++ +++++++++++++     .read = seq_read,
+++++ +++++++++++++     .llseek = seq_lseek,
+++++ +++++++++++++     .release = single_release,
+++++ +++++++++++++};
+++++ +++++++++++++
+++++ +++++++++++++static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private,
+++++ +++++++++++++             struct device *dev)
+++++ +++++++++++++{
+++++ +++++++++++++     ssi_private->dbg_dir = debugfs_create_dir(dev_name(dev), NULL);
+++++ +++++++++++++     if (!ssi_private->dbg_dir)
+++++ +++++++++++++             return -ENOMEM;
+++++ +++++++++++++
+++++ +++++++++++++     ssi_private->dbg_stats = debugfs_create_file("stats", S_IRUGO,
+++++ +++++++++++++                     ssi_private->dbg_dir, ssi_private, &fsl_ssi_stats_ops);
+++++ +++++++++++++     if (!ssi_private->dbg_stats) {
+++++ +++++++++++++             debugfs_remove(ssi_private->dbg_dir);
+++++ +++++++++++++             return -ENOMEM;
+++++ +++++++++++++     }
+++++ +++++++++++++
+++++ +++++++++++++     return 0;
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private)
+++++ +++++++++++++{
+++++ +++++++++++++     debugfs_remove(ssi_private->dbg_stats);
+++++ +++++++++++++     debugfs_remove(ssi_private->dbg_dir);
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++#else
+++++ +++++++++++++
+++++ +++++++++++++static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private,
+++++ +++++++++++++             struct device *dev)
+++++ +++++++++++++{
+++++ +++++++++++++     return 0;
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private)
+++++ +++++++++++++{
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
+++++ +++++++++++++
+++++ +++++++++++++/*
+++++ +++++++++++++ * Enable/Disable all rx/tx config flags at once.
+++++ +++++++++++++ */
+++++ +++++++++++++static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
+++++ +++++++++++++             bool enable)
+++++ +++++++++++++{
+++++ +++++++++++++     struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+++++ +++++++++++++     struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val;
+++++ +++++++++++++
+++++ +++++++++++++     if (enable) {
+++++ +++++++++++++             write_ssi_mask(&ssi->sier, 0, vals->rx.sier | vals->tx.sier);
+++++ +++++++++++++             write_ssi_mask(&ssi->srcr, 0, vals->rx.srcr | vals->tx.srcr);
+++++ +++++++++++++             write_ssi_mask(&ssi->stcr, 0, vals->rx.stcr | vals->tx.stcr);
+++++ +++++++++++++     } else {
+++++ +++++++++++++             write_ssi_mask(&ssi->srcr, vals->rx.srcr | vals->tx.srcr, 0);
+++++ +++++++++++++             write_ssi_mask(&ssi->stcr, vals->rx.stcr | vals->tx.stcr, 0);
+++++ +++++++++++++             write_ssi_mask(&ssi->sier, vals->rx.sier | vals->tx.sier, 0);
+++++ +++++++++++++     }
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++/*
+++++ +++++++++++++ * Enable/Disable a ssi configuration. You have to pass either
+++++ +++++++++++++ * ssi_private->rxtx_reg_val.rx or tx as vals parameter.
+++++ +++++++++++++ */
+++++ +++++++++++++static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
+++++ +++++++++++++             struct fsl_ssi_reg_val *vals)
+++++ +++++++++++++{
+++++ +++++++++++++     struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+++++ +++++++++++++     struct fsl_ssi_reg_val *avals;
+++++ +++++++++++++     u32 scr_val = read_ssi(&ssi->scr);
+++++ +++++++++++++     int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) +
+++++ +++++++++++++                             !!(scr_val & CCSR_SSI_SCR_RE);
+++++ +++++++++++++
+++++ +++++++++++++     /* Find the other direction values rx or tx which we do not want to
+++++ +++++++++++++      * modify */
+++++ +++++++++++++     if (&ssi_private->rxtx_reg_val.rx == vals)
+++++ +++++++++++++             avals = &ssi_private->rxtx_reg_val.tx;
+++++ +++++++++++++     else
+++++ +++++++++++++             avals = &ssi_private->rxtx_reg_val.rx;
+++++ +++++++++++++
+++++ +++++++++++++     /* If vals should be disabled, start with disabling the unit */
+++++ +++++++++++++     if (!enable) {
+++++ +++++++++++++             u32 scr = vals->scr & (vals->scr ^ avals->scr);
+++++ +++++++++++++             write_ssi_mask(&ssi->scr, scr, 0);
+++++ +++++++++++++     }
+++++ +++++++++++++
+++++ +++++++++++++     /*
+++++ +++++++++++++      * We are running on a SoC which does not support online SSI
+++++ +++++++++++++      * reconfiguration, so we have to enable all necessary flags at once
+++++ +++++++++++++      * even if we do not use them later (capture and playback configuration)
+++++ +++++++++++++      */
+++++ +++++++++++++     if (ssi_private->offline_config) {
+++++ +++++++++++++             if ((enable && !nr_active_streams) ||
+++++ +++++++++++++                             (!enable && nr_active_streams == 1))
+++++ +++++++++++++                     fsl_ssi_rxtx_config(ssi_private, enable);
+++++ +++++++++++++
+++++ +++++++++++++             goto config_done;
+++++ +++++++++++++     }
+++++ +++++++++++++
+++++ +++++++++++++     /*
+++++ +++++++++++++      * Configure single direction units while the SSI unit is running
+++++ +++++++++++++      * (online configuration)
+++++ +++++++++++++      */
+++++ +++++++++++++     if (enable) {
+++++ +++++++++++++             write_ssi_mask(&ssi->sier, 0, vals->sier);
+++++ +++++++++++++             write_ssi_mask(&ssi->srcr, 0, vals->srcr);
+++++ +++++++++++++             write_ssi_mask(&ssi->stcr, 0, vals->stcr);
+++++ +++++++++++++     } else {
+++++ +++++++++++++             u32 sier;
+++++ +++++++++++++             u32 srcr;
+++++ +++++++++++++             u32 stcr;
+++++ +++++++++++++
+++++ +++++++++++++             /*
+++++ +++++++++++++              * Disabling the necessary flags for one of rx/tx while the
+++++ +++++++++++++              * other stream is active is a little bit more difficult. We
+++++ +++++++++++++              * have to disable only those flags that differ between both
+++++ +++++++++++++              * streams (rx XOR tx) and that are set in the stream that is
+++++ +++++++++++++              * disabled now. Otherwise we could alter flags of the other
+++++ +++++++++++++              * stream
+++++ +++++++++++++              */
+++++ +++++++++++++
+++++ +++++++++++++             /* These assignments are simply vals without bits set in avals*/
+++++ +++++++++++++             sier = vals->sier & (vals->sier ^ avals->sier);
+++++ +++++++++++++             srcr = vals->srcr & (vals->srcr ^ avals->srcr);
+++++ +++++++++++++             stcr = vals->stcr & (vals->stcr ^ avals->stcr);
+++++ +++++++++++++
+++++ +++++++++++++             write_ssi_mask(&ssi->srcr, srcr, 0);
+++++ +++++++++++++             write_ssi_mask(&ssi->stcr, stcr, 0);
+++++ +++++++++++++             write_ssi_mask(&ssi->sier, sier, 0);
+++++ +++++++++++++     }
+++++ +++++++++++++
+++++ +++++++++++++config_done:
+++++ +++++++++++++     /* Enabling of subunits is done after configuration */
+++++ +++++++++++++     if (enable)
+++++ +++++++++++++             write_ssi_mask(&ssi->scr, 0, vals->scr);
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++
+++++ +++++++++++++static void fsl_ssi_rx_config(struct fsl_ssi_private *ssi_private, bool enable)
+++++ +++++++++++++{
+++++ +++++++++++++     fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.rx);
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable)
+++++ +++++++++++++{
+++++ +++++++++++++     fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx);
+++++ +++++++++++++}
+++++ +++++++++++++
+++++ +++++++++++++/*
+++++ +++++++++++++ * Setup rx/tx register values used to enable/disable the streams. These will
+++++ +++++++++++++ * be used later in fsl_ssi_config to setup the streams without the need to
+++++ +++++++++++++ * check for all different SSI modes.
+++++ +++++++++++++ */
+++++ +++++++++++++static void fsl_ssi_setup_reg_vals(struct fsl_ssi_private *ssi_private)
+++++ +++++++++++++{
+++++ +++++++++++++     struct fsl_ssi_rxtx_reg_val *reg = &ssi_private->rxtx_reg_val;
+++++ +++++++++++++
+++++ +++++++++++++     reg->rx.sier = CCSR_SSI_SIER_RFF0_EN;
+++++ +++++++++++++     reg->rx.srcr = CCSR_SSI_SRCR_RFEN0;
+++++ +++++++++++++     reg->rx.scr = 0;
+++++ +++++++++++++     reg->tx.sier = CCSR_SSI_SIER_TFE0_EN;
+++++ +++++++++++++     reg->tx.stcr = CCSR_SSI_STCR_TFEN0;
+++++ +++++++++++++     reg->tx.scr = 0;
+++++ +++++++++++++
+++++ +++++++++++++     if (!ssi_private->imx_ac97) {
+++++ +++++++++++++             reg->rx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE;
+++++ +++++++++++++             reg->rx.sier |= CCSR_SSI_SIER_RFF0_EN;
+++++ +++++++++++++             reg->tx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE;
+++++ +++++++++++++             reg->tx.sier |= CCSR_SSI_SIER_TFE0_EN;
+++++ +++++++++++++     }
+++++ +++++++++++++
+++++ +++++++++++++     if (ssi_private->use_dma) {
+++++ +++++++++++++             reg->rx.sier |= CCSR_SSI_SIER_RDMAE;
+++++ +++++++++++++             reg->tx.sier |= CCSR_SSI_SIER_TDMAE;
+++++ +++++++++++++     } else {
+++++ +++++++++++++             reg->rx.sier |= CCSR_SSI_SIER_RIE;
+++++ +++++++++++++             reg->tx.sier |= CCSR_SSI_SIER_TIE;
+++++ +++++++++++++     }
+++++ +++++++++++++
+++++ +++++++++++++     reg->rx.sier |= FSLSSI_SIER_DBG_RX_FLAGS;
+++++ +++++++++++++     reg->tx.sier |= FSLSSI_SIER_DBG_TX_FLAGS;
+++++ +++++++++++++}
+++++ +++++++++++++
 ++++ +++++++++++++static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
 ++++ +++++++++++++{
 ++++ +++++++++++++     struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
 ++++ +++++++++++++
 ++++ +++++++++++++     /*
 ++++ +++++++++++++      * Setup the clock control register
 ++++ +++++++++++++      */
 ++++ +++++++++++++     write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
 ++++ +++++++++++++                     &ssi->stccr);
 ++++ +++++++++++++     write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
 ++++ +++++++++++++                     &ssi->srccr);
 ++++ +++++++++++++
 ++++ +++++++++++++     /*
 ++++ +++++++++++++      * Enable AC97 mode and startup the SSI
 ++++ +++++++++++++      */
 ++++ +++++++++++++     write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
 ++++ +++++++++++++                     &ssi->sacnt);
 ++++ +++++++++++++     write_ssi(0xff, &ssi->saccdis);
 ++++ +++++++++++++     write_ssi(0x300, &ssi->saccen);
 ++++ +++++++++++++
 ++++ +++++++++++++     /*
 ++++ +++++++++++++      * Enable SSI, Transmit and Receive. AC97 has to communicate with the
 ++++ +++++++++++++      * codec before a stream is started.
 ++++ +++++++++++++      */
 ++++ +++++++++++++     write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
 ++++ +++++++++++++                     CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
 ++++ +++++++++++++
 ++++ +++++++++++++     write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
 ++++ +++++++++++++}
 ++++ +++++++++++++
                   static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
                   {
                        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
                        u8 wm;
                        int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
                   
+++++ +++++++++++++     fsl_ssi_setup_reg_vals(ssi_private);
+++++ +++++++++++++
                        if (ssi_private->imx_ac97)
 ---- -------------             i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
 ++++ +++++++++++++             ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
                        else
 ---- -------------             i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
 ++++ +++++++++++++             ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
                   
                        /*
                         * Section 16.5 of the MPC8610 reference manual says that the SSI needs
                        write_ssi_mask(&ssi->scr,
                                CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
                                CCSR_SSI_SCR_TFR_CLK_DIS |
 ---- -------------             i2s_mode |
 ++++ +++++++++++++             ssi_private->i2s_mode |
                                (synchronous ? CCSR_SSI_SCR_SYN : 0));
                   
----- -------------     write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
----- -------------              CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
----- -------------              CCSR_SSI_STCR_TSCKP, &ssi->stcr);
+++++ +++++++++++++     write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFSI |
+++++ +++++++++++++                     CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP, &ssi->stcr);
+++++ +++++++++++++
+++++ +++++++++++++     write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFSI |
+++++ +++++++++++++                     CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
                   
----- -------------     write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
----- -------------              CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
----- -------------              CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
                        /*
                         * The DC and PM bits are only used if the SSI is the clock master.
                         */
                         * because it is also running without an active substream. Normally SSI
                         * is only enabled when there is a substream.
                         */
 ---- -------------     if (ssi_private->imx_ac97) {
 ---- -------------             /*
 ---- -------------              * Setup the clock control register
 ---- -------------              */
 ---- -------------             write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
 ---- -------------                             &ssi->stccr);
 ---- -------------             write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
 ---- -------------                             &ssi->srccr);
 ---- -------------
 ---- -------------             /*
 ---- -------------              * Enable AC97 mode and startup the SSI
 ---- -------------              */
 ---- -------------             write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
 ---- -------------                             &ssi->sacnt);
 ---- -------------             write_ssi(0xff, &ssi->saccdis);
 ---- -------------             write_ssi(0x300, &ssi->saccen);
 ---- -------------
 ---- -------------             /*
 ---- -------------              * Enable SSI, Transmit and Receive
 ---- -------------              */
 ---- -------------             write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
 ---- -------------                             CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
 ++++ +++++++++++++     if (ssi_private->imx_ac97)
 ++++ +++++++++++++             fsl_ssi_setup_ac97(ssi_private);
                   
 ---- -------------             write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
+++++ +++++++++++++     /*
+++++ +++++++++++++      * Set a default slot number so that there is no need for those common
+++++ +++++++++++++      * cases like I2S mode to call the extra set_tdm_slot() any more.
+++++ +++++++++++++      */
+++++ +++++++++++++     if (!ssi_private->imx_ac97) {
+++++ +++++++++++++             write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
+++++ +++++++++++++                             CCSR_SSI_SxCCR_DC(2));
+++++ +++++++++++++             write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
+++++ +++++++++++++                             CCSR_SSI_SxCCR_DC(2));
+                       }
+                  
                        return 0;
                   }
                   
@@@@@@@@@@@@@@@@@@@@ -761,29 -548,28 -548,28 -548,28 -548,28 -1064,8 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 +1063,8 @@@@@@@@@@@@@@@@@@@@ static int fsl_ssi_trigger(struct snd_p
                        struct snd_soc_pcm_runtime *rtd = substream->private_data;
                        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
                        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
----- -------------     unsigned int sier_bits;
 ---- -------------
 ---- -------------     /*
 ---- -------------      *  Enable only the interrupts and DMA requests
 ---- -------------      *  that are needed for the channel. As the fiq
 ---- -------------      *  is polling for this bits, we have to ensure
 ---- -------------      *  that this are aligned with the preallocated
 ---- -------------      *  buffers
 ---- -------------      */
 ---- -------------
 ---- -------------     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 ---- -------------             if (ssi_private->use_dma)
 ---- -------------                     sier_bits = SIER_FLAGS;
 ---- -------------             else
 ---- -------------                     sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN;
 ---- -------------     } else {
 ---- -------------             if (ssi_private->use_dma)
 ---- -------------                     sier_bits = SIER_FLAGS;
 ---- -------------             else
 ---- -------------                     sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN;
 ---- -------------     }
 ++++ +++++++++++++     unsigned long flags;
                   
-                       /*
-                        *  Enable only the interrupts and DMA requests
-                        *  that are needed for the channel. As the fiq
-                        *  is polling for this bits, we have to ensure
-                        *  that this are aligned with the preallocated
-                        *  buffers
-                        */
-                  
-                       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                               if (ssi_private->use_dma)
-                                       sier_bits = SIER_FLAGS;
-                               else
-                                       sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN;
-                       } else {
-                               if (ssi_private->use_dma)
-                                       sier_bits = SIER_FLAGS;
-                               else
-                                       sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN;
-                       }
-                  
                        switch (cmd) {
                        case SNDRV_PCM_TRIGGER_START:
                        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                        case SNDRV_PCM_TRIGGER_STOP:
                        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
----- -------------                     write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0);
+++++ +++++++++++++                     fsl_ssi_tx_config(ssi_private, false);
                                else
----- -------------                     write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
+++++ +++++++++++++                     fsl_ssi_rx_config(ssi_private, false);
                   
                                if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) &
 ---- -------------                                     (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0)
 ---- -------------                     write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
 ++++ +++++++++++++                                     (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) {
-                                       write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
 ++++ +++++++++++++                     spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
 ++++ +++++++++++++                     ssi_private->baudclk_locked = false;
 ++++ +++++++++++++                     spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
 ++++ +++++++++++++             }
                                break;
                   
                        default:
@@@@@@@@@@@@@@@@@@@@ -863,58 -661,59 -661,59 -661,59 -661,59 -1147,6 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 +1146,6 @@@@@@@@@@@@@@@@@@@@ static const struct snd_soc_component_d
                        .name           = "fsl-ssi",
                   };
                   
----- -------------/**
----- ------------- * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit.
----- ------------- *
----- ------------- * This function is called by ALSA to start, stop, pause, and resume the
----- ------------- * transfer of data.
----- ------------- */
----- -------------static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
----- -------------                        struct snd_soc_dai *dai)
----- -------------{
----- -------------     struct snd_soc_pcm_runtime *rtd = substream->private_data;
----- -------------     struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(
----- -------------                     rtd->cpu_dai);
----- -------------     struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
----- -------------
----- -------------     switch (cmd) {
----- -------------     case SNDRV_PCM_TRIGGER_START:
----- -------------     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
----- -------------             if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
----- -------------                     write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE |
----- -------------                                     CCSR_SSI_SIER_TFE0_EN);
----- -------------             else
----- -------------                     write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE |
----- -------------                                     CCSR_SSI_SIER_RFF0_EN);
----- -------------             break;
----- -------------
----- -------------     case SNDRV_PCM_TRIGGER_STOP:
----- -------------     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
----- -------------             if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
----- -------------                     write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE |
----- -------------                                     CCSR_SSI_SIER_TFE0_EN, 0);
----- -------------             else
----- -------------                     write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE |
----- -------------                                     CCSR_SSI_SIER_RFF0_EN, 0);
----- -------------             break;
----- -------------
----- -------------     default:
----- -------------             return -EINVAL;
----- -------------     }
----- -------------
----- -------------     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
----- -------------             write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor);
----- -------------     else
----- -------------             write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor);
----- -------------
----- -------------     return 0;
----- -------------}
----- -------------
----- -------------static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = {
----- -------------     .startup        = fsl_ssi_startup,
 ---- -------------     .shutdown       = fsl_ssi_shutdown,
----- -------------     .trigger        = fsl_ssi_ac97_trigger,
----- -------------};
----- -------------
                   static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
                        .ac97_control = 1,
                        .playback = {
@@@@@@@@@@@@@@@@@@@@ -1150,10 -946,7 -946,7 -946,7 -946,7 -1340,37 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 +1339,37 @@@@@@@@@@@@@@@@@@@@ static int fsl_ssi_probe(struct platfor
                                   /* Older 8610 DTs didn't have the fifo-depth property */
                                ssi_private->fifo_depth = 8;
                   
 ---- -------------     if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
 ++++ +++++++++++++     ssi_private->baudclk_locked = false;
 ++++ +++++++++++++     spin_lock_init(&ssi_private->baudclk_lock);
 ++++ +++++++++++++
-                       if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
+++++ +++++++++++++     /*
+++++ +++++++++++++      * imx51 and later SoCs have a slightly different IP that allows the
+++++ +++++++++++++      * SSI configuration while the SSI unit is running.
+++++ +++++++++++++      *
+++++ +++++++++++++      * More important, it is necessary on those SoCs to configure the
+++++ +++++++++++++      * sperate TX/RX DMA bits just before starting the stream
+++++ +++++++++++++      * (fsl_ssi_trigger). The SDMA unit has to be configured before fsl_ssi
+++++ +++++++++++++      * sends any DMA requests to the SDMA unit, otherwise it is not defined
+++++ +++++++++++++      * how the SDMA unit handles the DMA request.
+++++ +++++++++++++      *
+++++ +++++++++++++      * SDMA units are present on devices starting at imx35 but the imx35
+++++ +++++++++++++      * reference manual states that the DMA bits should not be changed
+++++ +++++++++++++      * while the SSI unit is running (SSIEN). So we support the necessary
+++++ +++++++++++++      * online configuration of fsl-ssi starting at imx51.
+++++ +++++++++++++      */
+++++ +++++++++++++     switch (hw_type) {
+++++ +++++++++++++     case FSL_SSI_MCP8610:
+++++ +++++++++++++     case FSL_SSI_MX21:
+++++ +++++++++++++     case FSL_SSI_MX35:
+++++ +++++++++++++             ssi_private->offline_config = true;
+++++ +++++++++++++             break;
+++++ +++++++++++++     case FSL_SSI_MX51:
+++++ +++++++++++++             ssi_private->offline_config = false;
+++++ +++++++++++++             break;
+++++ +++++++++++++     }
+++++ +++++++++++++
+++++ +++++++++++++     if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 ||
+++++ +++++++++++++                     hw_type == FSL_SSI_MX35) {
                                u32 dma_events[2];
                                ssi_private->ssi_on_imx = true;
                   
                                        goto error_irqmap;
                                }
                   
-                                       dev_warn(&pdev->dev, "could not get baud clock: %d\n", ret);
 ++++ +++++++++++++             /* For those SLAVE implementations, we ingore non-baudclk cases
 ++++ +++++++++++++              * and, instead, abandon MASTER mode that needs baud clock.
 ++++ +++++++++++++              */
 ++++ +++++++++++++             ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud");
 ++++ +++++++++++++             if (IS_ERR(ssi_private->baudclk))
+++++ +++++++++++++                     dev_warn(&pdev->dev, "could not get baud clock: %ld\n",
+++++ +++++++++++++                              PTR_ERR(ssi_private->baudclk));
 ++++ +++++++++++++             else
 ++++ +++++++++++++                     clk_prepare_enable(ssi_private->baudclk);
 ++++ +++++++++++++
                                /*
                                 * We have burstsize be "fifo_depth - 2" to match the SSI
                                 * watermark setting in fsl_ssi_startup().
                        return 0;
                   
                   error_dai:
 ---- -------------     if (ssi_private->ssi_on_imx)
 ---- -------------             imx_pcm_dma_exit(pdev);
+++++ +++++++++++++     if (ssi_private->ssi_on_imx && !ssi_private->use_dma)
+++++ +++++++++++++             imx_pcm_fiq_exit(pdev);
+++++ +++++++++++++
+++++ +++++++++++++error_pcm:
+++++ +++++++++++++     fsl_ssi_debugfs_remove(ssi_private);
+++++ +++++++++++++
+++++ +++++++++++++error_dbgfs:
                        snd_soc_unregister_component(&pdev->dev);
                   
                   error_dev:
                        device_remove_file(&pdev->dev, dev_attr);
                   
                   error_clk:
 ---- -------------     if (ssi_private->ssi_on_imx)
 ++++ +++++++++++++     if (ssi_private->ssi_on_imx) {
 ++++ +++++++++++++             if (!IS_ERR(ssi_private->baudclk))
 ++++ +++++++++++++                     clk_disable_unprepare(ssi_private->baudclk);
                                clk_disable_unprepare(ssi_private->clk);
 ++++ +++++++++++++     }
                   
                   error_irqmap:
----- -------------     irq_dispose_mapping(ssi_private->irq);
+++++ +++++++++++++     if (ssi_private->irq_stats)
+++++ +++++++++++++             irq_dispose_mapping(ssi_private->irq);
                   
                        return ret;
                   }
                   {
                        struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
                   
+++++ +++++++++++++     fsl_ssi_debugfs_remove(ssi_private);
+++++ +++++++++++++
                        if (!ssi_private->new_binding)
                                platform_device_unregister(ssi_private->pdev);
 ---- -------------     if (ssi_private->ssi_on_imx)
 ---- -------------             imx_pcm_dma_exit(pdev);
                        snd_soc_unregister_component(&pdev->dev);
----- -------------     device_remove_file(&pdev->dev, &ssi_private->dev_attr);
 ---- -------------     if (ssi_private->ssi_on_imx)
 ++++ +++++++++++++     if (ssi_private->ssi_on_imx) {
 ++++ +++++++++++++             if (!IS_ERR(ssi_private->baudclk))
 ++++ +++++++++++++                     clk_disable_unprepare(ssi_private->baudclk);
                                clk_disable_unprepare(ssi_private->clk);
 ---- -------------     irq_dispose_mapping(ssi_private->irq);
 ++++ +++++++++++++     }
-                       irq_dispose_mapping(ssi_private->irq);
+++++ +++++++++++++     if (ssi_private->irq_stats)
+++++ +++++++++++++             irq_dispose_mapping(ssi_private->irq);
                   
                        return 0;
                   }
                    * it under the terms of the GNU General Public License version 2 as
                    * published by the Free Software Foundation.
                    */
 ----- ------------
 ----- ------------#include <linux/platform_device.h>
 +++++ ++++++++++++#include <linux/clk.h>
+                  #include <linux/module.h>
 +++++ ++++++++++++#include <linux/of.h>
 +++++ ++++++++++++#include <linux/platform_device.h>
-                  #include <linux/module.h>
++++++ ++++++++++++#include <linux/string.h>
                   #include <sound/simple_card.h>
                   
------ ------------#define asoc_simple_get_card_info(p) \
------ ------------     container_of(p->dai_link, struct asoc_simple_card_info, snd_link)
------ ------------
                   static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
                                                       struct asoc_simple_dai *set,
                                                       unsigned int daifmt)
@@@@@@@@@@@@@@@@@@@@ -58,173 -57,14 -57,14 -57,14 -57,14 -57,14 -57,171 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 +57,174 @@@@@@@@@@@@@@@@@@@@ static int asoc_simple_card_dai_init(st
                        return 0;
                   }
                   
-                               if (IS_ERR(clk)) {
-                                       ret = PTR_ERR(clk);
-                                       goto parse_error;
-                               }
-                  
-                               dai->sysclk = clk_get_rate(clk);
 +++++ ++++++++++++static int
 +++++ ++++++++++++asoc_simple_card_sub_parse_of(struct device_node *np,
 +++++ ++++++++++++                           struct asoc_simple_dai *dai,
 +++++ ++++++++++++                           struct device_node **node)
 +++++ ++++++++++++{
 +++++ ++++++++++++     struct clk *clk;
 +++++ ++++++++++++     int ret;
 +++++ ++++++++++++
 +++++ ++++++++++++     /*
 +++++ ++++++++++++      * get node via "sound-dai = <&phandle port>"
 +++++ ++++++++++++      * it will be used as xxx_of_node on soc_bind_dai_link()
 +++++ ++++++++++++      */
 +++++ ++++++++++++     *node = of_parse_phandle(np, "sound-dai", 0);
 +++++ ++++++++++++     if (!*node)
 +++++ ++++++++++++             return -ENODEV;
 +++++ ++++++++++++
 +++++ ++++++++++++     /* get dai->name */
 +++++ ++++++++++++     ret = snd_soc_of_get_dai_name(np, &dai->name);
 +++++ ++++++++++++     if (ret < 0)
 +++++ ++++++++++++             goto parse_error;
 +++++ ++++++++++++
 +++++ ++++++++++++     /*
 +++++ ++++++++++++      * bitclock-inversion, frame-inversion
 +++++ ++++++++++++      * bitclock-master,    frame-master
 +++++ ++++++++++++      * and specific "format" if it has
 +++++ ++++++++++++      */
 +++++ ++++++++++++     dai->fmt = snd_soc_of_parse_daifmt(np, NULL);
 +++++ ++++++++++++
 +++++ ++++++++++++     /*
 +++++ ++++++++++++      * dai->sysclk come from
 +++++ ++++++++++++      *  "clocks = <&xxx>" (if system has common clock)
 +++++ ++++++++++++      *  or "system-clock-frequency = <xxx>"
 +++++ ++++++++++++      *  or device's module clock.
 +++++ ++++++++++++      */
 +++++ ++++++++++++     if (of_property_read_bool(np, "clocks")) {
 +++++ ++++++++++++             clk = of_clk_get(np, 0);
 +++++ ++++++++++++             if (IS_ERR(clk)) {
 +++++ ++++++++++++                     ret = PTR_ERR(clk);
 +++++ ++++++++++++                     goto parse_error;
 +++++ ++++++++++++             }
 +++++ ++++++++++++
 +++++ ++++++++++++             dai->sysclk = clk_get_rate(clk);
 +++++ ++++++++++++     } else if (of_property_read_bool(np, "system-clock-frequency")) {
 +++++ ++++++++++++             of_property_read_u32(np,
 +++++ ++++++++++++                                  "system-clock-frequency",
 +++++ ++++++++++++                                  &dai->sysclk);
 +++++ ++++++++++++     } else {
 +++++ ++++++++++++             clk = of_clk_get(*node, 0);
-                       ret = snd_soc_of_parse_audio_routing(&info->snd_card,
-                                                       "simple-audio-routing");
-                       if (ret)
-                               return ret;
++++++ ++++++++++++             if (!IS_ERR(clk))
++++++ ++++++++++++                     dai->sysclk = clk_get_rate(clk);
 +++++ ++++++++++++     }
 +++++ ++++++++++++
 +++++ ++++++++++++     ret = 0;
 +++++ ++++++++++++
 +++++ ++++++++++++parse_error:
 +++++ ++++++++++++     of_node_put(*node);
 +++++ ++++++++++++
 +++++ ++++++++++++     return ret;
 +++++ ++++++++++++}
 +++++ ++++++++++++
 +++++ ++++++++++++static int asoc_simple_card_parse_of(struct device_node *node,
 +++++ ++++++++++++                                  struct asoc_simple_card_info *info,
 +++++ ++++++++++++                                  struct device *dev,
 +++++ ++++++++++++                                  struct device_node **of_cpu,
 +++++ ++++++++++++                                  struct device_node **of_codec,
 +++++ ++++++++++++                                  struct device_node **of_platform)
 +++++ ++++++++++++{
 +++++ ++++++++++++     struct device_node *np;
 +++++ ++++++++++++     char *name;
 +++++ ++++++++++++     int ret;
 +++++ ++++++++++++
 +++++ ++++++++++++     /* get CPU/CODEC common format via simple-audio-card,format */
 +++++ ++++++++++++     info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") &
 +++++ ++++++++++++             (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK);
 +++++ ++++++++++++
 +++++ ++++++++++++     /* DAPM routes */
++++++ ++++++++++++     if (of_property_read_bool(node, "simple-audio-card,routing")) {
++++++ ++++++++++++             ret = snd_soc_of_parse_audio_routing(&info->snd_card,
++++++ ++++++++++++                                     "simple-audio-card,routing");
++++++ ++++++++++++             if (ret)
++++++ ++++++++++++                     return ret;
++++++ ++++++++++++     }
 +++++ ++++++++++++
 +++++ ++++++++++++     /* CPU sub-node */
 +++++ ++++++++++++     ret = -EINVAL;
 +++++ ++++++++++++     np = of_get_child_by_name(node, "simple-audio-card,cpu");
 +++++ ++++++++++++     if (np)
 +++++ ++++++++++++             ret = asoc_simple_card_sub_parse_of(np,
 +++++ ++++++++++++                                               &info->cpu_dai,
 +++++ ++++++++++++                                               of_cpu);
 +++++ ++++++++++++     if (ret < 0)
 +++++ ++++++++++++             return ret;
 +++++ ++++++++++++
 +++++ ++++++++++++     /* CODEC sub-node */
 +++++ ++++++++++++     ret = -EINVAL;
 +++++ ++++++++++++     np = of_get_child_by_name(node, "simple-audio-card,codec");
 +++++ ++++++++++++     if (np)
 +++++ ++++++++++++             ret = asoc_simple_card_sub_parse_of(np,
 +++++ ++++++++++++                                               &info->codec_dai,
 +++++ ++++++++++++                                               of_codec);
 +++++ ++++++++++++     if (ret < 0)
 +++++ ++++++++++++             return ret;
 +++++ ++++++++++++
 ++++++++++++++++++     if (!info->cpu_dai.name || !info->codec_dai.name)
 ++++++++++++++++++             return -EINVAL;
 ++++++++++++++++++
 +++++ ++++++++++++     /* card name is created from CPU/CODEC dai name */
 +++++ ++++++++++++     name = devm_kzalloc(dev,
 +++++ ++++++++++++                         strlen(info->cpu_dai.name)   +
 +++++ ++++++++++++                         strlen(info->codec_dai.name) + 2,
 +++++ ++++++++++++                         GFP_KERNEL);
 +++++ ++++++++++++     sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name);
 +++++ ++++++++++++     info->name = info->card = name;
 +++++ ++++++++++++
 +++++ ++++++++++++     /* simple-card assumes platform == cpu */
 +++++ ++++++++++++     *of_platform = *of_cpu;
 +++++ ++++++++++++
 +++++ ++++++++++++     dev_dbg(dev, "card-name : %s\n", info->card);
 +++++ ++++++++++++     dev_dbg(dev, "platform : %04x\n", info->daifmt);
 +++++ ++++++++++++     dev_dbg(dev, "cpu : %s / %04x / %d\n",
 +++++ ++++++++++++             info->cpu_dai.name,
 +++++ ++++++++++++             info->cpu_dai.fmt,
 +++++ ++++++++++++             info->cpu_dai.sysclk);
 +++++ ++++++++++++     dev_dbg(dev, "codec : %s / %04x / %d\n",
 +++++ ++++++++++++             info->codec_dai.name,
 +++++ ++++++++++++             info->codec_dai.fmt,
 +++++ ++++++++++++             info->codec_dai.sysclk);
 +++++ ++++++++++++
 +++++ ++++++++++++     return 0;
 +++++ ++++++++++++}
 +++++ ++++++++++++
                   static int asoc_simple_card_probe(struct platform_device *pdev)
                   {
 ----- ------------     struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
 +++++ ++++++++++++     struct asoc_simple_card_info *cinfo;
 +++++ ++++++++++++     struct device_node *np = pdev->dev.of_node;
 +++++ ++++++++++++     struct device_node *of_cpu, *of_codec, *of_platform;
                        struct device *dev = &pdev->dev;
++++++ ++++++++++++     int ret;
                   
 ----- ------------     if (!cinfo) {
 ----- ------------             dev_err(dev, "no info for asoc-simple-card\n");
 ----- ------------             return -EINVAL;
 +++++ ++++++++++++     cinfo           = NULL;
 +++++ ++++++++++++     of_cpu          = NULL;
 +++++ ++++++++++++     of_codec        = NULL;
 +++++ ++++++++++++     of_platform     = NULL;
++++++ ++++++++++++
++++++ ++++++++++++     cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL);
++++++ ++++++++++++     if (!cinfo)
++++++ ++++++++++++             return -ENOMEM;
++++++ ++++++++++++
 +++++ ++++++++++++     if (np && of_device_is_available(np)) {
-                               cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL);
-                               if (cinfo) {
-                                       int ret;
-                                       cinfo->snd_card.dev = &pdev->dev;
-                                       ret = asoc_simple_card_parse_of(np, cinfo, dev,
-                                                                       &of_cpu,
-                                                                       &of_codec,
-                                                                       &of_platform);
-                                       if (ret < 0) {
-                                               if (ret != -EPROBE_DEFER)
-                                                       dev_err(dev, "parse error %d\n", ret);
-                                               return ret;
-                                       }
++++++ ++++++++++++             cinfo->snd_card.dev = dev;
++++++ ++++++++++++
++++++ ++++++++++++             ret = asoc_simple_card_parse_of(np, cinfo, dev,
++++++ ++++++++++++                                             &of_cpu,
++++++ ++++++++++++                                             &of_codec,
++++++ ++++++++++++                                             &of_platform);
++++++ ++++++++++++             if (ret < 0) {
++++++ ++++++++++++                     if (ret != -EPROBE_DEFER)
++++++ ++++++++++++                             dev_err(dev, "parse error %d\n", ret);
++++++ ++++++++++++                     return ret;
 +++++ ++++++++++++             }
 +++++ ++++++++++++     } else {
-                               cinfo->snd_card.dev = &pdev->dev;
-                               cinfo = pdev->dev.platform_data;
-                       }
++++++ ++++++++++++             if (!dev->platform_data) {
++++++ ++++++++++++                     dev_err(dev, "no info for asoc-simple-card\n");
++++++ ++++++++++++                     return -EINVAL;
++++++ ++++++++++++             }
 +++++ ++++++++++++
-                       if (!cinfo) {
-                               dev_err(dev, "no info for asoc-simple-card\n");
-                               return -EINVAL;
++++++ ++++++++++++             memcpy(cinfo, dev->platform_data, sizeof(*cinfo));
++++++ ++++++++++++             cinfo->snd_card.dev = dev;
                        }
                   
                        if (!cinfo->name        ||
                        cinfo->snd_card.owner           = THIS_MODULE;
                        cinfo->snd_card.dai_link        = &cinfo->snd_link;
                        cinfo->snd_card.num_links       = 1;
 ----- ------------     cinfo->snd_card.dev             = &pdev->dev;
                   
 ----- ------------     return snd_soc_register_card(&cinfo->snd_card);
 ----- ------------}
++++++ ++++++++++++     snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo);
+                  
 ----- ------------static int asoc_simple_card_remove(struct platform_device *pdev)
 ----- ------------{
 ----- ------------     struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
 ----- ------------
 ----- ------------     return snd_soc_unregister_card(&cinfo->snd_card);
 +++++ ++++++++++++     return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card);
                   }
                   
 +++++ ++++++++++++static const struct of_device_id asoc_simple_of_match[] = {
 +++++ ++++++++++++     { .compatible = "simple-audio-card", },
 +++++ ++++++++++++     {},
 +++++ ++++++++++++};
 +++++ ++++++++++++MODULE_DEVICE_TABLE(of, asoc_simple_of_match);
 +++++ ++++++++++++
                   static struct platform_driver asoc_simple_card = {
                        .driver = {
                                .name   = "asoc-simple-card",
Simple merge