mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 07:31:29 +00:00
drm: handle HDMI 2.0 VICs in AVI info-frames
HDMI 1.4b support the CEA video modes as per range of CEA-861-D (VIC 1-64). For any other mode, the VIC filed in AVI infoframes should be 0. HDMI 2.0 sinks, support video modes range as per CEA-861-F spec, which is extended to (VIC 1-107). This patch adds a bool input variable, which indicates if the connected sink is a HDMI 2.0 sink or not. This will make sure that we don't pass a HDMI 2.0 VIC to a HDMI 1.4 sink. This patch touches all drm drivers, who are callers of this function drm_hdmi_avi_infoframe_from_display_mode but to make sure there is no change in current behavior, is_hdmi2 is kept as false. In case of I915 driver, this patch: - checks if the connected display is HDMI 2.0. - HDMI infoframes carry one of this two type of information: - VIC for 4K modes for HDMI 1.4 sinks - S3D information for S3D modes As CEA-861-F has already defined VICs for 4K videomodes, this patch doesn't allow sending HDMI infoframes for HDMI 2.0 sinks, until the mode is 3D. Cc: Ville Syrjala <ville.syrjala@linux.intel.com> Cc: Jose Abreu <jose.abreu@synopsys.com> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Daniel Vetter <daniel.vetter@intel.com> PS: This patch touches a few lines in few files, which were already above 80 char, so checkpatch gives 80 char warning again. - gpu/drm/omapdrm/omap_encoder.c - gpu/drm/i915/intel_sdvo.c V2: Rebase, Added r-b from Andrzej V3: Addressed review comment from Ville: - Do not send VICs in both AVI-IF and HDMI-IF send only one of it. V4: Rebase V5: Added r-b from Neil. Addressed review comments from Ville - Do not block HDMI vendor IF, instead check for VIC while handling AVI infoframes V6: Rebase V7: Rebase Reviewed-by: Andrzej Hajda <a.hajda@samsung.com> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-2-git-send-email-shashank.sharma@intel.com Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
This commit is contained in:
parent
3589211e9b
commit
0c1f528cb1
@ -1867,7 +1867,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder,
|
||||
dce_v10_0_audio_write_sad_regs(encoder);
|
||||
dce_v10_0_audio_write_latency_fields(encoder, mode);
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
if (err < 0) {
|
||||
DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
|
||||
return;
|
||||
|
@ -1851,7 +1851,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder,
|
||||
dce_v11_0_audio_write_sad_regs(encoder);
|
||||
dce_v11_0_audio_write_latency_fields(encoder, mode);
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
if (err < 0) {
|
||||
DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
|
||||
return;
|
||||
|
@ -1597,7 +1597,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder,
|
||||
ssize_t err;
|
||||
u32 tmp;
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
if (err < 0) {
|
||||
DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
|
||||
return;
|
||||
|
@ -1750,7 +1750,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
|
||||
dce_v8_0_audio_write_sad_regs(encoder);
|
||||
dce_v8_0_audio_write_latency_fields(encoder, mode);
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
if (err < 0) {
|
||||
DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
|
||||
return;
|
||||
|
@ -1097,7 +1097,8 @@ static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
|
||||
|
||||
mutex_lock(&anx78xx->lock);
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode);
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode,
|
||||
false);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
|
||||
goto unlock;
|
||||
|
@ -269,7 +269,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj);
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("couldn't fill AVI infoframe\n");
|
||||
return;
|
||||
|
@ -1317,7 +1317,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||
u8 val;
|
||||
|
||||
/* Initialise info frame from DRM mode */
|
||||
drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
|
||||
if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
|
||||
frame.colorspace = HDMI_COLORSPACE_YUV444;
|
||||
|
@ -4334,12 +4334,14 @@ EXPORT_SYMBOL(drm_set_preferred_mode);
|
||||
* data from a DRM display mode
|
||||
* @frame: HDMI AVI infoframe
|
||||
* @mode: DRM display mode
|
||||
* @is_hdmi2_sink: Sink is HDMI 2.0 compliant
|
||||
*
|
||||
* Return: 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int
|
||||
drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
|
||||
const struct drm_display_mode *mode)
|
||||
const struct drm_display_mode *mode,
|
||||
bool is_hdmi2_sink)
|
||||
{
|
||||
int err;
|
||||
|
||||
@ -4355,6 +4357,28 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
|
||||
|
||||
frame->video_code = drm_match_cea_mode(mode);
|
||||
|
||||
/*
|
||||
* HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
|
||||
* HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
|
||||
* have to make sure we dont break HDMI 1.4 sinks.
|
||||
*/
|
||||
if (!is_hdmi2_sink && frame->video_code > 64)
|
||||
frame->video_code = 0;
|
||||
|
||||
/*
|
||||
* HDMI spec says if a mode is found in HDMI 1.4b 4K modes
|
||||
* we should send its VIC in vendor infoframes, else send the
|
||||
* VIC in AVI infoframes. Lets check if this mode is present in
|
||||
* HDMI 1.4b 4K modes
|
||||
*/
|
||||
if (frame->video_code) {
|
||||
u8 vendor_if_vic = drm_match_hdmi_mode(mode);
|
||||
bool is_s3d = mode->flags & DRM_MODE_FLAG_3D_MASK;
|
||||
|
||||
if (drm_valid_hdmi_vic(vendor_if_vic) && !is_s3d)
|
||||
frame->video_code = 0;
|
||||
}
|
||||
|
||||
frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
|
||||
|
||||
/*
|
||||
|
@ -784,7 +784,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
|
||||
}
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
|
||||
&hdata->current_mode);
|
||||
&hdata->current_mode, false);
|
||||
if (!ret)
|
||||
ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
|
||||
if (ret > 0) {
|
||||
|
@ -712,7 +712,7 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
|
||||
{
|
||||
union hdmi_infoframe frame;
|
||||
|
||||
drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
|
||||
drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
|
||||
frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
|
||||
|
||||
tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
|
||||
|
@ -459,11 +459,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->base.adjusted_mode;
|
||||
struct drm_connector *connector = &intel_hdmi->attached_connector->base;
|
||||
bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
|
||||
union hdmi_infoframe frame;
|
||||
int ret;
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
|
||||
adjusted_mode);
|
||||
adjusted_mode,
|
||||
is_hdmi2_sink);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("couldn't fill AVI infoframe\n");
|
||||
return;
|
||||
|
@ -996,7 +996,8 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
ssize_t len;
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
|
||||
&pipe_config->base.adjusted_mode);
|
||||
&pipe_config->base.adjusted_mode,
|
||||
false);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("couldn't fill AVI infoframe\n");
|
||||
return false;
|
||||
|
@ -975,7 +975,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
|
||||
u8 buffer[17];
|
||||
ssize_t err;
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
if (err < 0) {
|
||||
dev_err(hdmi->dev,
|
||||
"Failed to get AVI infoframe from mode: %zd\n", err);
|
||||
|
@ -97,7 +97,7 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi)
|
||||
u32 val;
|
||||
int len;
|
||||
|
||||
drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
|
||||
drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
|
||||
|
||||
len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer));
|
||||
if (len < 0) {
|
||||
|
@ -2762,7 +2762,8 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
|
||||
if (!drm_detect_hdmi_monitor(nv_connector->edid))
|
||||
return;
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode);
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode,
|
||||
false);
|
||||
if (!ret) {
|
||||
/* We have an AVI InfoFrame, populate it to the display */
|
||||
args.pwr.avi_infoframe_length
|
||||
|
@ -85,7 +85,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
|
||||
if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
|
||||
struct hdmi_avi_infoframe avi;
|
||||
|
||||
r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
|
||||
r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
|
||||
false);
|
||||
if (r == 0)
|
||||
dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
|
||||
}
|
||||
|
@ -516,7 +516,7 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
|
||||
if (!connector)
|
||||
return -EINVAL;
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
if (err < 0) {
|
||||
DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
|
||||
return err;
|
||||
|
@ -294,7 +294,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
|
||||
union hdmi_infoframe frame;
|
||||
int rc;
|
||||
|
||||
rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
|
||||
rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
|
||||
|
||||
if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
|
||||
frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
|
||||
|
@ -434,7 +434,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -52,7 +52,7 @@ static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
|
||||
u8 buffer[17];
|
||||
int i, ret;
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("Failed to get infoframes from mode\n");
|
||||
return ret;
|
||||
|
@ -734,7 +734,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
|
||||
u8 buffer[17];
|
||||
ssize_t err;
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
if (err < 0) {
|
||||
dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
|
||||
return;
|
||||
|
@ -1904,7 +1904,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
|
||||
value &= ~INFOFRAME_CTRL_ENABLE;
|
||||
tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
|
||||
if (err < 0) {
|
||||
dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
|
||||
return err;
|
||||
|
@ -395,7 +395,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
|
||||
union hdmi_infoframe frame;
|
||||
int ret;
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("couldn't fill AVI infoframe\n");
|
||||
return;
|
||||
|
@ -124,7 +124,7 @@ static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
|
||||
union hdmi_infoframe frame;
|
||||
int ret;
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
|
||||
ret);
|
||||
|
@ -343,7 +343,8 @@ drm_load_edid_firmware(struct drm_connector *connector)
|
||||
|
||||
int
|
||||
drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
|
||||
const struct drm_display_mode *mode);
|
||||
const struct drm_display_mode *mode,
|
||||
bool is_hdmi2_sink);
|
||||
int
|
||||
drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
|
||||
const struct drm_display_mode *mode);
|
||||
|
Loading…
Reference in New Issue
Block a user