[PATCH] ASoC: ak4458: enable daisy chain

From: Shengjiu Wang
Date: Tue Apr 20 2021 - 06:59:25 EST


From: Viorel Suman <viorel.suman@xxxxxxx>

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@xxxxxxx>
Signed-off-by: Shengjiu Wang <shengjiu.wang@xxxxxxx>
---
sound/soc/codecs/ak4458.c | 47 ++++++++++++++++++++++++++-------------
sound/soc/codecs/ak4458.h | 1 +
2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c
index 3088128816bb..29eb78702bf3 100644
--- a/sound/soc/codecs/ak4458.c
+++ b/sound/soc/codecs/ak4458.c
@@ -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,
diff --git a/sound/soc/codecs/ak4458.h b/sound/soc/codecs/ak4458.h
index 9548c5d78621..9ad869575f8d 100644
--- a/sound/soc/codecs/ak4458.h
+++ b/sound/soc/codecs/ak4458.h
@@ -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)
--
2.27.0