From e02e7813df718e01d51de6e6cc8a760e786457bd Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 1 Mar 2019 11:07:19 +0000 Subject: drm/i2c: tda998x: support for bclk_ratio via hdmi-codec hw_params Signed-off-by: Russell King --- drivers/gpu/drm/i2c/tda998x_drv.c | 57 ++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 9517f522dcb9..77787daab6d5 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -62,6 +62,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; @@ -961,25 +962,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", @@ -1059,12 +1059,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 = { @@ -1107,10 +1123,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; @@ -1160,6 +1185,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, .digital_mute = tda998x_audio_digital_mute, @@ -1757,7 +1784,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; @@ -1771,8 +1798,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; -- cgit