Add support for the left and right justified I2S formats as well as the
more tranditional "Philips" I2S format.

Signed-off-by: Russell King <rmk+ker...@armlinux.org.uk>
---
 drivers/gpu/drm/i2c/tda998x_drv.c | 57 ++++++++++++++++++++++++++-------------
 include/drm/i2c/tda998x.h         | 11 +++++---
 2 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c 
b/drivers/gpu/drm/i2c/tda998x_drv.c
index a7c39f39793f..645d884fb9e8 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -242,7 +242,9 @@ struct tda998x_priv {
 # define HVF_CNTRL_1_SEMI_PLANAR  (1 << 6)
 #define REG_RPT_CNTRL             REG(0x00, 0xf0)     /* write */
 #define REG_I2S_FORMAT            REG(0x00, 0xfc)     /* read/write */
-# define I2S_FORMAT(x)            (((x) & 3) << 0)
+# define I2S_FORMAT_PHILIPS       (0 << 0)
+# define I2S_FORMAT_LEFT_J        (2 << 0)
+# define I2S_FORMAT_RIGHT_J       (3 << 0)
 #define REG_AIP_CLKSEL            REG(0x00, 0xfd)     /* write */
 # define AIP_CLKSEL_AIP_SPDIF    (0 << 3)
 # define AIP_CLKSEL_AIP_I2S      (1 << 3)
@@ -872,14 +874,14 @@ static int
 tda998x_configure_audio(struct tda998x_priv *priv,
                        struct tda998x_audio_params *params)
 {
-       u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv;
+       u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv, i2s_fmt;
        u32 n;
 
        /* Enable audio ports */
        reg_write(priv, REG_ENA_AP, params->config);
 
        /* Set audio input source */
-       switch (params->format) {
+       switch (params->format & AFMT_MASK) {
        case AFMT_SPDIF:
                reg_write(priv, REG_ENA_ACLK, 0);
                reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF);
@@ -907,6 +909,19 @@ tda998x_configure_audio(struct tda998x_priv *priv,
                        cts_n = CTS_N_M(3) | CTS_N_K(3);
                        break;
                }
+
+               switch (params->format & AFMT_I2S_MASK) {
+               case AFMT_I2S_LEFT_J:
+                       i2s_fmt = I2S_FORMAT_LEFT_J;
+                       break;
+               case AFMT_I2S_RIGHT_J:
+                       i2s_fmt = I2S_FORMAT_RIGHT_J;
+                       break;
+               default:
+                       i2s_fmt = I2S_FORMAT_PHILIPS;
+                       break;
+               }
+               reg_write(priv, REG_I2S_FORMAT, i2s_fmt);
                break;
 
        default:
@@ -992,23 +1007,15 @@ static int tda998x_audio_hw_params(struct device *dev, 
void *data,
 
        switch (daifmt->fmt) {
        case HDMI_I2S:
-               if (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
-                   daifmt->bit_clk_master || daifmt->frame_clk_master) {
-                       dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
-                               daifmt->bit_clk_inv, daifmt->frame_clk_inv,
-                               daifmt->bit_clk_master,
-                               daifmt->frame_clk_master);
-                       return -EINVAL;
-               }
-               for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
-                       if (priv->audio_port[i].format == AFMT_I2S)
-                               audio.config = priv->audio_port[i].config;
-               audio.format = AFMT_I2S;
+               audio.format = AFMT_I2S | AFMT_I2S_PHILIPS;
+               break;
+       case HDMI_LEFT_J:
+               audio.format = AFMT_I2S | AFMT_I2S_LEFT_J;
+               break;
+       case HDMI_RIGHT_J:
+               audio.format = AFMT_I2S | AFMT_I2S_RIGHT_J;
                break;
        case HDMI_SPDIF:
-               for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
-                       if (priv->audio_port[i].format == AFMT_SPDIF)
-                               audio.config = priv->audio_port[i].config;
                audio.format = AFMT_SPDIF;
                break;
        default:
@@ -1016,11 +1023,25 @@ static int tda998x_audio_hw_params(struct device *dev, 
void *data,
                return -EINVAL;
        }
 
+       for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
+               if (priv->audio_port[i].format == (audio.format & AFMT_MASK))
+                       audio.config = priv->audio_port[i].config;
+
        if (audio.config == 0) {
                dev_err(dev, "%s: No audio configuration found\n", __func__);
                return -EINVAL;
        }
 
+       if ((audio.format & AFMT_MASK) == HDMI_I2S &&
+           (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
+            daifmt->bit_clk_master || daifmt->frame_clk_master)) {
+               dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
+                       daifmt->bit_clk_inv, daifmt->frame_clk_inv,
+                       daifmt->bit_clk_master,
+                       daifmt->frame_clk_master);
+               return -EINVAL;
+       }
+
        mutex_lock(&priv->audio_mutex);
        if (priv->supports_infoframes && priv->sink_has_audio)
                ret = tda998x_configure_audio(priv, &audio);
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index 3cb25ccbe5e6..b0864f0be017 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -6,9 +6,14 @@
 #include <dt-bindings/display/tda998x.h>
 
 enum {
-       AFMT_UNUSED =   0,
-       AFMT_SPDIF =    TDA998x_SPDIF,
-       AFMT_I2S =      TDA998x_I2S,
+       AFMT_UNUSED      = 0,
+       AFMT_SPDIF       = TDA998x_SPDIF,
+       AFMT_I2S         = TDA998x_I2S,
+       AFMT_MASK        = AFMT_SPDIF | AFMT_I2S,
+       AFMT_I2S_PHILIPS = 0 << 4,
+       AFMT_I2S_LEFT_J  = 1 << 4,
+       AFMT_I2S_RIGHT_J = 2 << 4,
+       AFMT_I2S_MASK    = 3 << 4,
 };
 
 struct tda998x_audio_params {
-- 
2.7.4

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

Reply via email to