From patchwork Tue Jul 4 14:11:59 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Sharma, Shashank" X-Patchwork-Id: 9825145 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 16853603B5 for ; Tue, 4 Jul 2017 14:10:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 06F6C28497 for ; Tue, 4 Jul 2017 14:10:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EFB1A284FF; Tue, 4 Jul 2017 14:10:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6739327F88 for ; Tue, 4 Jul 2017 14:10:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 860F56E37D; Tue, 4 Jul 2017 14:09:25 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id F215B6E349; Tue, 4 Jul 2017 14:09:20 +0000 (UTC) Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 04 Jul 2017 07:09:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.40,307,1496127600"; d="scan'208";a="120727565" Received: from shashanks-linuxbox.iind.intel.com ([10.223.161.29]) by orsmga005.jf.intel.com with ESMTP; 04 Jul 2017 07:09:09 -0700 From: Shashank Sharma To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org Date: Tue, 4 Jul 2017 19:41:59 +0530 Message-Id: <1499177524-26292-13-git-send-email-shashank.sharma@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1499177524-26292-1-git-send-email-shashank.sharma@intel.com> References: <1499177524-26292-1-git-send-email-shashank.sharma@intel.com> Cc: Daniel Vetter Subject: [Intel-gfx] [PATCH v5 12/17] drm/i915: add compute-config for YCBCR outputs X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP This patch checks encoder level support for HDMI YCBCR outputs. HDMI output mode is a connector property, this patch checks if source and sink can support the HDMI output type selected by user. And if they both can, it commits the hdmi output type into crtc state, for further staging in driver. V2: Split the patch into two, kept helper functions in DRM layer. V3: Changed the compute_config function based on new DRM API. V4: Rebase V5: Rebase Cc: Ville Syrjala Cc: Daniel Vetter Cc: Ander Conselvan de Oliveira Signed-off-by: Shashank Sharma --- drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/i915/intel_drv.h | 3 ++ drivers/gpu/drm/i915/intel_hdmi.c | 93 ++++++++++++++++++++++++++++++++++-- 3 files changed, 94 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4e03ca6..082270d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11930,6 +11930,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, PIPE_CONF_CHECK_I(hdmi_scrambling); PIPE_CONF_CHECK_I(hdmi_high_tmds_clock_ratio); PIPE_CONF_CHECK_I(has_infoframe); + PIPE_CONF_CHECK_I(hdmi_output); PIPE_CONF_CHECK_I(has_audio); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d17a324..cc25d71 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -780,6 +780,9 @@ struct intel_crtc_state { /* HDMI High TMDS char rate ratio */ bool hdmi_high_tmds_clock_ratio; + + /* HDMI output type */ + enum drm_hdmi_output_type hdmi_output; }; struct intel_crtc { diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index cc0d100..3a07431 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1305,7 +1305,8 @@ intel_hdmi_mode_valid(struct drm_connector *connector, return status; } -static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) +static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state, + enum drm_hdmi_output_type hdmi_out) { struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); @@ -1317,6 +1318,16 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) if (HAS_GMCH_DISPLAY(dev_priv)) return false; + if (hdmi_out == DRM_HDMI_OUTPUT_YCBCR422) { + /* + * HDMI spec says YCBCR422 is 12bpc, but its not a deep + * color format. So respect the spec, and not allow this + * to be deep color + */ + DRM_DEBUG_KMS("Not allowing deep color for YCBCR422 output\n"); + return false; + } + /* * HDMI 12bpc affects the clocks, so it's only possible * when not cloning with other encoder types. @@ -1330,6 +1341,12 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) if (connector_state->crtc != crtc_state->base.crtc) continue; + if (hdmi_out == DRM_HDMI_OUTPUT_YCBCR420) { + if (!(info->hdmi.y420_dc_modes & + DRM_EDID_YCBCR420_DC_36)) + return false; + } + if ((info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) == 0) return false; } @@ -1342,6 +1359,65 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) return true; } +static u8 +intel_hdmi_get_src_output_support(struct drm_connector *connector) +{ + struct drm_i915_private *dev_priv = connector->dev->dev_private; + u8 supported_outputs = DRM_COLOR_FORMAT_RGB444; + + if (dev_priv->info.gen < 7) + return supported_outputs; + + /* Gen 7 and above support HDMI 1.4b outputs */ + supported_outputs |= DRM_COLOR_FORMAT_YCRCB444; + + if (IS_GEMINILAKE(dev_priv)) + supported_outputs |= DRM_COLOR_FORMAT_YCRCB420; + + return supported_outputs; +} + +static enum drm_hdmi_output_type +intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state, + struct intel_crtc_state *config, + int *clock_12bpc, int *clock_8bpc) +{ + struct drm_connector *connector = conn_state->connector; + struct drm_display_mode *mode = &config->base.adjusted_mode; + enum drm_hdmi_output_type type = conn_state->hdmi_output; + u8 src_output_cap = intel_hdmi_get_src_output_support(connector); + + /* + * Can we support any YCBCR output based on these parameters ? + * current source capabilities + + * current sink capabilities + + * given video mode + + * current user's choice for HDMI output (from connector property) + */ + type = drm_display_info_hdmi_output_type(&connector->display_info, + mode, type, src_output_cap); + if ((type == DRM_HDMI_OUTPUT_INVALID) || + (type == DRM_HDMI_OUTPUT_DEFAULT_RGB)) { + DRM_DEBUG_KMS("Can't support YCBCR output\n"); + return type; + } + + if (type == DRM_HDMI_OUTPUT_YCBCR420) { + + /* YCBCR420 TMDS rate requirement is half the pixel clock */ + config->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420; + config->port_clock /= 2; + *clock_12bpc /= 2; + *clock_8bpc /= 2; + + } + + /* Encoder is capable of this output, lets commit to CRTC */ + config->hdmi_output = type; + DRM_DEBUG_KMS("HDMI output: %s\n", drm_get_hdmi_output_name(type)); + return type; +} + bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) @@ -1349,13 +1425,15 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - struct drm_scdc *scdc = &conn_state->connector->display_info.hdmi.scdc; + struct drm_connector *connector = conn_state->connector; + struct drm_scdc *scdc = &connector->display_info.hdmi.scdc; struct intel_digital_connector_state *intel_conn_state = to_intel_digital_connector_state(conn_state); int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock; int clock_12bpc = clock_8bpc * 3 / 2; int desired_bpp; bool force_dvi = intel_conn_state->force_audio == HDMI_AUDIO_OFF_DVI; + enum drm_hdmi_output_type hdmi_out = conn_state->hdmi_output; pipe_config->has_hdmi_sink = !force_dvi && intel_hdmi->has_hdmi_sink; @@ -1379,6 +1457,15 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, clock_12bpc *= 2; } + /* Check if YCBCR HDMI output handling is required */ + hdmi_out = intel_hdmi_compute_ycbcr_config(conn_state, + pipe_config, &clock_12bpc, + &clock_8bpc); + if (hdmi_out == DRM_HDMI_OUTPUT_INVALID) { + DRM_ERROR("Can't support desired HDMI output\n"); + return false; + } + if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv)) pipe_config->has_pch_encoder = true; @@ -1398,7 +1485,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, */ if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink && !force_dvi && hdmi_port_clock_valid(intel_hdmi, clock_12bpc, true, force_dvi) == MODE_OK && - hdmi_12bpc_possible(pipe_config)) { + hdmi_12bpc_possible(pipe_config, hdmi_out)) { DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n"); desired_bpp = 12*3;