OSDN Git Service

ASoC: ak4458: enable daisy chain
authorViorel Suman <viorel.suman@nxp.com>
Tue, 20 Apr 2021 10:44:13 +0000 (18:44 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 20 Apr 2021 16:25:51 +0000 (17:25 +0100)
Enable Daisy Chain if in TDM mode and the number of played
channels is bigger than the maximum supported number of channels.

Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Link: https://lore.kernel.org/r/1618915453-29445-1-git-send-email-shengjiu.wang@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/ak4458.c
sound/soc/codecs/ak4458.h

index 3088128..29eb787 100644 (file)
@@ -306,6 +306,20 @@ static const struct snd_soc_dapm_route ak4497_intercon[] = {
 
 };
 
+static int ak4458_get_tdm_mode(struct ak4458_priv *ak4458)
+{
+       switch (ak4458->slots * ak4458->slot_width) {
+       case 128:
+               return 1;
+       case 256:
+               return 2;
+       case 512:
+               return 3;
+       default:
+               return 0;
+       }
+}
+
 static int ak4458_rstn_control(struct snd_soc_component *component, int bit)
 {
        int ret;
@@ -333,13 +347,16 @@ static int ak4458_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_component *component = dai->component;
        struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
        int pcm_width = max(params_physical_width(params), ak4458->slot_width);
-       u8 format, dsdsel0, dsdsel1;
-       int nfs1, dsd_bclk, ret;
+       u8 format, dsdsel0, dsdsel1, dchn;
+       int nfs1, dsd_bclk, ret, channels, channels_max;
 
        nfs1 = params_rate(params);
        ak4458->fs = nfs1;
 
        /* calculate bit clock */
+       channels = params_channels(params);
+       channels_max = dai->driver->playback.channels_max;
+
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_DSD_U8:
        case SNDRV_PCM_FORMAT_DSD_U16_LE:
@@ -419,6 +436,17 @@ static int ak4458_hw_params(struct snd_pcm_substream *substream,
        snd_soc_component_update_bits(component, AK4458_00_CONTROL1,
                            AK4458_DIF_MASK, format);
 
+       /*
+        * Enable/disable Daisy Chain if in TDM mode and the number of played
+        * channels is bigger than the maximum supported number of channels
+        */
+       dchn = ak4458_get_tdm_mode(ak4458) &&
+               (ak4458->fmt == SND_SOC_DAIFMT_DSP_B) &&
+               (channels > channels_max) ? AK4458_DCHAIN_MASK : 0;
+
+       snd_soc_component_update_bits(component, AK4458_0B_CONTROL7,
+                                     AK4458_DCHAIN_MASK, dchn);
+
        ret = ak4458_rstn_control(component, 0);
        if (ret)
                return ret;
@@ -519,20 +547,7 @@ static int ak4458_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
        ak4458->slots = slots;
        ak4458->slot_width = slot_width;
 
-       switch (slots * slot_width) {
-       case 128:
-               mode = AK4458_MODE_TDM128;
-               break;
-       case 256:
-               mode = AK4458_MODE_TDM256;
-               break;
-       case 512:
-               mode = AK4458_MODE_TDM512;
-               break;
-       default:
-               mode = AK4458_MODE_NORMAL;
-               break;
-       }
+       mode = ak4458_get_tdm_mode(ak4458) << AK4458_MODE_SHIFT;
 
        snd_soc_component_update_bits(component, AK4458_0A_CONTROL6,
                            AK4458_MODE_MASK,
index 9548c5d..9ad8695 100644 (file)
@@ -82,6 +82,7 @@
  * */
 #define AK4458_ATS_SHIFT       6
 #define AK4458_ATS_MASK                GENMASK(7, 6)
+#define AK4458_DCHAIN_MASK     (0x1 << 1)
 
 #define AK4458_DSDSEL_MASK             (0x1 << 0)
 #define AK4458_DP_MASK                 (0x1 << 7)