ASoC: SOF: Intel: hda: set I2S slave before enabling DSP
authorZhu Yingjiang <yingjiang.zhu@linux.intel.com>
Tue, 30 Apr 2019 23:09:22 +0000 (18:09 -0500)
committerMark Brown <broonie@kernel.org>
Fri, 3 May 2019 05:58:11 +0000 (14:58 +0900)
By default, the I2S ports are configured in master mode during
DSP powerup sequences, the FS and BCLK lines will be driven on
startup, even when the topology file explicitly requires the
SSP to be slave.

This may be problematic for external components configured in
master mode who don't expect the Intel SOC/PCH to drive. Fix by
configuring the SSP as slave before the SSP outputs are enabled
to avoid this transient behavior.

When the topology file configures the SSP as clock master, the
initial slave configuration will be overridden.

Signed-off-by: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/intel/hda-loader.c
sound/soc/sof/intel/hda.h

index 6a44bc349e44ceafb29917c5940b11e49250dc23..6427f0b3a2f113b7a7a13e65ce66e3e9c7ac8fc0 100644 (file)
@@ -84,6 +84,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata,
        const struct sof_intel_dsp_desc *chip = hda->desc;
        unsigned int status;
        int ret;
+       int i;
 
        /* step 1: power up corex */
        ret = hda_dsp_core_power_up(sdev, chip->cores_mask);
@@ -92,6 +93,16 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata,
                goto err;
        }
 
+       /* DSP is powered up, set all SSPs to slave mode */
+       for (i = 0; i < chip->ssp_count; i++) {
+               snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR,
+                                                chip->ssp_base_offset
+                                                + i * SSP_DEV_MEM_SIZE
+                                                + SSP_SSC1_OFFSET,
+                                                SSP_SET_SLAVE,
+                                                SSP_SET_SLAVE);
+       }
+
        /* step 2: purge FW request */
        snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req,
                          chip->ipc_req_mask | (HDA_DSP_IPC_PURGE_FW |
index b2cf6fa155758e035f6e5f5d52b2420376b1e62e..3799a351810613c6ab7d7908f685a4fd0e28460c 100644 (file)
 #define APL_SSP_COUNT          6
 #define CNL_SSP_COUNT          3
 
+/* SSP Registers */
+#define SSP_SSC1_OFFSET                0x4
+#define SSP_SET_SCLK_SLAVE     BIT(25)
+#define SSP_SET_SFRM_SLAVE     BIT(24)
+#define SSP_SET_SLAVE          (SSP_SET_SCLK_SLAVE | SSP_SET_SFRM_SLAVE)
+
 #define HDA_IDISP_CODEC(x) ((x) & BIT(2))
 
 struct sof_intel_dsp_bdl {