All of lore.kernel.org
 help / color / mirror / Atom feed
From: "David Härdeman" <david@hardeman.nu>
To: intel-gfx@lists.freedesktop.org
Cc: jesse.barnes@intel.com
Subject: [PATCH] i915: enable AVI infoframe for intel_hdmi.c
Date: Thu, 09 Sep 2010 00:52:17 +0200	[thread overview]
Message-ID: <20100908225217.6870.54888.stgit@localhost.localdomain> (raw)

This patch enables the sending of AVI infoframes in
drivers/gpu/drm/i915/intel_hdmi.c.

My receiver currently loses sync when the HDMI output on my computer
(DG45FC motherboard) is switched from 800x600 (the BIOS resolution) to
1920x1080 as part of the boot. Fixable by switching inputs on the receiver
a couple of times.

With this patch, my receiver has not lost sync yet (> 40 tries).

I'm not sure that the general approach is sound, which is why I'm sending
this out for some feedback and review (in particular, is the SDVOB and SDVOC
handling in intel_hdmi_set_avi_infoframe() correct?).

Regards,
David Härdeman
---
 drivers/gpu/drm/i915/i915_reg.h   |   16 +++++++
 drivers/gpu/drm/i915/intel_hdmi.c |   90 +++++++++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 67e3ec1..6c2d9a6 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1330,6 +1330,22 @@
 #define   LVDS_B0B3_POWER_DOWN		(0 << 2)
 #define   LVDS_B0B3_POWER_UP		(3 << 2)
 
+/* Video Data Island Packet control */
+#define VIDEO_DIP_DATA		0x61178
+#define VIDEO_DIP_CTL		0x61170
+#define   VIDEO_DIP_ENABLE		(1 << 31)
+#define   VIDEO_DIP_PORT_B		(1 << 29)
+#define   VIDEO_DIP_PORT_C		(2 << 29)
+#define   VIDEO_DIP_ENABLE_AVI		(1 << 21)
+#define   VIDEO_DIP_ENABLE_VENDOR	(2 << 21)
+#define   VIDEO_DIP_ENABLE_SPD		(8 << 21)
+#define   VIDEO_DIP_SELECT_AVI		(0 << 19)
+#define   VIDEO_DIP_SELECT_VENDOR	(1 << 19)
+#define   VIDEO_DIP_SELECT_SPD		(3 << 19)
+#define   VIDEO_DIP_FREQ_ONCE		(0 << 16)
+#define   VIDEO_DIP_FREQ_VSYNC		(1 << 16)
+#define   VIDEO_DIP_FREQ_2VSYNC		(2 << 16)
+
 /* Panel power sequencing */
 #define PP_STATUS	0x61200
 #define   PP_ON		(1 << 31)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index ccd4c97..e3a92c2 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -48,6 +48,93 @@ static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
 	return container_of(enc_to_intel_encoder(encoder), struct intel_hdmi, base);
 }
 
+#define DIP_TYPE_AVI    0x82
+#define DIP_VERSION_AVI 0x2
+#define DIP_LEN_AVI     13
+
+struct dip_avi_infoframe {
+	uint8_t type;           /* HB0 */
+	uint8_t ver;            /* HB1 */
+	uint8_t len;            /* HB2 - body len, not including checksum */
+	uint8_t ecc;            /* HW specific, not part of the infoframe */
+	uint8_t checksum;       /* PB0 */
+	uint8_t Y_A_B_S;        /* PB1 - Y 6:5, A 4:4, B 3:2, S 1:0 */
+	uint8_t C_M_R;          /* PB2 - C 7:6, M 5:4, R 3:0 */
+	uint8_t ITC_EC_Q_SC;    /* PB3 - ITC 7:7, EC 6:4, Q 3:2, SC 1:0 */
+	uint8_t VIC;            /* PB4 - VIC 6:0 */
+	uint8_t PR;             /* PB5 - PR 3:0 */
+	/* PB6 - PB13 */
+	uint16_t top_bar_end;
+	uint16_t bottom_bar_start;
+	uint16_t left_bar_end;
+	uint16_t right_bar_start;
+	/* Pad to 32-bit */
+	uint16_t padding;
+} __attribute__((packed));
+
+static void intel_hdmi_calc_csum(struct dip_avi_infoframe *avi_if)
+{
+	uint8_t *data = (uint8_t *)avi_if;
+	uint8_t sum = 0;
+	unsigned i;
+
+	avi_if->checksum = 0;
+	avi_if->ecc = 0;
+	avi_if->padding = 0;
+
+	for (i = 0; i < sizeof(*avi_if); i++)
+		sum += data[i];
+
+	avi_if->checksum = 0x100 - sum;
+}
+static void intel_hdmi_write_avi_infoframe(struct drm_encoder *encoder,
+					   struct dip_avi_infoframe *avi_if)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 *data = (u32 *)avi_if;
+	unsigned i;
+
+	for (i = 0; i < sizeof(*avi_if); i += 4) {
+		I915_WRITE(VIDEO_DIP_DATA, *data);
+		data++;
+	}
+
+}
+
+static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
+{
+	struct dip_avi_infoframe avi_if = {
+		.type = DIP_TYPE_AVI,
+		.ver = DIP_VERSION_AVI,
+		.len = DIP_LEN_AVI,
+		.Y_A_B_S = 0x02,
+		.C_M_R = 0x28,
+	};
+	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	u32 port;
+
+	if (!intel_hdmi->has_hdmi_sink)
+		return;
+
+	if (intel_hdmi->sdvox_reg == SDVOB)
+		port = VIDEO_DIP_PORT_B;
+	else if (intel_hdmi->sdvox_reg == SDVOC)
+		port = VIDEO_DIP_PORT_C;
+	else
+		return;
+
+	intel_hdmi_calc_csum(&avi_if);
+	I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port | VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC);
+	POSTING_READ(VIDEO_DIP_ENABLE);
+	intel_hdmi_write_avi_infoframe(encoder, &avi_if);
+	I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port | VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC);
+	POSTING_READ(VIDEO_DIP_ENABLE);
+}
+
+
 static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
@@ -67,6 +154,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 
 	if (intel_hdmi->has_hdmi_sink) {
 		sdvox |= SDVO_AUDIO_ENABLE;
+		sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
 		if (HAS_PCH_CPT(dev))
 			sdvox |= HDMI_MODE_SELECT;
 	}
@@ -80,6 +168,8 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 
 	I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
 	POSTING_READ(intel_hdmi->sdvox_reg);
+
+	intel_hdmi_set_avi_infoframe(encoder);
 }
 
 static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

             reply	other threads:[~2010-09-08 22:59 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-08 22:52 David Härdeman [this message]
2010-09-08 23:26 ` Chris Wilson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100908225217.6870.54888.stgit@localhost.localdomain \
    --to=david@hardeman.nu \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jesse.barnes@intel.com \
    --subject='Re: [PATCH] i915: enable AVI infoframe for intel_hdmi.c' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.