From patchwork Mon Jan 23 10:00:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrea Merello X-Patchwork-Id: 9532005 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 E14B36042F for ; Mon, 23 Jan 2017 10:00:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D2AF927D0C for ; Mon, 23 Jan 2017 10:00:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C783D27E3E; Mon, 23 Jan 2017 10:00:27 +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.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham 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 3E23027D0C for ; Mon, 23 Jan 2017 10:00:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 00B366E3CE; Mon, 23 Jan 2017 10:00:26 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wm0-x243.google.com (mail-wm0-x243.google.com [IPv6:2a00:1450:400c:c09::243]) by gabe.freedesktop.org (Postfix) with ESMTPS id D0C016E3CE for ; Mon, 23 Jan 2017 10:00:23 +0000 (UTC) Received: by mail-wm0-x243.google.com with SMTP id c85so25091758wmi.1 for ; Mon, 23 Jan 2017 02:00:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=0OVWhl+zUObvuWFJOeiAEkwvAQH2Z6tZnRmWww9WcPc=; b=PawCd4CyUHZJ/rclN/Y0NnMe9+436Gl8WoplnTxnBXzhSQyv5odS43+yOI/bJUxsr9 l036lU9R1JQU4jaVP+C0lYUT57cLfjqsG43lctiVC5X2yYbAn9xt7Lumc8Gl/VfTt0hM IKiaRzhzAGRdKbaH3UVkMUix47D39rH7jViM0Zo8voabIO4VG++UNuHBSIS/F8Yxjswl w6vBXyyWUN8RLQ/qczkdxsyVA/vmLcDbnbgXcQohYVFVA9c6HML2QRKFBxChlVWCK9P+ 3PGZWonoTYqFSMtSaPe8UBZYze4t3w3bVwZWG35YDFImACRdZSzV54XEjaycD557fuj5 hWdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=0OVWhl+zUObvuWFJOeiAEkwvAQH2Z6tZnRmWww9WcPc=; b=EyBhp1um6JbFVk5Dr548zTqJtSspBh7mdrzJU8FTyb/snmyZ+brT8k6Hcd9kyvYGLA UM7LOKfsdaCuL3rbYp/Z4vdvNExq8zSSjIECJFs8B4CtBPh9Nl0JXf6pQ1Ab3CsoPWLO 4ReV63XClA3+M4ReokOsBHvxRXhghQyJ2hwhD8IWzW/Ttfzfw8gRLPStPS4/4wGaBSD0 CeZhM12OkOht2vgIR5d0cOj2vBujwD34sAK9cscA/gsF4JDC/JWyVK615NILA0VVz/Zl JUv08h87viqJicifC/fLL+wPGsx2brE91ozk4s5zT1vtLAjefWZfEjnwYUfZlhj69k4l 7U5A== X-Gm-Message-State: AIkVDXJck8xKLJiRGGdm9OvLKAw7xvgKWY6yROGcd+CnA5yLsDX/1HE0KbsXFncAkTFXUw== X-Received: by 10.28.229.193 with SMTP id c184mr14312105wmh.83.1485165622255; Mon, 23 Jan 2017 02:00:22 -0800 (PST) Received: from NewMoon.iit.local ([90.147.180.254]) by smtp.googlemail.com with ESMTPSA id a13sm20392705wma.0.2017.01.23.02.00.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Jan 2017 02:00:21 -0800 (PST) From: Andrea Merello X-Google-Original-From: Andrea Merello To: dri-devel@lists.freedesktop.org Subject: [PATCH] drm/bridge: sii902x: fix get edid may fail Date: Mon, 23 Jan 2017 11:00:02 +0100 Message-Id: <1485165602-19264-1-git-send-email-andrea.merello@iit.it> X-Mailer: git-send-email 2.7.4 Cc: Andrea Merello , Andrea Merello X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Andrea Merello The standard DRM function to get the edid from the i2c bus performs (at least) two transfers. By experiments it seems that the sii9022a have problems with the 2nd I2C start, at least unless a wait is introduced detween the two transfers. So we perform one single I2C transfer, and if the transfer must be split, then we introduce a delay. Signed-off-by: Andrea Merello Cc: Andrea Merello Cc: Boris Brezillon Cc: Archit Taneja Cc: David Airlie --- drivers/gpu/drm/bridge/sii902x.c | 70 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index 9126d03..042d7e2 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -133,6 +133,62 @@ static const struct drm_connector_funcs sii902x_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; +#define DDC_SEGMENT_ADDR 0x30 +static int sii902x_do_probe_ddc_edid(void *data, u8 *buf, + unsigned int block, size_t len) +{ + struct i2c_adapter *adapter = data; + unsigned char start = block * EDID_LENGTH; + unsigned char segment = block >> 1; + unsigned char xfers = segment ? 3 : 2; + int ret, retries = 5; + + /* + * The core I2C driver will automatically retry the transfer if the + * adapter reports EAGAIN. However, we find that bit-banging transfers + * are susceptible to errors under a heavily loaded machine and + * generate spurious NAKs and timeouts. Retrying the transfer + * of the individual block a few times seems to overcome this. + */ + while (1) { + struct i2c_msg msgs[] = { + { + .addr = DDC_SEGMENT_ADDR, + .flags = 0, + .len = 1, + .buf = &segment, + }, { + .addr = DDC_ADDR, + .flags = 0, + .len = 1, + .buf = &start, + }, { + .addr = DDC_ADDR, + .flags = I2C_M_RD, + .len = len, + .buf = buf, + } + }; + + /* + * Avoid sending the segment addr to not upset non-compliant + * DDC monitors. + */ + ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers); + + if (ret == -ENXIO) { + DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n", + adapter->name); + break; + } + if (ret == xfers || --retries == 0) + break; + + udelay(100); + } + + return ret == xfers ? 0 : -1; +} static int sii902x_get_modes(struct drm_connector *connector) { struct sii902x *sii902x = connector_to_sii902x(connector); @@ -168,8 +224,20 @@ static int sii902x_get_modes(struct drm_connector *connector) if (ret) return ret; - edid = drm_get_edid(connector, sii902x->i2c->adapter); + /* drm_get_edid() runs two I2C transfers. The sii902x seems + * to have problem with the 2nd I2C start. A wait seems needed. + * So, we don't perform use drm_get_edid(). We don't perform + * the first "probe" transfer, and we use a custom block read + * function that, in case the trasfer is split, does introduce + * a delay. + */ + edid = drm_do_get_edid(connector, sii902x_do_probe_ddc_edid, + sii902x->i2c->adapter); + if (!edid) + return num; + drm_mode_connector_update_edid_property(connector, edid); + if (edid) { num = drm_add_edid_modes(connector, edid); kfree(edid);