diff mbox

[v2,12/14] ASoC: hdac_hdmi: Add infoframe support for dp audio

Message ID 1449176942-3441-12-git-send-email-subhransu.s.prusty@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Subhransu S. Prusty Dec. 3, 2015, 9:09 p.m. UTC
This uses the get_conn_type API added in the previous patch to
identify the type of display connected and fills the infoframe
accordingly.

Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
---
 sound/soc/codecs/hdac_hdmi.c | 68 ++++++++++++++++++++++++++++++++++++++------
 1 file changed, 59 insertions(+), 9 deletions(-)

Comments

Daniel Stone Dec. 3, 2015, 5:13 p.m. UTC | #1
Hi Subhransu,

On 3 December 2015 at 21:09, Subhransu S. Prusty
<subhransu.s.prusty@intel.com> wrote:
> +       if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
> +               hdmi_audio_infoframe_init(&frame);
> +
> +               /* Default stereo for now */
> +               frame.channels = channels;
> +
> +               ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
> +               if (ret < 0)
> +                       return ret;
> +
> +               dip = (u8 *)&frame;
> +
> +       } else if (conn_type == DRM_ELD_CONN_TYPE_DP) {
> +               memset(&dp_ai, 0, sizeof(dp_ai));
> +               dp_ai.type      = 0x84;
> +               dp_ai.len       = 0x1b;
> +               dp_ai.ver       = 0x11 << 2;
> +               dp_ai.CC02_CT47 = channels - 1;
> +               dp_ai.CA        = 0;
> +
> +               dip = (u8 *)&dip;

Surely this should be dip = (u8 *) &dp_ai, instead of pointing to itself?

Cheers,
Daniel

On 3 December 2015 at 21:09, Subhransu S. Prusty
<subhransu.s.prusty@intel.com> wrote:
> This uses the get_conn_type API added in the previous patch to
> identify the type of display connected and fills the infoframe
> accordingly.
>
> Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
> ---
>  sound/soc/codecs/hdac_hdmi.c | 68 ++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 59 insertions(+), 9 deletions(-)
>
> diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
> index 3ac3498..d963d92 100644
> --- a/sound/soc/codecs/hdac_hdmi.c
> +++ b/sound/soc/codecs/hdac_hdmi.c
> @@ -22,6 +22,7 @@
>  #include <linux/module.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/hdmi.h>
> +#include <drm/drm_edid.h>
>  #include <sound/pcm_params.h>
>  #include <sound/soc.h>
>  #include <sound/hdaudio_ext.h>
> @@ -201,27 +202,70 @@ hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid,
>                                 AC_VERB_SET_HDMI_DIP_INDEX, val);
>  }
>
> +struct dp_audio_infoframe {
> +       u8 type; /* 0x84 */
> +       u8 len;  /* 0x1b */
> +       u8 ver;  /* 0x11 << 2 */
> +
> +       u8 CC02_CT47;   /* match with HDMI infoframe from this on */
> +       u8 SS01_SF24;
> +       u8 CXT04;
> +       u8 CA;
> +       u8 LFEPBL01_LSV36_DM_INH7;
> +};
> +
>  static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
>                                 hda_nid_t cvt_nid, hda_nid_t pin_nid)
>  {
>         uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
>         struct hdmi_audio_infoframe frame;
> +       struct dp_audio_infoframe dp_ai;
> +       struct hdac_hdmi_priv *hdmi = hdac->private_data;
> +       struct hdac_hdmi_pin *pin;
>         u8 *dip = (u8 *)&frame;
>         int ret;
>         int i;
> +       const u8 *eld_buf;
> +       u8 conn_type;
> +       int channels = 2;
>
> -       hdmi_audio_infoframe_init(&frame);
> +       list_for_each_entry(pin, &hdmi->pin_list, head) {
> +               if (pin->nid == pin_nid)
> +                       break;
> +       }
>
> -       /* Default stereo for now */
> -       frame.channels = 2;
> +       eld_buf = pin->eld.eld_buffer;
> +       conn_type = drm_eld_get_conn_type(eld_buf);
>
>         /* setup channel count */
>         snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0,
> -                           AC_VERB_SET_CVT_CHAN_COUNT, frame.channels - 1);
> +                           AC_VERB_SET_CVT_CHAN_COUNT, channels - 1);
>
> -       ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
> -       if (ret < 0)
> -               return ret;
> +       if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
> +               hdmi_audio_infoframe_init(&frame);
> +
> +               /* Default stereo for now */
> +               frame.channels = channels;
> +
> +               ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
> +               if (ret < 0)
> +                       return ret;
> +
> +               dip = (u8 *)&frame;
> +
> +       } else if (conn_type == DRM_ELD_CONN_TYPE_DP) {
> +               memset(&dp_ai, 0, sizeof(dp_ai));
> +               dp_ai.type      = 0x84;
> +               dp_ai.len       = 0x1b;
> +               dp_ai.ver       = 0x11 << 2;
> +               dp_ai.CC02_CT47 = channels - 1;
> +               dp_ai.CA        = 0;
> +
> +               dip = (u8 *)&dip;
> +       } else {
> +               dev_err(&hdac->hdac.dev, "Invalid connection type: %d\n", conn_type);
> +               return -EIO;
> +       }
>
>         /* stop infoframe transmission */
>         hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
> @@ -231,9 +275,15 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
>
>         /*  Fill infoframe. Index auto-incremented */
>         hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
> -       for (i = 0; i < sizeof(frame); i++)
> -               snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
> +       if (conn_type == 0) {
> +               for (i = 0; i < sizeof(frame); i++)
> +                       snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
>                                 AC_VERB_SET_HDMI_DIP_DATA, dip[i]);
> +       } else {
> +               for (i = 0; i < sizeof(dp_ai); i++)
> +                       snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
> +                               AC_VERB_SET_HDMI_DIP_DATA, dip[i]);
> +       }
>
>         /* Start infoframe */
>         hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
> --
> 1.9.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
Subhransu S. Prusty Dec. 4, 2015, 10:32 a.m. UTC | #2
On Thu, Dec 03, 2015 at 05:13:16PM +0000, Daniel Stone wrote:
> Hi Subhransu,
> 
> On 3 December 2015 at 21:09, Subhransu S. Prusty
> <subhransu.s.prusty@intel.com> wrote:
> > +       if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
> > +               hdmi_audio_infoframe_init(&frame);
> > +
> > +               /* Default stereo for now */
> > +               frame.channels = channels;
> > +
> > +               ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
> > +               if (ret < 0)
> > +                       return ret;
> > +
> > +               dip = (u8 *)&frame;
> > +
> > +       } else if (conn_type == DRM_ELD_CONN_TYPE_DP) {
> > +               memset(&dp_ai, 0, sizeof(dp_ai));
> > +               dp_ai.type      = 0x84;
> > +               dp_ai.len       = 0x1b;
> > +               dp_ai.ver       = 0x11 << 2;
> > +               dp_ai.CC02_CT47 = channels - 1;
> > +               dp_ai.CA        = 0;
> > +
> > +               dip = (u8 *)&dip;
> 
> Surely this should be dip = (u8 *) &dp_ai, instead of pointing to itself?

Thanks for pointing. It's a mistake, will fix it.

Regards,
Subhansu
> 
> Cheers,
> Daniel
>
diff mbox

Patch

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 3ac3498..d963d92 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -22,6 +22,7 @@ 
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/hdmi.h>
+#include <drm/drm_edid.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/hdaudio_ext.h>
@@ -201,27 +202,70 @@  hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid,
 				AC_VERB_SET_HDMI_DIP_INDEX, val);
 }
 
+struct dp_audio_infoframe {
+	u8 type; /* 0x84 */
+	u8 len;  /* 0x1b */
+	u8 ver;  /* 0x11 << 2 */
+
+	u8 CC02_CT47;	/* match with HDMI infoframe from this on */
+	u8 SS01_SF24;
+	u8 CXT04;
+	u8 CA;
+	u8 LFEPBL01_LSV36_DM_INH7;
+};
+
 static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
 				hda_nid_t cvt_nid, hda_nid_t pin_nid)
 {
 	uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
 	struct hdmi_audio_infoframe frame;
+	struct dp_audio_infoframe dp_ai;
+	struct hdac_hdmi_priv *hdmi = hdac->private_data;
+	struct hdac_hdmi_pin *pin;
 	u8 *dip = (u8 *)&frame;
 	int ret;
 	int i;
+	const u8 *eld_buf;
+	u8 conn_type;
+	int channels = 2;
 
-	hdmi_audio_infoframe_init(&frame);
+	list_for_each_entry(pin, &hdmi->pin_list, head) {
+		if (pin->nid == pin_nid)
+			break;
+	}
 
-	/* Default stereo for now */
-	frame.channels = 2;
+	eld_buf = pin->eld.eld_buffer;
+	conn_type = drm_eld_get_conn_type(eld_buf);
 
 	/* setup channel count */
 	snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0,
-			    AC_VERB_SET_CVT_CHAN_COUNT, frame.channels - 1);
+			    AC_VERB_SET_CVT_CHAN_COUNT, channels - 1);
 
-	ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
-	if (ret < 0)
-		return ret;
+	if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
+		hdmi_audio_infoframe_init(&frame);
+
+		/* Default stereo for now */
+		frame.channels = channels;
+
+		ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
+		if (ret < 0)
+			return ret;
+
+		dip = (u8 *)&frame;
+
+	} else if (conn_type == DRM_ELD_CONN_TYPE_DP) {
+		memset(&dp_ai, 0, sizeof(dp_ai));
+		dp_ai.type	= 0x84;
+		dp_ai.len	= 0x1b;
+		dp_ai.ver	= 0x11 << 2;
+		dp_ai.CC02_CT47	= channels - 1;
+		dp_ai.CA	= 0;
+
+		dip = (u8 *)&dip;
+	} else {
+		dev_err(&hdac->hdac.dev, "Invalid connection type: %d\n", conn_type);
+		return -EIO;
+	}
 
 	/* stop infoframe transmission */
 	hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
@@ -231,9 +275,15 @@  static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
 
 	/*  Fill infoframe. Index auto-incremented */
 	hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(frame); i++)
-		snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
+	if (conn_type == 0) {
+		for (i = 0; i < sizeof(frame); i++)
+			snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
 				AC_VERB_SET_HDMI_DIP_DATA, dip[i]);
+	} else {
+		for (i = 0; i < sizeof(dp_ai); i++)
+			snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
+				AC_VERB_SET_HDMI_DIP_DATA, dip[i]);
+	}
 
 	/* Start infoframe */
 	hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);