Merge remote-tracking branches 'asoc/topic/fsl-sai', 'asoc/topic/fsl-ssl', 'asoc...
[cascardo/linux.git] / sound / soc / fsl / fsl_sai.c
index 4919de9..0754df7 100644 (file)
@@ -405,7 +405,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
        struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
        unsigned int channels = params_channels(params);
-       u32 word_width = snd_pcm_format_width(params_format(params));
+       u32 word_width = params_width(params);
        u32 val_cr4 = 0, val_cr5 = 0;
        u32 slots = (channels == 1) ? 2 : channels;
        u32 slot_width = word_width;
@@ -514,7 +514,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
         * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx.
         * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx.
         */
-       regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, 0);
+       regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC,
+                          sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
        regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC,
                           sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0);
 
@@ -564,6 +565,24 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
                                           FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
                        regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
                                           FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
+
+                       /*
+                        * For sai master mode, after several open/close sai,
+                        * there will be no frame clock, and can't recover
+                        * anymore. Add software reset to fix this issue.
+                        * This is a hardware bug, and will be fix in the
+                        * next sai version.
+                        */
+                       if (!sai->is_slave_mode) {
+                               /* Software Reset for both Tx and Rx */
+                               regmap_write(sai->regmap,
+                                            FSL_SAI_TCSR, FSL_SAI_CSR_SR);
+                               regmap_write(sai->regmap,
+                                            FSL_SAI_RCSR, FSL_SAI_CSR_SR);
+                               /* Clear SR bit to finish the reset */
+                               regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
+                               regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
+                       }
                }
                break;
        default:
@@ -669,6 +688,22 @@ static const struct snd_soc_component_driver fsl_component = {
        .name           = "fsl-sai",
 };
 
+static struct reg_default fsl_sai_reg_defaults[] = {
+       {FSL_SAI_TCR1, 0},
+       {FSL_SAI_TCR2, 0},
+       {FSL_SAI_TCR3, 0},
+       {FSL_SAI_TCR4, 0},
+       {FSL_SAI_TCR5, 0},
+       {FSL_SAI_TDR,  0},
+       {FSL_SAI_TMR,  0},
+       {FSL_SAI_RCR1, 0},
+       {FSL_SAI_RCR2, 0},
+       {FSL_SAI_RCR3, 0},
+       {FSL_SAI_RCR4, 0},
+       {FSL_SAI_RCR5, 0},
+       {FSL_SAI_RMR,  0},
+};
+
 static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
@@ -702,13 +737,11 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
        case FSL_SAI_RCSR:
        case FSL_SAI_TFR:
        case FSL_SAI_RFR:
-       case FSL_SAI_TDR:
        case FSL_SAI_RDR:
                return true;
        default:
                return false;
        }
-
 }
 
 static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
@@ -741,6 +774,8 @@ static const struct regmap_config fsl_sai_regmap_config = {
        .val_bits = 32,
 
        .max_register = FSL_SAI_RMR,
+       .reg_defaults = fsl_sai_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults),
        .readable_reg = fsl_sai_readable_reg,
        .volatile_reg = fsl_sai_volatile_reg,
        .writeable_reg = fsl_sai_writeable_reg,