diff mbox

drm/i915: clear the entire sdvo infoframe buffer

Message ID 1350747406-4898-1-git-send-email-daniel.vetter@ffwll.ch (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Vetter Oct. 20, 2012, 3:36 p.m. UTC
Like in the case of native hdmi, which is fixed already in

commit 29de6ce574870a0d3fd157afdbf51c0282e2bf63
Author: Damien Lespiau <damien.lespiau@intel.com>
Date:   Fri Oct 19 17:55:43 2012 +0100

    drm/i915: Don't program DSPCLK_GATE_D twice on IVB and VLV

we need to clear the entire sdvo buffer to avoid upsetting the
display.

Since infoframe buffer writing is now a bit more elaborate, extract it
into it's own function. This will be useful if we ever get around to
properly update the ELD for sdvo. Also #define proper names for the
two buffer indexes with fixed usage.

v2: Cite the right commit above, spotted by Paulo Zanoni.

Reported-and-tested-by: Jürg Billeter <j@bitron.ch>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25732
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_sdvo.c      |   64 ++++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_sdvo_regs.h |    2 +
 2 files changed, 46 insertions(+), 20 deletions(-)

Comments

Paulo Zanoni Oct. 20, 2012, 4:26 p.m. UTC | #1
Hi

2012/10/20 Daniel Vetter <daniel.vetter@ffwll.ch>:
> Like in the case of native hdmi, which is fixed already in
>
> commit 29de6ce574870a0d3fd157afdbf51c0282e2bf63
> Author: Damien Lespiau <damien.lespiau@intel.com>
> Date:   Fri Oct 19 17:55:43 2012 +0100
>
>     drm/i915: Don't program DSPCLK_GATE_D twice on IVB and VLV
>
> we need to clear the entire sdvo buffer to avoid upsetting the
> display.

This is not exactly the commit I mentioned... As far as I know,
Damien's commit does not fix any known HDMI bug.

>
> Since infoframe buffer writing is now a bit more elaborate, extract it
> into it's own function. This will be useful if we ever get around to
> properly update the ELD for sdvo. Also #define proper names for the
> two buffer indexes with fixed usage.
>
> v2: Cite the right commit above, spotted by Paulo Zanoni.
>
> Reported-and-tested-by: Jürg Billeter <j@bitron.ch>
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25732
> Cc: stable@vger.kernel.org
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_sdvo.c      |   64 ++++++++++++++++++++++----------
>  drivers/gpu/drm/i915/intel_sdvo_regs.h |    2 +
>  2 files changed, 46 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index d2e8c9f..4bc9c52 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -895,6 +895,47 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
>  }
>  #endif
>
> +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
> +                                      unsigned if_index, uint8_t tx_rate,
> +                                      uint8_t *data, unsigned length)
> +{
> +       uint8_t set_buf_index[2] = { if_index, 0 };
> +       uint8_t hbuf_size, tmp[8];
> +       int i;
> +
> +       if (!intel_sdvo_set_value(intel_sdvo,
> +                                 SDVO_CMD_SET_HBUF_INDEX,
> +                                 set_buf_index, 2))
> +               return false;
> +
> +       if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
> +                                 &hbuf_size, 1))
> +               return false;
> +
> +       /* Buffer size is 0 base, hooray! */
> +       hbuf_size++;
> +
> +       DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
> +                     if_index, length, hbuf_size);
> +
> +       for (i = 0; i < hbuf_size; i += 8) {
> +               memset(tmp, 0, 8);
> +               memcpy(tmp, data, min_t(unsigned, 8, length));
> +
> +               if (!intel_sdvo_set_value(intel_sdvo,
> +                                         SDVO_CMD_SET_HBUF_DATA,
> +                                         tmp, 8))
> +                       return false;
> +
> +               data += 8;
> +               length -= 8;
> +       }
> +
> +       return intel_sdvo_set_value(intel_sdvo,
> +                                   SDVO_CMD_SET_HBUF_TXRATE,
> +                                   &tx_rate, 1);
> +}
> +
>  static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
>  {
>         struct dip_infoframe avi_if = {
> @@ -902,11 +943,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
>                 .ver = DIP_VERSION_AVI,
>                 .len = DIP_LEN_AVI,
>         };
> -       uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
> -       uint8_t set_buf_index[2] = { 1, 0 };
>         uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
> -       uint64_t *data = (uint64_t *)sdvo_data;
> -       unsigned i;
>
>         intel_dip_infoframe_csum(&avi_if);
>
> @@ -916,22 +953,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
>         sdvo_data[3] = avi_if.checksum;
>         memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
>
> -       if (!intel_sdvo_set_value(intel_sdvo,
> -                                 SDVO_CMD_SET_HBUF_INDEX,
> -                                 set_buf_index, 2))
> -               return false;
> -
> -       for (i = 0; i < sizeof(sdvo_data); i += 8) {
> -               if (!intel_sdvo_set_value(intel_sdvo,
> -                                         SDVO_CMD_SET_HBUF_DATA,
> -                                         data, 8))
> -                       return false;
> -               data++;
> -       }
> -
> -       return intel_sdvo_set_value(intel_sdvo,
> -                                   SDVO_CMD_SET_HBUF_TXRATE,
> -                                   &tx_rate, 1);
> +       return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
> +                                         SDVO_HBUF_TX_VSYNC,
> +                                         sdvo_data, sizeof(sdvo_data));
>  }
>
>  static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
> diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h
> index 9d03014..770bdd6 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h
> +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h
> @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
>  #define SDVO_CMD_SET_AUDIO_STAT                0x91
>  #define SDVO_CMD_GET_AUDIO_STAT                0x92
>  #define SDVO_CMD_SET_HBUF_INDEX                0x93
> +  #define SDVO_HBUF_INDEX_ELD          0
> +  #define SDVO_HBUF_INDEX_AVI_IF       1
>  #define SDVO_CMD_GET_HBUF_INDEX                0x94
>  #define SDVO_CMD_GET_HBUF_INFO         0x95
>  #define SDVO_CMD_SET_HBUF_AV_SPLIT     0x96
> --
> 1.7.10.4
>
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d2e8c9f..4bc9c52 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -895,6 +895,47 @@  static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 }
 #endif
 
+static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
+				       unsigned if_index, uint8_t tx_rate,
+				       uint8_t *data, unsigned length)
+{
+	uint8_t set_buf_index[2] = { if_index, 0 };
+	uint8_t hbuf_size, tmp[8];
+	int i;
+
+	if (!intel_sdvo_set_value(intel_sdvo,
+				  SDVO_CMD_SET_HBUF_INDEX,
+				  set_buf_index, 2))
+		return false;
+
+	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
+				  &hbuf_size, 1))
+		return false;
+
+	/* Buffer size is 0 base, hooray! */
+	hbuf_size++;
+
+	DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
+		      if_index, length, hbuf_size);
+
+	for (i = 0; i < hbuf_size; i += 8) {
+		memset(tmp, 0, 8);
+		memcpy(tmp, data, min_t(unsigned, 8, length));
+
+		if (!intel_sdvo_set_value(intel_sdvo,
+					  SDVO_CMD_SET_HBUF_DATA,
+					  tmp, 8))
+			return false;
+
+		data += 8;
+		length -= 8;
+	}
+
+	return intel_sdvo_set_value(intel_sdvo,
+				    SDVO_CMD_SET_HBUF_TXRATE,
+				    &tx_rate, 1);
+}
+
 static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
 {
 	struct dip_infoframe avi_if = {
@@ -902,11 +943,7 @@  static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
 		.ver = DIP_VERSION_AVI,
 		.len = DIP_LEN_AVI,
 	};
-	uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
-	uint8_t set_buf_index[2] = { 1, 0 };
 	uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
-	uint64_t *data = (uint64_t *)sdvo_data;
-	unsigned i;
 
 	intel_dip_infoframe_csum(&avi_if);
 
@@ -916,22 +953,9 @@  static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
 	sdvo_data[3] = avi_if.checksum;
 	memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
 
-	if (!intel_sdvo_set_value(intel_sdvo,
-				  SDVO_CMD_SET_HBUF_INDEX,
-				  set_buf_index, 2))
-		return false;
-
-	for (i = 0; i < sizeof(sdvo_data); i += 8) {
-		if (!intel_sdvo_set_value(intel_sdvo,
-					  SDVO_CMD_SET_HBUF_DATA,
-					  data, 8))
-			return false;
-		data++;
-	}
-
-	return intel_sdvo_set_value(intel_sdvo,
-				    SDVO_CMD_SET_HBUF_TXRATE,
-				    &tx_rate, 1);
+	return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
+					  SDVO_HBUF_TX_VSYNC,
+					  sdvo_data, sizeof(sdvo_data));
 }
 
 static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h
index 9d03014..770bdd6 100644
--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h
+++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h
@@ -708,6 +708,8 @@  struct intel_sdvo_enhancements_arg {
 #define SDVO_CMD_SET_AUDIO_STAT		0x91
 #define SDVO_CMD_GET_AUDIO_STAT		0x92
 #define SDVO_CMD_SET_HBUF_INDEX		0x93
+  #define SDVO_HBUF_INDEX_ELD		0
+  #define SDVO_HBUF_INDEX_AVI_IF	1
 #define SDVO_CMD_GET_HBUF_INDEX		0x94
 #define SDVO_CMD_GET_HBUF_INFO		0x95
 #define SDVO_CMD_SET_HBUF_AV_SPLIT	0x96