dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Russell King <rmk+kernel@armlinux.org.uk>
To: Sven Van Asbroeck <thesven73@gmail.com>,
	Mark Brown <broonie@kernel.org>,
	Peter Ujfalusi <peter.ujfalusi@ti.com>,
	Jyri Sarha <jsarha@ti.com>
Cc: David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org
Subject: [PATCH 04/13] drm/i2c: tda998x: derive CTS_N value from aclk sample rate ratio
Date: Tue, 11 Jun 2019 12:01:52 +0100	[thread overview]
Message-ID: <E1haeXI-0001y0-S5@rmk-PC.armlinux.org.uk> (raw)
In-Reply-To: <20190611110052.iw6qbw2yvypxus6t@shell.armlinux.org.uk>

The TDA998x derives the CTS value using the supplied I2S bit clock
(ACLK, in TDA998x parlence) rather than 128·fs.  TDA998x uses two
constants named m and k in the CTS generator such that we have this
relationship between the I2S source ACLK and the sink fs:

	128·fs_sink = ACLK·m / k

Where ACLK = aclk_ratio·fs_source.

When audio support was originally added, we supported a fixed ratio
of 64·fs, intending to support the Kirkwood I2S on Dove.  However,
when hdmi-codec support was added, this was changed to scale the
ratio with the sample width, which would've broken its use with
Kirkwood I2S.

We are now starting to see other users whose I2S blocks send at 64·fs
for 16-bit samples, so we need to reinstate the support for the fixed
ratio I2S bit clock.

This commit takes a step towards supporting these configurations by
selecting the CTS_N register m and k values based on the bit clock
ratio.  However, as the driver is not given the bit clock ratio from
ALSA, continue deriving this from the sample width.  This will be
addressed in a later commit.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/i2c/tda998x_drv.c | 94 ++++++++++++++++++++++++++++++---------
 1 file changed, 74 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 78a2b815a8de..bf75414a8c63 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -43,6 +43,7 @@ struct tda998x_audio_port {
 struct tda998x_audio_settings {
 	struct tda998x_audio_params params;
 	u8 i2s_format;
+	u8 cts_n;
 };
 
 struct tda998x_priv {
@@ -891,6 +892,58 @@ static u8 tda998x_get_adiv(struct tda998x_priv *priv, unsigned int fs)
 	return adiv;
 }
 
+/*
+ * In auto-CTS mode, the TDA998x uses a "measured time stamp" counter to
+ * generate the CTS value.  It appears that the "measured time stamp" is
+ * the number of TDMS clock cycles within a number of audio input clock
+ * cycles defined by the k and N parameters defined below, in a similar
+ * way to that which is set out in the CTS generation in the HDMI spec.
+ *
+ *  tmdsclk ----> mts -> /m ---> CTS
+ *                 ^
+ *  sclk -> /k -> /N
+ *
+ * CTS = mts / m, where m is 2^M.
+ * /k is a divider based on the K value below, K+1 for K < 4, or 8 for K >= 4
+ * /N is a divider based on the HDMI specified N value.
+ *
+ * This produces the following equation:
+ *  CTS = tmds_clock * k * N / (sclk * m)
+ *
+ * When combined with the sink-side equation, and realising that sclk is
+ * bclk_ratio * fs, we end up with:
+ *  k = m * bclk_ratio / 128.
+ *
+ * Note: S/PDIF always uses a bclk_ratio of 64.
+ */
+static int tda998x_derive_cts_n(struct tda998x_priv *priv,
+				struct tda998x_audio_settings *settings,
+				unsigned int ratio)
+{
+	switch (ratio) {
+	case 16:
+		settings->cts_n = CTS_N_M(3) | CTS_N_K(0);
+		break;
+	case 32:
+		settings->cts_n = CTS_N_M(3) | CTS_N_K(1);
+		break;
+	case 48:
+		settings->cts_n = CTS_N_M(3) | CTS_N_K(2);
+		break;
+	case 64:
+		settings->cts_n = CTS_N_M(3) | CTS_N_K(3);
+		break;
+	case 128:
+		settings->cts_n = CTS_N_M(0) | CTS_N_K(0);
+		break;
+	default:
+		dev_err(&priv->hdmi->dev, "unsupported bclk ratio %ufs\n",
+			ratio);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
 {
 	if (on) {
@@ -905,7 +958,7 @@ static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
 static int tda998x_configure_audio(struct tda998x_priv *priv,
 				 const struct tda998x_audio_settings *settings)
 {
-	u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv;
+	u8 buf[6], clksel_aip, clksel_fs, adiv;
 	u32 n;
 
 	adiv = tda998x_get_adiv(priv, settings->params.sample_rate);
@@ -920,7 +973,6 @@ static int tda998x_configure_audio(struct tda998x_priv *priv,
 		reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF);
 		clksel_aip = AIP_CLKSEL_AIP_SPDIF;
 		clksel_fs = AIP_CLKSEL_FS_FS64SPDIF;
-		cts_n = CTS_N_M(3) | CTS_N_K(3);
 		break;
 
 	case AFMT_I2S:
@@ -928,20 +980,6 @@ static int tda998x_configure_audio(struct tda998x_priv *priv,
 		reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S);
 		clksel_aip = AIP_CLKSEL_AIP_I2S;
 		clksel_fs = AIP_CLKSEL_FS_ACLK;
-		switch (settings->params.sample_width) {
-		case 16:
-			cts_n = CTS_N_M(3) | CTS_N_K(1);
-			break;
-		case 18:
-		case 20:
-		case 24:
-			cts_n = CTS_N_M(3) | CTS_N_K(2);
-			break;
-		default:
-		case 32:
-			cts_n = CTS_N_M(3) | CTS_N_K(3);
-			break;
-		}
 		break;
 
 	default:
@@ -953,7 +991,7 @@ static int tda998x_configure_audio(struct tda998x_priv *priv,
 	reg_write(priv, REG_AIP_CLKSEL, clksel_aip);
 	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT |
 					AIP_CNTRL_0_ACR_MAN);	/* auto CTS */
-	reg_write(priv, REG_CTS_N, cts_n);
+	reg_write(priv, REG_CTS_N, settings->cts_n);
 	reg_write(priv, REG_AUDIO_DIV, adiv);
 
 	/*
@@ -1000,6 +1038,7 @@ static int tda998x_audio_hw_params(struct device *dev, void *data,
 				   struct hdmi_codec_params *params)
 {
 	struct tda998x_priv *priv = dev_get_drvdata(dev);
+	unsigned int bclk_ratio;
 	bool spdif = daifmt->fmt == HDMI_SPDIF;
 	int i, ret;
 	struct tda998x_audio_settings audio = {
@@ -1052,6 +1091,11 @@ static int tda998x_audio_hw_params(struct device *dev, void *data,
 		return -EINVAL;
 	}
 
+	bclk_ratio = spdif ? 64 : params->sample_width * 2;
+	ret = tda998x_derive_cts_n(priv, &audio, bclk_ratio);
+	if (ret < 0)
+		return ret;
+
 	mutex_lock(&priv->audio_mutex);
 	if (priv->supports_infoframes && priv->sink_has_audio)
 		ret = tda998x_configure_audio(priv, &audio);
@@ -1640,8 +1684,8 @@ static int tda998x_get_audio_ports(struct tda998x_priv *priv,
 	return 0;
 }
 
-static void tda998x_set_config(struct tda998x_priv *priv,
-			       const struct tda998x_encoder_params *p)
+static int tda998x_set_config(struct tda998x_priv *priv,
+			      const struct tda998x_encoder_params *p)
 {
 	priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
 			    (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
@@ -1657,9 +1701,17 @@ static void tda998x_set_config(struct tda998x_priv *priv,
 			    (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
 
 	if (p->audio_params.format != AFMT_UNUSED) {
+		unsigned int ratio;
+		bool spdif = p->audio_params.format == AFMT_SPDIF;
+
 		priv->audio.params = p->audio_params;
 		priv->audio.i2s_format = I2S_FORMAT_PHILIPS;
+
+		ratio = spdif ? 64 : p->audio_params.sample_width * 2;
+		return tda998x_derive_cts_n(priv, &priv->audio, ratio);
 	}
+
+	return 0;
 }
 
 static void tda998x_destroy(struct device *dev)
@@ -1861,7 +1913,9 @@ static int tda998x_create(struct device *dev)
 		if (priv->audio_port[0].format != AFMT_UNUSED)
 			tda998x_audio_codec_init(priv, &client->dev);
 	} else if (dev->platform_data) {
-		tda998x_set_config(priv, dev->platform_data);
+		ret = tda998x_set_config(priv, dev->platform_data);
+		if (ret)
+			goto fail;
 	}
 
 	priv->bridge.funcs = &tda998x_bridge_funcs;
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2019-06-11 11:09 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-11 11:00 [PATCH 00/13] tda998x updates Russell King - ARM Linux admin
2019-06-11 11:01 ` [PATCH 01/13] drm/i2c: tda998x: introduce tda998x_audio_settings Russell King
2019-06-12 15:24   ` Sven Van Asbroeck
2019-06-13  9:52     ` Russell King - ARM Linux admin
2019-06-11 11:01 ` [PATCH 02/13] drm/i2c: tda998x: implement different I2S flavours Russell King
2019-06-11 11:01 ` [PATCH 03/13] drm/i2c: tda998x: improve programming of audio divisor Russell King
2019-06-12 15:25   ` Sven Van Asbroeck
2019-06-12 16:26     ` Russell King - ARM Linux admin
2019-06-11 11:01 ` Russell King [this message]
2019-06-12 15:27   ` [PATCH 04/13] drm/i2c: tda998x: derive CTS_N value from aclk sample rate ratio Sven Van Asbroeck
2019-06-12 16:28     ` Russell King - ARM Linux admin
2019-06-12 16:37       ` Sven Van Asbroeck
2019-06-12 16:42         ` Russell King - ARM Linux admin
2019-06-12 16:45           ` Sven Van Asbroeck
2019-06-11 11:01 ` [PATCH 05/13] drm/i2c: tda998x: store audio port enable in settings Russell King
2019-06-11 11:02 ` [PATCH 06/13] drm/i2c: tda998x: index audio port enable config by route type Russell King
2019-06-11 11:02 ` [PATCH 07/13] drm/i2c: tda998x: configure both fields of AIP_CLKSEL together Russell King
2019-06-11 11:02 ` [PATCH 08/13] drm/i2c: tda998x: move audio routing configuration Russell King
2019-06-12 15:36   ` Sven Van Asbroeck
2019-06-12 16:32     ` Russell King - ARM Linux admin
2019-06-11 11:02 ` [PATCH 09/13] drm/i2c: tda998x: clean up tda998x_configure_audio() Russell King
2019-06-12 15:37   ` Sven Van Asbroeck
2019-06-11 11:02 ` [PATCH 10/13] drm/i2c: tda998x: get rid of params in audio settings Russell King
2019-06-11 11:02 ` [PATCH 11/13] drm/i2c: tda998x: add support for pixel repeated modes Russell King
2019-06-11 11:02 ` [PATCH 12/13] drm/i2c: tda998x: add bridge timing information Russell King
2019-06-12 15:38   ` Sven Van Asbroeck
2019-06-13 10:01     ` Russell King - ARM Linux admin
2019-06-11 11:02 ` [PATCH 13/13] drm/i2c: tda998x: improve correctness of quantisation range Russell King
2019-06-12 15:40 ` [PATCH 00/13] tda998x updates Sven Van Asbroeck
2019-06-13 10:52   ` Russell King - ARM Linux admin
2019-06-13 14:29 ` [PATCH v2 " Russell King - ARM Linux admin
2019-06-13 14:30   ` [PATCH v2 01/13] drm/i2c: tda998x: introduce tda998x_audio_settings Russell King
2019-06-13 18:48     ` Sven Van Asbroeck
2019-06-13 20:36       ` Russell King - ARM Linux admin
2019-06-13 14:31   ` [PATCH v2 02/13] drm/i2c: tda998x: implement different I2S flavours Russell King
2019-06-13 14:31   ` [PATCH v2 03/13] drm/i2c: tda998x: improve programming of audio divisor Russell King
2019-06-13 14:31   ` [PATCH v2 04/13] drm/i2c: tda998x: derive CTS_N value from aclk sample rate ratio Russell King
2019-06-13 14:31   ` [PATCH v2 05/13] drm/i2c: tda998x: store audio port enable in settings Russell King
2019-06-13 14:31   ` [PATCH v2 06/13] drm/i2c: tda998x: index audio port enable config by route type Russell King
2019-06-13 14:31   ` [PATCH v2 07/13] drm/i2c: tda998x: configure both fields of AIP_CLKSEL together Russell King
2019-06-13 14:31   ` [PATCH v2 08/13] drm/i2c: tda998x: move audio routing configuration Russell King
2019-06-13 14:31   ` [PATCH v2 09/13] drm/i2c: tda998x: clean up tda998x_configure_audio() Russell King
2019-06-13 14:31   ` [PATCH v2 10/13] drm/i2c: tda998x: get rid of params in audio settings Russell King
2019-06-13 14:31   ` [PATCH v2 11/13] drm/i2c: tda998x: add support for pixel repeated modes Russell King
2019-06-13 14:31   ` [PATCH v2 12/13] drm/i2c: tda998x: improve correctness of quantisation range Russell King
2019-06-13 14:31   ` [PATCH v2 13/13] drm/i2c: tda998x: add vendor specific infoframe support Russell King
2019-06-13 19:51   ` [PATCH v2 00/13] tda998x updates Sven Van Asbroeck
2019-06-13 20:56     ` Russell King - ARM Linux admin

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=E1haeXI-0001y0-S5@rmk-PC.armlinux.org.uk \
    --to=rmk+kernel@armlinux.org.uk \
    --cc=airlied@linux.ie \
    --cc=broonie@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jsarha@ti.com \
    --cc=peter.ujfalusi@ti.com \
    --cc=thesven73@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox