From patchwork Mon Nov 11 12:00:35 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 3167221 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 68ABA9F39E for ; Mon, 11 Nov 2013 12:01:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2033C201F9 for ; Mon, 11 Nov 2013 12:01:15 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 66A8C201F7 for ; Mon, 11 Nov 2013 12:01:10 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1D996FABEB; Mon, 11 Nov 2013 04:01:06 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-bk0-f45.google.com (mail-bk0-f45.google.com [209.85.214.45]) by gabe.freedesktop.org (Postfix) with ESMTP id A18FCFABEA for ; Mon, 11 Nov 2013 04:00:59 -0800 (PST) Received: by mail-bk0-f45.google.com with SMTP id r7so1671280bkg.32 for ; Mon, 11 Nov 2013 04:00:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references; bh=yadUXSC3DNv7bBBhNAHee0epfOpczKrnGQVPzHsVr9Q=; b=0Ru4kRXubS0EBrT5R8vz2J79Llj6XFaq3sHQgesDsqr8zDxFvR1EzRccO851juIl1j /IUFn6QYXOQ8s0wzRTQaO7rbZpoWX0+jbqMndoJICxRqcn88GIT8ezi8hdkGNGokjIHJ aIy9i+002FEqDudn+++LTWHKmaNpIkNhQkvGpNzpoVc2hsiKmHXDW3w3V/GjfE0Ppjpl 0PxnKgocEMt4stmQvmJclJbX1v/xXSHzTEBsL8YnzqJ9feMTaJr+1LKr7APsrea9/eDL t8al4cPSApxa1d4CgqsdMBLiRL9b/kOE5zSUwinBsE1YCfOBVdUxEl6ggHgyybSX1VXO 5zeQ== X-Received: by 10.204.105.198 with SMTP id u6mr21118617bko.19.1384171258706; Mon, 11 Nov 2013 04:00:58 -0800 (PST) Received: from localhost (port-13884.pppoe.wtnet.de. [84.46.54.114]) by mx.google.com with ESMTPSA id l9sm14163719bkg.0.2013.11.11.04.00.57 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Nov 2013 04:00:58 -0800 (PST) From: Thierry Reding To: dri-devel@lists.freedesktop.org Subject: [PATCH v3 7/7] WIP: drm/tegra: Implement DSI transfers Date: Mon, 11 Nov 2013 13:00:35 +0100 Message-Id: <1384171235-2498-8-git-send-email-treding@nvidia.com> X-Mailer: git-send-email 1.8.4.2 In-Reply-To: <1384171235-2498-1-git-send-email-treding@nvidia.com> References: <1384171235-2498-1-git-send-email-treding@nvidia.com> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dsi.c | 147 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index effd0b5a5554..a100719b3d0c 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -774,6 +774,131 @@ static void tegra_dsi_initialize(struct tegra_dsi *dsi) tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE); } +static int tegra_dsi_set_lp_clk(struct tegra_dsi *dsi, unsigned long pclk) +{ + unsigned long bclk, timeout, value; + struct clk *clk, *parent, *base; + unsigned int mul, div; + int err; + + err = tegra_dsi_get_muldiv(dsi->format, &mul, &div); + if (err < 0) + return err; + + bclk = pclk * 8; + + clk = clk_get_parent(dsi->clk); + parent = clk_get_parent(clk); + base = clk_get_parent(parent); + + err = clk_set_rate(base, pclk * 2); + if (err < 0) + return err; + + /* one frame high-speed transmission timeout */ + timeout = bclk / 512; + value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout); + tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0); + + /* 2 ms peripheral timeout for panel */ + timeout = 2 * bclk / 512 * 1000; + value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000); + tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1); + + value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0); + tegra_dsi_writel(dsi, value, DSI_TO_TALLY); + + return 0; +} + +static ssize_t tegra_dsi_host_transfer(struct dsi_host *host, + struct dsi_msg *msg) +{ + struct tegra_dsi *dsi = dsi_host_to_tegra(host); + unsigned long value, timeout; + unsigned int count = 0, i; + const u8 *tx = msg->tx; + int err; + + dev_info(dsi->dev, "> %s(host=%p, msg=%p)\n", __func__, host, msg); + + /* XXX */ + drm_panel_enable(dsi->output.panel); + + value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); + value |= DSI_POWER_CONTROL_ENABLE; + tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); + usleep_range(300, 1000); + + err = tegra_dsi_set_lp_clk(dsi, 10000000); + if (err < 0) { + dev_err(dsi->dev, "failed to setup low-power clock: %d\n", err); + return err; + } + + tegra_dsi_writel(dsi, DSI_HOST_FIFO_DEPTH, DSI_MAX_THRESHOLD); + + value = tegra_dsi_readl(dsi, DSI_CONTROL); + value = 0x00003031; + tegra_dsi_writel(dsi, value, DSI_CONTROL); + + value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL); + value = 0x00102003; + tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); + + if (msg->rx && msg->rx_len > 0) { + value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL); + value |= DSI_HOST_CONTROL_BTA; + tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); + } + + value = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f); + + value |= tx[0] << 8; + value |= tx[1] << 16; + + tegra_dsi_writel(dsi, value, DSI_WR_DATA); + + tegra_dsi_writel(dsi, 0x00000002, DSI_TRIGGER); + + timeout = jiffies + msecs_to_jiffies(250); + + while (true) { + value = tegra_dsi_readl(dsi, DSI_TRIGGER); + if ((value & 0x00000002) == 0) + break; + + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + + usleep_range(25, 100); + } + + timeout = jiffies + msecs_to_jiffies(250); + + while (true) { + usleep_range(1000, 2000); + + value = tegra_dsi_readl(dsi, DSI_STATUS); + count = value & 0x1f; + + if (count > 0) + break; + + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + } + + for (i = 0; i < count; i++) + tegra_dsi_readl(dsi, DSI_RD_DATA); + + /* XXX */ + drm_panel_disable(dsi->output.panel); + + dev_info(dsi->dev, "< %s()\n", __func__); + return 0; +} + static int tegra_dsi_host_attach(struct dsi_host *host, struct dsi_device *device) { @@ -784,6 +909,27 @@ static int tegra_dsi_host_attach(struct dsi_host *host, if (output->panel) { if (output->connector.dev) drm_helper_hpd_irq_event(output->connector.dev); + + if (0) { + struct dsi_msg msg; + u8 tx[2], rx[2]; + ssize_t err; + + rx[0] = rx[1] = 0; + tx[0] = tx[1] = 0; + + memset(&msg, 0, sizeof(msg)); + msg.channel = 0; + msg.type = 0x05; + msg.tx_len = 2; + msg.tx = tx; + msg.rx_len = 2; + msg.rx = rx; + + err = dsi_host_transfer(&dsi->host, &msg); + if (err < 0) + dev_err(dsi->dev, "dsi_host_transfer() failed: %zd\n", err); + } } return 0; @@ -808,6 +954,7 @@ static int tegra_dsi_host_detach(struct dsi_host *host, static const struct dsi_host_ops tegra_dsi_host_ops = { .attach = tegra_dsi_host_attach, .detach = tegra_dsi_host_detach, + .transfer = tegra_dsi_host_transfer, }; static int tegra_dsi_probe(struct platform_device *pdev)