Skip to content

Commit

Permalink
drm/edid: Don't send non-zero YQ in AVI infoframe for HDMI 1.x sinks
Browse files Browse the repository at this point in the history
Apparently some sinks look at the YQ bits even when receiving RGB,
and they get somehow confused when they see a non-zero YQ value.
So we can't just blindly follow CEA-861-F and set YQ to match the
RGB range.

Unfortunately there is no good way to tell whether the sink
designer claims to have read CEA-861-F. The CEA extension block
revision number has generally been stuck at 3 since forever,
and even a very recently manufactured sink might be based on
an old design so the manufacturing date doesn't seem like
something we can use. In lieu of better information let's
follow CEA-861-F only for HDMI 2.0 sinks, since HDMI 2.0 is
based on CEA-861-F. For HDMI 1.x sinks we'll always set YQ=0.

The alternative would of course be to always set YQ=0. And if
we ever encounter a HDMI 2.0+ sink with this bug that's what
we'll probably have to do.

Cc: stable@vger.kernel.org
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: Neil Kownacki <njkkow@gmail.com>
Reported-by: Neil Kownacki <njkkow@gmail.com>
Tested-by: Neil Kownacki <njkkow@gmail.com>
Fixes: fcc8a22 ("drm/edid: Set YQ bits in the AVI infoframe according to CEA-861-F")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101639
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171108152504.12596-1-ville.syrjala@linux.intel.com
Acked-by: Eric Anholt <eric@anholt.net>
  • Loading branch information
vsyrjala committed Nov 15, 2017
1 parent 253696c commit 9271c0c
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 5 deletions.
12 changes: 10 additions & 2 deletions drivers/gpu/drm/drm_edid.c
Original file line number Diff line number Diff line change
Expand Up @@ -4809,7 +4809,8 @@ void
drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
const struct drm_display_mode *mode,
enum hdmi_quantization_range rgb_quant_range,
bool rgb_quant_range_selectable)
bool rgb_quant_range_selectable,
bool is_hdmi2_sink)
{
/*
* CEA-861:
Expand All @@ -4833,8 +4834,15 @@ drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
* YQ-field to match the RGB Quantization Range being transmitted
* (e.g., when Limited Range RGB, set YQ=0 or when Full Range RGB,
* set YQ=1) and the Sink shall ignore the YQ-field."
*
* Unfortunate certain sinks (eg. VIZ Model 67/E261VA) get confused
* by non-zero YQ when receiving RGB. There doesn't seem to be any
* good way to tell which version of CEA-861 the sink supports, so
* we limit non-zero YQ to HDMI 2.0 sinks only as HDMI 2.0 is based
* on on CEA-861-F.
*/
if (rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED)
if (!is_hdmi2_sink ||
rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED)
frame->ycc_quantization_range =
HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
else
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/intel_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,8 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
crtc_state->limited_color_range ?
HDMI_QUANTIZATION_RANGE_LIMITED :
HDMI_QUANTIZATION_RANGE_FULL,
intel_hdmi->rgb_quant_range_selectable);
intel_hdmi->rgb_quant_range_selectable,
is_hdmi2_sink);

/* TODO: handle pixel repetition for YCBCR420 outputs */
intel_write_infoframe(encoder, crtc_state, &frame);
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/vc4/vc4_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,8 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
vc4_encoder->limited_rgb_range ?
HDMI_QUANTIZATION_RANGE_LIMITED :
HDMI_QUANTIZATION_RANGE_FULL,
vc4_encoder->rgb_range_selectable);
vc4_encoder->rgb_range_selectable,
false);

vc4_hdmi_write_infoframe(encoder, &frame);
}
Expand Down
3 changes: 2 additions & 1 deletion include/drm/drm_edid.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,8 @@ void
drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
const struct drm_display_mode *mode,
enum hdmi_quantization_range rgb_quant_range,
bool rgb_quant_range_selectable);
bool rgb_quant_range_selectable,
bool is_hdmi2_sink);

/**
* drm_eld_mnl - Get ELD monitor name length in bytes.
Expand Down

0 comments on commit 9271c0c

Please sign in to comment.