All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
To: broonie@kernel.org, lgirdwood@gmail.com
Cc: alsa-devel@alsa-project.org, kuninori.morimoto.gx@renesas.com
Subject: [PATCH 1/2] ASoC: pcm3168a: Retain the independence of DAC and ADC side of the codec
Date: Mon, 12 Aug 2019 12:52:25 +0300	[thread overview]
Message-ID: <20190812095226.18870-2-peter.ujfalusi@ti.com> (raw)
In-Reply-To: <20190812095226.18870-1-peter.ujfalusi@ti.com>

The DAC and ADC path of the codec is independent, have dedicated LRCK (FS)
and BCK for DAC/ADC.

They can be configured to use different format, TDM slots and slot_width if
needed.

Move these parameters under dedicated io_params structure and manage them
independently based on the dai.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
 sound/soc/codecs/pcm3168a.c | 125 ++++++++++++++++--------------------
 1 file changed, 54 insertions(+), 71 deletions(-)

diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c
index e84a1509fe65..75fa8e9ee894 100644
--- a/sound/soc/codecs/pcm3168a.c
+++ b/sound/soc/codecs/pcm3168a.c
@@ -44,18 +44,25 @@ static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = {
 	"VCCDA2"
 };
 
+#define PCM3168A_DAI_DAC		0
+#define PCM3168A_DAI_ADC		1
+
+/* ADC/DAC side parameters */
+struct pcm3168a_io_params {
+	bool master_mode;
+	unsigned int fmt;
+	int tdm_slots;
+	u32 tdm_mask;
+	int slot_width;
+};
+
 struct pcm3168a_priv {
 	struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES];
 	struct regmap *regmap;
 	struct clk *scki;
-	bool adc_master_mode;
-	bool dac_master_mode;
 	unsigned long sysclk;
-	unsigned int adc_fmt;
-	unsigned int dac_fmt;
-	int tdm_slots;
-	u32 tdm_mask[2];
-	int slot_width;
+
+	struct pcm3168a_io_params io_params[2];
 };
 
 static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" };
@@ -308,8 +315,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
 	return 0;
 }
 
-static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai,
-			       unsigned int format, bool dac)
+static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
@@ -356,43 +362,31 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai,
 		return -EINVAL;
 	}
 
-	if (dac) {
+	if (dai->id == PCM3168A_DAI_DAC) {
 		reg = PCM3168A_DAC_PWR_MST_FMT;
 		mask = PCM3168A_DAC_FMT_MASK;
 		shift = PCM3168A_DAC_FMT_SHIFT;
-		pcm3168a->dac_master_mode = master_mode;
-		pcm3168a->dac_fmt = fmt;
 	} else {
 		reg = PCM3168A_ADC_MST_FMT;
 		mask = PCM3168A_ADC_FMTAD_MASK;
 		shift = PCM3168A_ADC_FMTAD_SHIFT;
-		pcm3168a->adc_master_mode = master_mode;
-		pcm3168a->adc_fmt = fmt;
 	}
 
+	pcm3168a->io_params[dai->id].master_mode = master_mode;
+	pcm3168a->io_params[dai->id].fmt = fmt;
+
 	regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift);
 
 	return 0;
 }
 
-static int pcm3168a_set_dai_fmt_dac(struct snd_soc_dai *dai,
-			       unsigned int format)
-{
-	return pcm3168a_set_dai_fmt(dai, format, true);
-}
-
-static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai,
-			       unsigned int format)
-{
-	return pcm3168a_set_dai_fmt(dai, format, false);
-}
-
 static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 				 unsigned int rx_mask, int slots,
 				 int slot_width)
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
+	struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
 
 	if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) {
 		dev_err(component->dev,
@@ -408,22 +402,25 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 		return -EINVAL;
 	}
 
-	if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) {
+	if (io_params->tdm_slots && io_params->tdm_slots != slots) {
 		dev_err(component->dev, "Not matching slots %d vs %d\n",
-			pcm3168a->tdm_slots, slots);
+			io_params->tdm_slots, slots);
 		return -EINVAL;
 	}
 
-	if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) {
+	if (io_params->slot_width && io_params->slot_width != slot_width) {
 		dev_err(component->dev, "Not matching slot_width %d vs %d\n",
-			pcm3168a->slot_width, slot_width);
+			io_params->slot_width, slot_width);
 		return -EINVAL;
 	}
 
-	pcm3168a->tdm_slots = slots;
-	pcm3168a->slot_width = slot_width;
-	pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
-	pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
+	io_params->tdm_slots = slots;
+	io_params->slot_width = slot_width;
+	/* Ignore the not relevant mask for the DAI/direction */
+	if (dai->id == PCM3168A_DAI_DAC)
+		io_params->tdm_mask = tx_mask;
+	else
+		io_params->tdm_mask = rx_mask;
 
 	return 0;
 }
@@ -434,7 +431,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
-	bool tx, master_mode;
+	struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
+	bool master_mode;
 	u32 val, mask, shift, reg;
 	unsigned int rate, fmt, ratio, max_ratio;
 	unsigned int tdm_slots;
@@ -444,23 +442,21 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
 
 	ratio = pcm3168a->sysclk / rate;
 
-	tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-	if (tx) {
+	if (dai->id == PCM3168A_DAI_DAC) {
 		max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC;
 		reg = PCM3168A_DAC_PWR_MST_FMT;
 		mask = PCM3168A_DAC_MSDA_MASK;
 		shift = PCM3168A_DAC_MSDA_SHIFT;
-		master_mode = pcm3168a->dac_master_mode;
-		fmt = pcm3168a->dac_fmt;
 	} else {
 		max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC;
 		reg = PCM3168A_ADC_MST_FMT;
 		mask = PCM3168A_ADC_MSAD_MASK;
 		shift = PCM3168A_ADC_MSAD_SHIFT;
-		master_mode = pcm3168a->adc_master_mode;
-		fmt = pcm3168a->adc_fmt;
 	}
 
+	master_mode = io_params->master_mode;
+	fmt = io_params->fmt;
+
 	for (i = 0; i < max_ratio; i++) {
 		if (pcm3168a_scki_ratios[i] == ratio)
 			break;
@@ -471,8 +467,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	if (pcm3168a->slot_width)
-		slot_width = pcm3168a->slot_width;
+	if (io_params->slot_width)
+		slot_width = io_params->slot_width;
 	else
 		slot_width = params_width(params);
 
@@ -497,8 +493,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	if (pcm3168a->tdm_slots)
-		tdm_slots = pcm3168a->tdm_slots;
+	if (io_params->tdm_slots)
+		tdm_slots = io_params->tdm_slots;
 	else
 		tdm_slots = params_channels(params);
 
@@ -534,7 +530,7 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
 
 	regmap_update_bits(pcm3168a->regmap, reg, mask, val);
 
-	if (tx) {
+	if (dai->id == PCM3168A_DAI_DAC) {
 		mask = PCM3168A_DAC_FMT_MASK;
 		shift = PCM3168A_DAC_FMT_SHIFT;
 	} else {
@@ -552,20 +548,13 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
-	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-	unsigned int fmt;
 	unsigned int sample_min;
 	unsigned int channel_max;
 	unsigned int channel_maxs[] = {
-		6, /* rx */
-		8  /* tx */
+		8, /* DAC */
+		6  /* ADC */
 	};
 
-	if (tx)
-		fmt = pcm3168a->dac_fmt;
-	else
-		fmt = pcm3168a->adc_fmt;
-
 	/*
 	 * Available Data Bits
 	 *
@@ -578,7 +567,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
 	 * I2S
 	 * LEFT_J
 	 */
-	switch (fmt) {
+	switch (pcm3168a->io_params[dai->id].fmt) {
 	case PCM3168A_FMT_RIGHT_J:
 		sample_min  = 16;
 		channel_max =  2;
@@ -588,7 +577,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
 	case PCM3168A_FMT_DSP_A:
 	case PCM3168A_FMT_DSP_B:
 		sample_min  = 24;
-		channel_max = channel_maxs[tx];
+		channel_max = channel_maxs[dai->id];
 		break;
 	default:
 		sample_min  = 24;
@@ -600,8 +589,8 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
 				     sample_min, 32);
 
 	/* Allow all channels in multi DIN/DOUT mode */
-	if (pcm3168a->tdm_slots == 2)
-		channel_max = channel_maxs[tx];
+	if (pcm3168a->io_params[dai->id].tdm_slots == 2)
+		channel_max = channel_maxs[dai->id];
 
 	snd_pcm_hw_constraint_minmax(substream->runtime,
 				     SNDRV_PCM_HW_PARAM_CHANNELS,
@@ -609,26 +598,19 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream,
 
 	return 0;
 }
-static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = {
+static const struct snd_soc_dai_ops pcm3168a_dai_ops = {
 	.startup	= pcm3168a_startup,
-	.set_fmt	= pcm3168a_set_dai_fmt_dac,
+	.set_fmt	= pcm3168a_set_dai_fmt,
 	.set_sysclk	= pcm3168a_set_dai_sysclk,
 	.hw_params	= pcm3168a_hw_params,
 	.digital_mute	= pcm3168a_digital_mute,
 	.set_tdm_slot	= pcm3168a_set_tdm_slot,
 };
 
-static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = {
-	.startup	= pcm3168a_startup,
-	.set_fmt	= pcm3168a_set_dai_fmt_adc,
-	.set_sysclk	= pcm3168a_set_dai_sysclk,
-	.hw_params	= pcm3168a_hw_params,
-	.set_tdm_slot	= pcm3168a_set_tdm_slot,
-};
-
 static struct snd_soc_dai_driver pcm3168a_dais[] = {
 	{
 		.name = "pcm3168a-dac",
+		.id = PCM3168A_DAI_DAC,
 		.playback = {
 			.stream_name = "Playback",
 			.channels_min = 1,
@@ -636,10 +618,11 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = {
 			.rates = SNDRV_PCM_RATE_8000_192000,
 			.formats = PCM3168A_FORMATS
 		},
-		.ops = &pcm3168a_dac_dai_ops
+		.ops = &pcm3168a_dai_ops
 	},
 	{
 		.name = "pcm3168a-adc",
+		.id = PCM3168A_DAI_ADC,
 		.capture = {
 			.stream_name = "Capture",
 			.channels_min = 1,
@@ -647,7 +630,7 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = {
 			.rates = SNDRV_PCM_RATE_8000_96000,
 			.formats = PCM3168A_FORMATS
 		},
-		.ops = &pcm3168a_adc_dai_ops
+		.ops = &pcm3168a_dai_ops
 	},
 };
 
-- 
Peter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

  reply	other threads:[~2019-08-12  9:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-12  9:52 [PATCH 0/2] ASoC: pcm3168a: DAC/ADC independence and right_j fix Peter Ujfalusi
2019-08-12  9:52 ` Peter Ujfalusi [this message]
2019-08-12  9:52 ` [PATCH 2/2] ASoC: pcm3168a: Allow reconfiguration of tdm_slots and slot_width Peter Ujfalusi
2019-08-12 13:09   ` Applied "ASoC: pcm3168a: Allow reconfiguration of tdm_slots and slot_width" to the asoc tree Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190812095226.18870-2-peter.ujfalusi@ti.com \
    --to=peter.ujfalusi@ti.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=kuninori.morimoto.gx@renesas.com \
    --cc=lgirdwood@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.