Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp3003786ybi; Mon, 17 Jun 2019 14:28:34 -0700 (PDT) X-Google-Smtp-Source: APXvYqwh+5fnMXgr0gFYXOk3w9fUfbLD/Lnql1snfY0f9Skg7cwGvHFaWFx13ULsXkEs+bidcCUP X-Received: by 2002:a62:b40a:: with SMTP id h10mr117427607pfn.216.1560806913924; Mon, 17 Jun 2019 14:28:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560806913; cv=none; d=google.com; s=arc-20160816; b=gc1Qqmun1EzN9EIHsd2ezI1CBEdLg3sUyCIEGUYYOXbcH3sy/C0S+dQEoq43EKh8av kybqy/oB2YO81xWdgRSPknZ/rwh8oR5d8evhjW1h6XJpfEgjb+PxaT/wsk50v77BuUXM n748QmskI3RcQFgjRNZ+YSmVimD3BJeewD3RHkeTQUOCObLw2+8I7if3xCcxOKrV86sQ PaWV225LMAUyMgPVBX0QALxyqGv8ecVerWzTzTilQCriC975LbRM/R2Wlck8U55dlglC 1t6jAMTLr666Bg9MU3aoN1aSYQ+g+FQovYWqpTnaLw8PNbhm/8Tf8nKm3WNj+4qBkBxG 6Spw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=JA1iiML8+sw/LmUDQv+tW/nkC92n43KM3EAK/jl29zQ=; b=cpMamH4iqNbBQbz0+wz0HmnF7oKxRsER/+7YuvhTUdlPKn43+CzEDjAdY9Tr6gO6E6 VehB+AavVdMMIbzPJvoMUsN48PrRezszlfxrwW/qBmp5wBOcIVJXVG2BAinobRKX7d6g ql1ge7yPOQUOlJoW6VqOcC3atGa5OBdkCB1qqV/VBQfvw/BsFsLWLdhiosXpJnQfq5yE 235zv0QaSn48ClgyRnt6tEqv7Au9XbEmu1wjaIL2TKIak2q9bo6R+6OM07Qopbg5D21X 6QCLNLAjlaIB3Bny4X/fm+oZje2+N2O2R5oLUcBK7owDWNqWvDd7eeDbQAb0hrAjArjb MkrQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=WmmtQykI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q26si11724846pgl.114.2019.06.17.14.28.18; Mon, 17 Jun 2019 14:28:33 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=WmmtQykI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730431AbfFQV1k (ORCPT + 99 others); Mon, 17 Jun 2019 17:27:40 -0400 Received: from mail.kernel.org ([198.145.29.99]:54650 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730419AbfFQV1j (ORCPT ); Mon, 17 Jun 2019 17:27:39 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id EDE552070B; Mon, 17 Jun 2019 21:27:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1560806857; bh=saiZy8z1Sk7dEyBsaCG/Gcy8sC/pf67bUjMRPIYC7iQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WmmtQykIRnyq+vXSZR+GzQH8hogxxNTkI21+OtZ48TvUVzzf7NWAQfgXyB3O3O7Ho bDPYkUPO5pGF4D7L14JDIl2+oGxy0dVkBvH6PldXyOhiITrrgis3eR+EAC1ufumbP3 87MJDSiAMtE1Ev5VGSlVtebJeifrp5ceKuwHw3zI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Paul Wise , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Daniel Vetter , =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= , Harish Chegondi , Jani Nikula Subject: [PATCH 4.19 74/75] drm: add fallback override/firmware EDID modes workaround Date: Mon, 17 Jun 2019 23:10:25 +0200 Message-Id: <20190617210756.179341513@linuxfoundation.org> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190617210752.799453599@linuxfoundation.org> References: <20190617210752.799453599@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jani Nikula commit 48eaeb7664c76139438724d520a1ea4a84a3ed92 upstream. We've moved the override and firmware EDID (simply "override EDID" from now on) handling to the low level drm_do_get_edid() function in order to transparently use the override throughout the stack. The idea is that you get the override EDID via the ->get_modes() hook. Unfortunately, there are scenarios where the DDC probe in drm_get_edid() called via ->get_modes() fails, although the preceding ->detect() succeeds. In the case reported by Paul Wise, the ->detect() hook, intel_crt_detect(), relies on hotplug detect, bypassing the DDC. In the case reported by Ilpo Järvinen, there is no ->detect() hook, which is interpreted as connected. The subsequent DDC probe reached via ->get_modes() fails, and we don't even look at the override EDID, resulting in no modes being added. Because drm_get_edid() is used via ->detect() all over the place, we can't trivially remove the DDC probe, as it leads to override EDID effectively meaning connector forcing. The goal is that connector forcing and override EDID remain orthogonal. Generally, the underlying problem here is the conflation of ->detect() and ->get_modes() via drm_get_edid(). The former should just detect, and the latter should just get the modes, typically via reading the EDID. As long as drm_get_edid() is used in ->detect(), it needs to retain the DDC probe. Or such users need to have a separate DDC probe step first. The EDID caching between ->detect() and ->get_modes() done by some drivers is a further complication that prevents us from making drm_do_get_edid() adapt to the two cases. Work around the regression by falling back to a separate attempt at getting the override EDID at drm_helper_probe_single_connector_modes() level. With a working DDC and override EDID, it'll never be called; the override EDID will come via ->get_modes(). There will still be a failing DDC probe attempt in the cases that require the fallback. v2: - Call drm_connector_update_edid_property (Paul) - Update commit message about EDID caching (Daniel) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107583 Reported-by: Paul Wise Cc: Paul Wise Reported-by: Ilpo Järvinen Cc: Ilpo Järvinen Suggested-by: Daniel Vetter Fixes: 53fd40a90f3c ("drm: handle override and firmware EDID at drm_do_get_edid() level") Cc: # v4.15+ 56a2b7f2a39a drm/edid: abstract override/firmware EDID retrieval Cc: # v4.15+ Cc: Daniel Vetter Cc: Ville Syrjälä Cc: Harish Chegondi Tested-by: Paul Wise Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20190610093054.28445-1-jani.nikula@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_edid.c | 30 ++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_probe_helper.c | 7 +++++++ include/drm/drm_edid.h | 1 + 3 files changed, 38 insertions(+) --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1595,6 +1595,36 @@ static struct edid *drm_get_override_edi } /** + * drm_add_override_edid_modes - add modes from override/firmware EDID + * @connector: connector we're probing + * + * Add modes from the override/firmware EDID, if available. Only to be used from + * drm_helper_probe_single_connector_modes() as a fallback for when DDC probe + * failed during drm_get_edid() and caused the override/firmware EDID to be + * skipped. + * + * Return: The number of modes added or 0 if we couldn't find any. + */ +int drm_add_override_edid_modes(struct drm_connector *connector) +{ + struct edid *override; + int num_modes = 0; + + override = drm_get_override_edid(connector); + if (override) { + drm_connector_update_edid_property(connector, override); + num_modes = drm_add_edid_modes(connector, override); + kfree(override); + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] adding %d modes via fallback override/firmware EDID\n", + connector->base.id, connector->name, num_modes); + } + + return num_modes; +} +EXPORT_SYMBOL(drm_add_override_edid_modes); + +/** * drm_do_get_edid - get EDID data using a custom EDID block read function * @connector: connector we're probing * @get_edid_block: EDID block read function --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -479,6 +479,13 @@ retry: count = (*connector_funcs->get_modes)(connector); + /* + * Fallback for when DDC probe failed in drm_get_edid() and thus skipped + * override/firmware EDID. + */ + if (count == 0 && connector->status == connector_status_connected) + count = drm_add_override_edid_modes(connector); + if (count == 0 && connector->status == connector_status_connected) count = drm_add_modes_noedid(connector, 1024, 768); count += drm_helper_probe_add_cmdline_mode(connector); --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -466,6 +466,7 @@ struct edid *drm_get_edid_switcheroo(str struct i2c_adapter *adapter); struct edid *drm_edid_duplicate(const struct edid *edid); int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); +int drm_add_override_edid_modes(struct drm_connector *connector); u8 drm_match_cea_mode(const struct drm_display_mode *to_match); enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);