From patchwork Fri Aug 14 19:44:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 247742 Delivered-To: patch@linaro.org Received: by 2002:a92:cc90:0:0:0:0:0 with SMTP id x16csp637662ilo; Fri, 14 Aug 2020 12:45:19 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxsG1og6KthDfd1mB1baTtJkL8d4PtwCJDqZPjTsQdpbT9KtpPeF1T5XRN6l0a/ApY+T33d X-Received: by 2002:a17:90a:cc14:: with SMTP id b20mr3346323pju.1.1597434319241; Fri, 14 Aug 2020 12:45:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1597434319; cv=none; d=google.com; s=arc-20160816; b=Qp5QO8eLphw1JhVo+12s6srFaSynVohqTnPviyGx8kVSKS9KR0VmlQGgbzn5aEzX1h TftOh0RFzFLuF6W/6If02fSvgb4wTv7SpFNQbeBToiXs+9PqdpQWD9cg6wS1NvdenxbD wyPT7UYFyWTZgCIHLDYkb1XEy8MaDS8N7TMACcFVMOsRHxSYFp6zZseB1r5t0qDj4sIN IwYWEdn+kNf2S2HozDfCkx8p7P+JWnWN0StIbe+ROSm+zCyGvogUN/l5knAqh5KCN+m/ ylc9w5ejkOnhCIIX23fL03EaqsgPo9nYGd6NdbBV2VvO4pYxwQtbo/5b2Rg4nepyraX6 oL4g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:mime-version:message-id:date:subject:to:from :dkim-signature:delivered-to; bh=7R7DkAH/KegcfMeTeEpBLRee2132uDh1UNnNpKCTXrc=; b=fQppL9hLBQR3al65m+Y9DiHdjko4O7DqlQOtWMO5971fhAvkijcV/NdRnzaM9yYhKQ cPsG4mZ7SQSkmpcaVo41qFn6VHat+nNCpKB+7FZ7Z5UZckAWFEvUP3xmMMD6VLVcd1IK ycNPk3R12slQC0K3KQgTrnbvYFZx1mR73u+FvuOTd8D6TRtQjDxH+eb/Rxm1/TdWsj0Y pcQ3mZUD1qdx62dGgoV+8RQL9/OPoY9aNTRqguQdHSypoQyq14xO6S/FlugASr4Vs00f be2OFwo0kPdyWWEptAupewgnkya0Q6muaJhXnv/wguS1H1+V/dZS4SSeiFo7P6yDefGB HuLA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=caTRvB3i; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [131.252.210.177]) by mx.google.com with ESMTPS id r25si6908448pge.263.2020.08.14.12.45.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Aug 2020 12:45:19 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) client-ip=131.252.210.177; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=caTRvB3i; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 26D2F6EC0D; Fri, 14 Aug 2020 19:45:16 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-lj1-x244.google.com (mail-lj1-x244.google.com [IPv6:2a00:1450:4864:20::244]) by gabe.freedesktop.org (Postfix) with ESMTPS id C76A66EC0D for ; Fri, 14 Aug 2020 19:45:15 +0000 (UTC) Received: by mail-lj1-x244.google.com with SMTP id t6so11100003ljk.9 for ; Fri, 14 Aug 2020 12:45:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=KsFn0c7QdtWCb3DsEhl/Wuyowc273VuyU1hI8J52hq0=; b=caTRvB3i0SvVbFZoQGsJ4z/ityAKFAfmcwWcW3TKUjnm5T4qt7zr/3nKA30U7lNWkA L4gJypj+EpQA6I0sNEfHUm19XmUhgKkA3p44Ip17Www43aUJ9mu3QKcOCm0Ryf7M0saj n4+YlNMu/7lzvTWV9v3+DnUcatqS/jm0JRub9rZKTXMCMy/00HkMcizoXd3F6s0jYVT9 O4qeI7CAu5rao5eAVk1qa0uiMMQyKZ6eyg+XNKlFI/DXly67QUkchkjkpxOqs1zxs987 emTdBfdIHdE6fZYpC+e072+RHpOvGB9oEON9v8XExOI7tnOTqjiUGrC+Fgp4/n1awmmp AopA== 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:mime-version :content-transfer-encoding; bh=KsFn0c7QdtWCb3DsEhl/Wuyowc273VuyU1hI8J52hq0=; b=D6zt8IKjD0aZQ/pa2RDnUKmJ2956RSDlAFGEd5oPPCnJdzo/jZmY2kk/JUhJ97lIlP 6z+TEE3xRv/dDdjWB7TtrGMu5wv7TqJUxzfUfKUfwV5E9kqyRat5GexbOkjceleAa85e pVpHM2g53ETp8oRJgPvkVF8/Xi9YbQKpieANs5ruIDsSa3VVp9fJgoHve60HFQ9korkb 4IKe2hyfEO37uGyEVNd4wmC3Kc2zgFYExQENKemz/Ic3uXhLsIHw3yDfqJBitMgYajOt 74phIr0odPnSQ8pEIaPaGnDXRUmEFFchXWrFilcjiPEk+xvTvLXxosHXYdvfNpu1dpPD u1OQ== X-Gm-Message-State: AOAM533Wul4/5LnGUzgtjDJPQH5ew+M+G1/iCqLASALqpp+9WmbDmTcr r6U3/ycjf0S3Ohu+n3HmtmYFfD7dtGaHDA== X-Received: by 2002:a2e:9a15:: with SMTP id o21mr1969351lji.419.1597434313776; Fri, 14 Aug 2020 12:45:13 -0700 (PDT) Received: from localhost.bredbandsbolaget (c-92d7225c.014-348-6c756e10.bbcust.telenor.se. [92.34.215.146]) by smtp.gmail.com with ESMTPSA id y16sm1938847ljg.21.2020.08.14.12.45.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Aug 2020 12:45:12 -0700 (PDT) From: Linus Walleij To: dri-devel@lists.freedesktop.org, Maarten Lankhorst , Maxime Ripard , Sean Paul Subject: [PATCH v2] drm/mcde: Retry DSI read/write transactions Date: Fri, 14 Aug 2020 21:44:51 +0200 Message-Id: <20200814194451.3494294-1-linus.walleij@linaro.org> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stephan Gerhold , linux-arm-kernel@lists.infradead.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The vendor driver makes a few retries on read DSI transactions, something that is needed especially in case of read (such as reading the panel MTP ID) while the panel is running in video mode. This happens on the Samsung s6e63m0 panel on the Golden device. Retry reads and writes alike three times. Cc: Stephan Gerhold Signed-off-by: Linus Walleij --- ChangeLog v1->v2: - Retry three times. - Only retry the actual command transmission like the vendor driver does, no need to set up all registers and do checks all over. Break out a part of the mcde_dsi_host_transfer() function to achieve this. --- drivers/gpu/drm/mcde/mcde_dsi.c | 158 +++++++++++++++++++------------- 1 file changed, 92 insertions(+), 66 deletions(-) -- 2.26.2 _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel Reviewed-by: Stephan Gerhold diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c index 4ce8cc5f0be2..b3c5d3cbda92 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi.c +++ b/drivers/gpu/drm/mcde/mcde_dsi.c @@ -208,79 +208,16 @@ static int mcde_dsi_host_detach(struct mipi_dsi_host *host, (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \ (type == MIPI_DSI_DCS_READ)) -static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, - const struct mipi_dsi_msg *msg) +static int mcde_dsi_execute_transfer(struct mcde_dsi *d, + const struct mipi_dsi_msg *msg) { - struct mcde_dsi *d = host_to_mcde_dsi(host); const u32 loop_delay_us = 10; /* us */ - const u8 *tx = msg->tx_buf; u32 loop_counter; size_t txlen = msg->tx_len; size_t rxlen = msg->rx_len; + int i; u32 val; int ret; - int i; - - if (txlen > 16) { - dev_err(d->dev, - "dunno how to write more than 16 bytes yet\n"); - return -EIO; - } - if (rxlen > 4) { - dev_err(d->dev, - "dunno how to read more than 4 bytes yet\n"); - return -EIO; - } - - dev_dbg(d->dev, - "message to channel %d, write %zd bytes read %zd bytes\n", - msg->channel, txlen, rxlen); - - /* Command "nature" */ - if (MCDE_DSI_HOST_IS_READ(msg->type)) - /* MCTL_MAIN_DATA_CTL already set up */ - val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_READ; - else - val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_WRITE; - /* - * More than 2 bytes will not fit in a single packet, so it's - * time to set the "long not short" bit. One byte is used by - * the MIPI DCS command leaving just one byte for the payload - * in a short package. - */ - if (mipi_dsi_packet_format_is_long(msg->type)) - val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT; - val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT; - val |= txlen << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT; - val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN; - val |= msg->type << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT; - writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS); - - /* MIPI DCS command is part of the data */ - if (txlen > 0) { - val = 0; - for (i = 0; i < 4 && i < txlen; i++) - val |= tx[i] << (i * 8); - } - writel(val, d->regs + DSI_DIRECT_CMD_WRDAT0); - if (txlen > 4) { - val = 0; - for (i = 0; i < 4 && (i + 4) < txlen; i++) - val |= tx[i + 4] << (i * 8); - writel(val, d->regs + DSI_DIRECT_CMD_WRDAT1); - } - if (txlen > 8) { - val = 0; - for (i = 0; i < 4 && (i + 8) < txlen; i++) - val |= tx[i + 8] << (i * 8); - writel(val, d->regs + DSI_DIRECT_CMD_WRDAT2); - } - if (txlen > 12) { - val = 0; - for (i = 0; i < 4 && (i + 12) < txlen; i++) - val |= tx[i + 12] << (i * 8); - writel(val, d->regs + DSI_DIRECT_CMD_WRDAT3); - } writel(~0, d->regs + DSI_DIRECT_CMD_STS_CLR); writel(~0, d->regs + DSI_CMD_MODE_STS_CLR); @@ -297,6 +234,7 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, usleep_range(loop_delay_us, (loop_delay_us * 3) / 2); if (!loop_counter) { dev_err(d->dev, "DSI read timeout!\n"); + /* Set exit code and retry */ return -ETIME; } } else { @@ -307,6 +245,7 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, usleep_range(loop_delay_us, (loop_delay_us * 3) / 2); if (!loop_counter) { + /* Set exit code and retry */ dev_err(d->dev, "DSI write timeout!\n"); return -ETIME; } @@ -348,6 +287,93 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, ret = rdsz; } + /* Successful transmission */ + return ret; +} + +static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct mcde_dsi *d = host_to_mcde_dsi(host); + const u8 *tx = msg->tx_buf; + size_t txlen = msg->tx_len; + size_t rxlen = msg->rx_len; + unsigned int retries = 0; + u32 val; + int ret; + int i; + + if (txlen > 16) { + dev_err(d->dev, + "dunno how to write more than 16 bytes yet\n"); + return -EIO; + } + if (rxlen > 4) { + dev_err(d->dev, + "dunno how to read more than 4 bytes yet\n"); + return -EIO; + } + + dev_dbg(d->dev, + "message to channel %d, write %zd bytes read %zd bytes\n", + msg->channel, txlen, rxlen); + + /* Command "nature" */ + if (MCDE_DSI_HOST_IS_READ(msg->type)) + /* MCTL_MAIN_DATA_CTL already set up */ + val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_READ; + else + val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_WRITE; + /* + * More than 2 bytes will not fit in a single packet, so it's + * time to set the "long not short" bit. One byte is used by + * the MIPI DCS command leaving just one byte for the payload + * in a short package. + */ + if (mipi_dsi_packet_format_is_long(msg->type)) + val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT; + val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT; + val |= txlen << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT; + val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN; + val |= msg->type << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT; + writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS); + + /* MIPI DCS command is part of the data */ + if (txlen > 0) { + val = 0; + for (i = 0; i < 4 && i < txlen; i++) + val |= tx[i] << (i * 8); + } + writel(val, d->regs + DSI_DIRECT_CMD_WRDAT0); + if (txlen > 4) { + val = 0; + for (i = 0; i < 4 && (i + 4) < txlen; i++) + val |= tx[i + 4] << (i * 8); + writel(val, d->regs + DSI_DIRECT_CMD_WRDAT1); + } + if (txlen > 8) { + val = 0; + for (i = 0; i < 4 && (i + 8) < txlen; i++) + val |= tx[i + 8] << (i * 8); + writel(val, d->regs + DSI_DIRECT_CMD_WRDAT2); + } + if (txlen > 12) { + val = 0; + for (i = 0; i < 4 && (i + 12) < txlen; i++) + val |= tx[i + 12] << (i * 8); + writel(val, d->regs + DSI_DIRECT_CMD_WRDAT3); + } + + while (retries < 3) { + ret = mcde_dsi_execute_transfer(d, msg); + if (ret >= 0) + break; + retries++; + } + if (ret < 0 && retries) + dev_err(d->dev, "gave up after %d retries\n", retries); + + /* Clear any errors */ writel(~0, d->regs + DSI_DIRECT_CMD_STS_CLR); writel(~0, d->regs + DSI_CMD_MODE_STS_CLR);