From patchwork Wed Mar 9 10:57:16 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Archit Taneja X-Patchwork-Id: 8545201 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 0AD08C0553 for ; Wed, 9 Mar 2016 10:57:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 025E320165 for ; Wed, 9 Mar 2016 10:57:57 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 8B6B7201D3 for ; Wed, 9 Mar 2016 10:57:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 456686E8D8; Wed, 9 Mar 2016 10:57:53 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.29.96]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0518C6E8CA for ; Wed, 9 Mar 2016 10:57:49 +0000 (UTC) Received: from smtp.codeaurora.org (localhost [127.0.0.1]) by smtp.codeaurora.org (Postfix) with ESMTP id E26AF60EC7; Wed, 9 Mar 2016 10:57:48 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id D05E760F35; Wed, 9 Mar 2016 10:57:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from localhost (unknown [202.46.23.61]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: architt@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 4406460ECC; Wed, 9 Mar 2016 10:57:46 +0000 (UTC) From: Archit Taneja To: dri-devel@lists.freedesktop.org Subject: [PATCH v3 5/7] drm/i2c: adv7511: Use internal timing generator Date: Wed, 9 Mar 2016 16:27:16 +0530 Message-Id: <1457521038-5906-6-git-send-email-architt@codeaurora.org> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1457521038-5906-1-git-send-email-architt@codeaurora.org> References: <1441625800-1858-1-git-send-email-architt@codeaurora.org> <1457521038-5906-1-git-send-email-architt@codeaurora.org> X-Virus-Scanned: ClamAV using ClamSMTP Cc: andy.green@linaro.org, linux-arm-msm@vger.kernel.org, amit.kucheria@linaro.org, srinivas.kandagatla@linaro.org, laurent.pinchart@ideasonboard.com, treding@nvidia.com 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 ADV7533 provides an internal timing generator for certain modes that it can't use the DSI clock directly. We've observed that HDMI is more stable with the internal timing generator, especially if there are instabilities in the DSI clock source. The data spec also seems to recommend the usage of the timing generator for all modes. However, on some platforms, it's reported that enabling the timing generator causes instabilities with the HDMI output. Create a DT parameter that lets a platform explicitly disable the timing generator. The timing generator is enabled by default. Signed-off-by: Archit Taneja --- drivers/gpu/drm/i2c/adv7511.c | 65 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c index 6c2a89a..88918ae 100644 --- a/drivers/gpu/drm/i2c/adv7511.c +++ b/drivers/gpu/drm/i2c/adv7511.c @@ -39,6 +39,8 @@ struct adv7511 { enum drm_connector_status status; bool powered; + struct drm_display_mode curr_mode; + unsigned int f_tmds; unsigned int current_edid_segment; @@ -62,6 +64,7 @@ struct adv7511 { struct device_node *host_node; struct mipi_dsi_device *dsi; u8 num_dsi_lanes; + bool use_timing_gen; enum adv7511_type type; }; @@ -397,14 +400,65 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB; } +static void adv7511_dsi_config_timing_gen(struct adv7511 *adv) +{ + struct mipi_dsi_device *dsi = adv->dsi; + struct drm_display_mode *mode = &adv->curr_mode; + unsigned int hsw, hfp, hbp, vsw, vfp, vbp; + u8 clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */ + + hsw = mode->hsync_end - mode->hsync_start; + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + vsw = mode->vsync_end - mode->vsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + + /* set pixel clock divider mode */ + regmap_write(adv->regmap_cec, 0x16, + clock_div_by_lanes[dsi->lanes - 2] << 3); + + /* horizontal porch params */ + regmap_write(adv->regmap_cec, 0x28, mode->htotal >> 4); + regmap_write(adv->regmap_cec, 0x29, (mode->htotal << 4) & 0xff); + regmap_write(adv->regmap_cec, 0x2a, hsw >> 4); + regmap_write(adv->regmap_cec, 0x2b, (hsw << 4) & 0xff); + regmap_write(adv->regmap_cec, 0x2c, hfp >> 4); + regmap_write(adv->regmap_cec, 0x2d, (hfp << 4) & 0xff); + regmap_write(adv->regmap_cec, 0x2e, hbp >> 4); + regmap_write(adv->regmap_cec, 0x2f, (hbp << 4) & 0xff); + + /* vertical porch params */ + regmap_write(adv->regmap_cec, 0x30, mode->vtotal >> 4); + regmap_write(adv->regmap_cec, 0x31, (mode->vtotal << 4) & 0xff); + regmap_write(adv->regmap_cec, 0x32, vsw >> 4); + regmap_write(adv->regmap_cec, 0x33, (vsw << 4) & 0xff); + regmap_write(adv->regmap_cec, 0x34, vfp >> 4); + regmap_write(adv->regmap_cec, 0x35, (vfp << 4) & 0xff); + regmap_write(adv->regmap_cec, 0x36, vbp >> 4); + regmap_write(adv->regmap_cec, 0x37, (vbp << 4) & 0xff); +} + static void adv7533_dsi_power_on(struct adv7511 *adv) { struct mipi_dsi_device *dsi = adv->dsi; + if (adv->use_timing_gen) + adv7511_dsi_config_timing_gen(adv); + /* set number of dsi lanes */ regmap_write(adv->regmap_cec, 0x1c, dsi->lanes << 4); - /* disable internal timing generator */ - regmap_write(adv->regmap_cec, 0x27, 0x0b); + + if (adv->use_timing_gen) { + /* reset internal timing generator */ + regmap_write(adv->regmap_cec, 0x27, 0xcb); + regmap_write(adv->regmap_cec, 0x27, 0x8b); + regmap_write(adv->regmap_cec, 0x27, 0xcb); + } else { + /* disable internal timing generator */ + regmap_write(adv->regmap_cec, 0x27, 0x0b); + } + /* enable hdmi */ regmap_write(adv->regmap_cec, 0x03, 0x89); /* disable test mode */ @@ -459,6 +513,8 @@ static void adv7533_dsi_power_off(struct adv7511 *adv) { /* disable hdmi */ regmap_write(adv->regmap_cec, 0x03, 0x0b); + /* disable internal timing generator */ + regmap_write(adv->regmap_cec, 0x27, 0x0b); } static void adv7511_power_off(struct adv7511 *adv7511) @@ -807,6 +863,8 @@ static void adv7511_mode_set(struct adv7511 *adv7511, regmap_update_bits(adv7511->regmap, 0x17, 0x60, (vsync_polarity << 6) | (hsync_polarity << 5)); + drm_mode_copy(&adv7511->curr_mode, adj_mode); + /* * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is * supposed to give better results. @@ -1094,6 +1152,9 @@ static int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv) of_node_put(endpoint); of_node_put(adv->host_node); + adv->use_timing_gen = !of_property_read_bool(np, + "adi,disable-timing-generator"); + /* TODO: Check if these need to be parsed by DT or not */ adv->rgb = true; adv->embedded_sync = false;