diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2019-03-01 11:07:19 +0000 |
---|---|---|
committer | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2023-10-30 13:32:15 +0000 |
commit | 1ec6262504919571c07a8ec2a95885f944f8f1e8 (patch) | |
tree | ee14ef6f2b4844a7aeb172cf4393faa6a9bb31d1 | |
parent | 8506ba07a3351148c1e76e9e273b257124a0a2db (diff) |
drm/i2c: tda998x: support for bclk_ratio via hdmi-codec hw_params
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r-- | drivers/gpu/drm/i2c/tda998x_drv.c | 57 |
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; |