From patchwork Mon Jan 13 06:51:54 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ramalingam C X-Patchwork-Id: 3473741 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id E4203C02DC for ; Mon, 13 Jan 2014 06:52:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 09575200FE for ; Mon, 13 Jan 2014 06:52:15 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 2044B200D9 for ; Mon, 13 Jan 2014 06:52:14 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E8853FC9DF for ; Sun, 12 Jan 2014 22:52:13 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTP id A8F83FC9D3 for ; Sun, 12 Jan 2014 22:52:01 -0800 (PST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 12 Jan 2014 22:48:00 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.95,651,1384329600"; d="scan'208";a="437869768" Received: from ramaling-desktop.iind.intel.com ([10.223.25.129]) by orsmga001.jf.intel.com with ESMTP; 12 Jan 2014 22:51:59 -0800 From: Ramalingam C To: intel-gfx@lists.freedesktop.org, shashank.sharma@intel.com Date: Mon, 13 Jan 2014 12:21:54 +0530 Message-Id: <1389595914-23141-3-git-send-email-ramalingam.c@intel.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1389595914-23141-1-git-send-email-ramalingam.c@intel.com> References: <1389595914-23141-1-git-send-email-ramalingam.c@intel.com> Subject: [Intel-gfx] [PATCH 2/2] drm/i915: Optimize EDID retrival on detect and get_modes X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Spam-Status: No, score=-4.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Shashank Sharma Multiple forced detect and read modes calls come from user space for different connectors, which can be handled with connector status and previous detect event's cached EDID. With this approach for hot pluggable displays, EDID retrieval is required only when there is a real hot-plug events. This approach optimizes access to the DDC interface and also the CPU cycles burned by intel_hdmi_detect and intel_hdmi_get_modes. This patch contains: 1. A logic to optimize those multiple calls, by re-using cached data from previous detect and get_mode calls. 2. Store HDMI EDID, and re-use it in read modes. 3. Read live status reg to suppress spurious interrupts Change-Id: Ia46cbe346dcc18ef11381eabcb157c5bcfd51322 Signed-off-by: Shashank Sharma Signed-off-by: Ramalingam C --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_hdmi.c | 66 +++++++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0f7d94b..4f7f81f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -463,6 +463,8 @@ struct intel_hdmi { bool has_audio; enum hdmi_force_audio force_audio; bool rgb_quant_range_selectable; + struct edid *edid; + uint32_t edid_mode_count; void (*write_infoframe)(struct drm_encoder *encoder, enum hdmi_infoframe_type type, const void *frame, ssize_t len); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index faeae3a..2d008b7 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -994,7 +994,14 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, drm_get_connector_name(connector)); + /* If its forced detect call, dont read EDID again */ + if (force && intel_hdmi->edid) + return connector->status; + status = get_hdmi_hotplug_live_status(dev, intel_hdmi); + /* Suppress spurious IRQ, if current status is same as live status*/ + if (connector->status == status) + return connector->status; intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_audio = false; @@ -1015,11 +1022,22 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) drm_detect_monitor_audio(edid); intel_hdmi->rgb_quant_range_selectable = drm_rgb_quant_range_selectable(edid); + + /* Free previously saved EDID and save new one + for read modes. */ + kfree(intel_hdmi->edid); + intel_hdmi->edid = edid; + } else { + kfree(edid); + DRM_ERROR("EDID is not in digital form ?\n"); } - kfree(edid); } else { - status = connector_status_disconnected; + DRM_DEBUG_KMS("EDID read failed\n"); } + + if (intel_hdmi->edid == NULL) + status = connector_status_disconnected; + } if (status == connector_status_connected) { @@ -1027,6 +1045,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) intel_hdmi->has_audio = (intel_hdmi->force_audio == HDMI_AUDIO_ON); intel_encoder->type = INTEL_OUTPUT_HDMI; + } else { + kfree(intel_hdmi->edid); + intel_hdmi->edid = NULL; } return status; @@ -1036,14 +1057,44 @@ static int intel_hdmi_get_modes(struct drm_connector *connector) { struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct drm_i915_private *dev_priv = connector->dev->dev_private; + struct edid *edid = intel_hdmi->edid; + struct drm_display_mode *mode = NULL; + int count = 0; - /* We should parse the EDID data and find out if it's an HDMI sink so - * we can send audio to it. - */ + /* No need to read modes if panel is not connected */ + if (connector->status != connector_status_connected) + return 0; - return intel_ddc_get_modes(connector, + /* Need not read modes again if previously read modes are + available and display is consistent */ + if (intel_hdmi->edid) { + list_for_each_entry(mode, &connector->modes, head) { + if (mode) { + /* Setting the MODE_OK for all sanitized modes*/ + mode->status = MODE_OK; + count++; + } + } + /* If modes are availlable, no need to read again */ + if (count) + goto out; + } + + /* EDID was saved in detect, re-use that if available, avoid + reading EDID everytime */ + if (edid) { + drm_mode_connector_update_edid_property(connector, edid); + count = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + } else { + count = intel_ddc_get_modes(connector, intel_gmbus_get_adapter(dev_priv, - intel_hdmi->ddc_bus)); + intel_hdmi->ddc_bus)); + } + +out: + intel_hdmi->edid_mode_count = count; + return count; } static bool @@ -1381,6 +1432,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) intel_dig_port->port = port; intel_dig_port->hdmi.hdmi_reg = hdmi_reg; + intel_dig_port->hdmi.edid = NULL; intel_dig_port->dp.output_reg = 0; intel_hdmi_init_connector(intel_dig_port, intel_connector);