| From b6e0e543f75729f207b9c72b0162ae61170635b2 Mon Sep 17 00:00:00 2001 |
| From: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Date: Sun, 21 Oct 2012 12:52:39 +0200 |
| Subject: drm/i915: clear the entire sdvo infoframe buffer |
| |
| From: Daniel Vetter <daniel.vetter@ffwll.ch> |
| |
| commit b6e0e543f75729f207b9c72b0162ae61170635b2 upstream. |
| |
| Like in the case of native hdmi, which is fixed already in |
| |
| commit adf00b26d18e1b3570451296e03bcb20e4798cdd |
| Author: Paulo Zanoni <paulo.r.zanoni@intel.com> |
| Date: Tue Sep 25 13:23:34 2012 -0300 |
| |
| drm/i915: make sure we write all the DIP data bytes |
| |
| 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. |
| |
| v3: I'm too stupid to paste the right commit. |
| |
| v4: Ben Hutchings noticed that I've failed to handle an underflow in |
| my loop logic, breaking it for i >= length + 8. Since I've just lost C |
| programmer license, use his solution. Also, make the frustrated 0-base |
| buffer size a notch more clear. |
| |
| Reported-and-tested-by: JΓΌrg Billeter <j@bitron.ch> |
| Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25732 |
| Cc: Paulo Zanoni <przanoni@gmail.com> |
| Cc: Ben Hutchings <ben@decadent.org.uk> |
| Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com> |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpu/drm/i915/intel_sdvo.c | 62 ++++++++++++++++++++++----------- |
| drivers/gpu/drm/i915/intel_sdvo_regs.h | 2 + |
| 2 files changed, 44 insertions(+), 20 deletions(-) |
| |
| --- a/drivers/gpu/drm/i915/intel_sdvo.c |
| +++ b/drivers/gpu/drm/i915/intel_sdvo.c |
| @@ -861,6 +861,45 @@ static void intel_sdvo_dump_hdmi_buf(str |
| } |
| #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 based, 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); |
| + if (i < length) |
| + memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); |
| + |
| + if (!intel_sdvo_set_value(intel_sdvo, |
| + SDVO_CMD_SET_HBUF_DATA, |
| + tmp, 8)) |
| + return false; |
| + } |
| + |
| + 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 = { |
| @@ -868,11 +907,7 @@ static bool intel_sdvo_set_avi_infoframe |
| .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); |
| |
| @@ -882,22 +917,9 @@ static bool intel_sdvo_set_avi_infoframe |
| 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) |
| --- 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 |