Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 478f544e authored by Subhransu S. Prusty's avatar Subhransu S. Prusty Committed by Mark Brown
Browse files

ASoC: hdac_hdmi: Add infoframe support for dp audio



For DP audio support, infoframe needs to be different. Based on
get_conn_type result we pack either HDMI or DP infoframe.

Signed-off-by: default avatarSubhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 148569fd
Loading
Loading
Loading
Loading
+64 −10
Original line number Diff line number Diff line
@@ -253,28 +253,76 @@ 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;
	u8 *dip = (u8 *)&frame;
	struct dp_audio_infoframe dp_ai;
	struct hdac_hdmi_priv *hdmi = hdac->private_data;
	struct hdac_hdmi_pin *pin;
	u8 *dip;
	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);

	switch (conn_type) {
	case 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;
		break;

	case 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 *)&dp_ai;
		break;

	default:
		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);
	snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
@@ -283,9 +331,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);
	if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
		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);