summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i2c/tda998x_drv.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2019-03-01 11:07:19 +0000
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2023-10-30 13:32:15 +0000
commit1ec6262504919571c07a8ec2a95885f944f8f1e8 (patch)
treeee14ef6f2b4844a7aeb172cf4393faa6a9bb31d1 /drivers/gpu/drm/i2c/tda998x_drv.c
parent8506ba07a3351148c1e76e9e273b257124a0a2db (diff)
drm/i2c: tda998x: support for bclk_ratio via hdmi-codec hw_params
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'drivers/gpu/drm/i2c/tda998x_drv.c')
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index d8d7de18dd65..15ea7b5f1f17 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -63,6 +63,7 @@ struct tda998x_priv {
u8 vip_cntrl_0;
u8 vip_cntrl_1;
u8 vip_cntrl_2;
+ u8 i2s_cts_n;
unsigned long tmds_clock;
struct tda998x_audio_settings audio;
@@ -962,25 +963,24 @@ static u8 tda998x_get_adiv(struct tda998x_priv *priv, unsigned int fs)
*
* 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,
+static int tda998x_derive_cts_n(struct tda998x_priv *priv, u8 *cts_n,
unsigned int ratio)
{
switch (ratio) {
case 16:
- settings->cts_n = CTS_N_M(3) | CTS_N_K(0);
+ *cts_n = CTS_N_M(3) | CTS_N_K(0);
break;
case 32:
- settings->cts_n = CTS_N_M(3) | CTS_N_K(1);
+ *cts_n = CTS_N_M(3) | CTS_N_K(1);
break;
case 48:
- settings->cts_n = CTS_N_M(3) | CTS_N_K(2);
+ *cts_n = CTS_N_M(3) | CTS_N_K(2);
break;
case 64:
- settings->cts_n = CTS_N_M(3) | CTS_N_K(3);
+ *cts_n = CTS_N_M(3) | CTS_N_K(3);
break;
case 128:
- settings->cts_n = CTS_N_M(0) | CTS_N_K(0);
+ *cts_n = CTS_N_M(0) | CTS_N_K(0);
break;
default:
dev_err(&priv->hdmi->dev, "unsupported bclk ratio %ufs\n",
@@ -1060,12 +1060,28 @@ static void tda998x_configure_audio(struct tda998x_priv *priv)
tda998x_write_aif(priv, &settings->cea);
}
+static int tda998x_audio_startup(struct device *dev, void *data)
+{
+ struct tda998x_priv *priv = dev_get_drvdata(dev);
+
+ priv->i2s_cts_n = 0xff;
+
+ return 0;
+}
+
+static int tda998x_audio_bclk_ratio(struct device *dev, void *data,
+ unsigned int ratio)
+{
+ struct tda998x_priv *priv = dev_get_drvdata(dev);
+
+ return tda998x_derive_cts_n(priv, &priv->i2s_cts_n, ratio);
+}
+
static int tda998x_audio_hw_params(struct device *dev, void *data,
struct hdmi_codec_daifmt *daifmt,
struct hdmi_codec_params *params)
{
struct tda998x_priv *priv = dev_get_drvdata(dev);
- unsigned int bclk_ratio;
bool spdif = daifmt->fmt == HDMI_SPDIF;
int ret;
struct tda998x_audio_settings audio = {
@@ -1108,10 +1124,19 @@ static int tda998x_audio_hw_params(struct device *dev, void *data,
if (ret < 0)
return ret;
- bclk_ratio = spdif ? 64 : params->sample_width * 2;
- ret = tda998x_derive_cts_n(priv, &audio, bclk_ratio);
- if (ret < 0)
- return ret;
+ if (spdif) {
+ tda998x_derive_cts_n(priv, &audio.cts_n, 64);
+ } else if (priv->i2s_cts_n != 0xff) {
+ audio.cts_n = priv->i2s_cts_n;
+ } else {
+ dev_warn_once(&priv->hdmi->dev,
+ "I2S bit clock ratio not set, defaulting to 2x sample_width.\n"
+ "Please call snd_soc_dai_set_bclk_ratio() for this codec.\n");
+ ret = tda998x_derive_cts_n(priv, &audio.cts_n,
+ params->sample_width * 2);
+ if (ret < 0)
+ return ret;
+ }
mutex_lock(&priv->audio_mutex);
priv->audio = audio;
@@ -1161,6 +1186,8 @@ static int tda998x_audio_get_eld(struct device *dev, void *data,
}
static const struct hdmi_codec_ops audio_codec_ops = {
+ .audio_startup = tda998x_audio_startup,
+ .set_bclk_ratio = tda998x_audio_bclk_ratio,
.hw_params = tda998x_audio_hw_params,
.audio_shutdown = tda998x_audio_shutdown,
.mute_stream = tda998x_audio_mute_stream,
@@ -1762,7 +1789,7 @@ static int 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, route;
+ unsigned int route;
bool spdif = p->audio_params.format == AFMT_SPDIF;
route = AUDIO_ROUTE_I2S + spdif;
@@ -1776,8 +1803,8 @@ static int tda998x_set_config(struct tda998x_priv *priv,
priv->audio.ena_ap = p->audio_params.config;
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 tda998x_derive_cts_n(priv, &priv->audio.cts_n,
+ p->audio_params.sample_width * 2);
}
return 0;