From patchwork Thu Dec 24 07:34:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Binacchi X-Patchwork-Id: 1420426 X-Patchwork-Delegate: lokeshvutla@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=quarantine dis=none) header.from=libero.it Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=libero.it header.i=@libero.it header.a=rsa-sha256 header.s=s2014 header.b=DF7S/sUG; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4D1hjP23Hdz9sRR for ; Thu, 24 Dec 2020 18:36:57 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 01C3A827BA; Thu, 24 Dec 2020 08:35:41 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=libero.it Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=libero.it header.i=@libero.it header.b="DF7S/sUG"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D71FC82715; Thu, 24 Dec 2020 08:35:12 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FORGED_SPF_HELO,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_PASS autolearn=no autolearn_force=no version=3.4.2 Received: from libero.it (smtp-18.italiaonline.it [213.209.10.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 5904D82702 for ; Thu, 24 Dec 2020 08:34:55 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=libero.it Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=dariobin@libero.it Received: from passgat-Modern-14-A10M.homenet.telecomitalia.it ([79.54.115.44]) by smtp-18.iol.local with ESMTPA id sL93kry9c7QU9sL9DkXNDB; Thu, 24 Dec 2020 08:34:55 +0100 x-libjamoibt: 1601 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=libero.it; s=s2014; t=1608795295; bh=kCLrOstbkOycLT1Y97kbcjoA7LGtj8mu0q5UncclQnw=; h=From; b=DF7S/sUGjww7JZ1hN7ERgCFv4H/K9QYHMnlbJZGhMfSkdOv6NlPHGcMPFn+C2kGUY 1lZZJleGxh94whS55UTRPT0PVcASjUrVXx32OcJkrgV6rd8snYvA17We7Y/2nC7sex SJ5+UXDFCkZTotpEi81xYZtQcihtoABj8x95AsD3OUL6BjUIDhVeGhtTnNC0JiVohY PVLisNeFpzo013J9tHp0yfIvezZP62SMFN/ihoOWnM6j4EnSqjrNZJafnNEPb1hR/N X5UHsbNwTGxj6jG4kFQNWMhO9tchbIEASSyKh2IgVU+mYqpbPyH3qe2gbjnwdcD2ck qLWQOmryACxgg== X-CNFS-Analysis: v=2.4 cv=Y+c9DjSN c=1 sm=1 tr=0 ts=5fe4449f cx=a_exe a=4XFUYcG0DNokufVEFeBjWw==:117 a=4XFUYcG0DNokufVEFeBjWw==:17 a=U7GvtkirgPeyM4qxJq4A:9 a=vbrGtdLndY3beCn0:21 a=de3mZ0dmDnV1G4_4:21 From: Dario Binacchi To: u-boot@lists.denx.de Cc: Lokesh Vutla , Dario Binacchi , Anatolij Gustschin Subject: [PATCH v7 25/28] video: omap: set LCD clock rate through DM API Date: Thu, 24 Dec 2020 08:34:03 +0100 Message-Id: <20201224073406.16764-26-dariobin@libero.it> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201224073406.16764-15-dariobin@libero.it> References: <20201224073406.16764-15-dariobin@libero.it> X-CMAE-Envelope: MS4xfBgU/TY3H784PtEVAD6TBT1ikJ7aNR3VKvNvkPaeH7N0jPnDC4pRr7zzFidZcZXs91SpbjSQVO6fjzUJP6CE0rWKbemmIki9Dhtj8hbGYYOlkliKuxMx ymCTgp2jtqKXqRBkHiKypN8pW3sjxiyvUgVSlxc+4pOOYeIgtfEzDNlRYuuQ4ytxUr477nZgP7C1aGXbgvHXRfEm0791+4S+0Y0C4tuUc6KItRl438RmlQVJ oRkcWQu1pBotbAYiuO641Nu9/7kBib0m71tsw5Veh5Cmhd0Bq5Oicr+fLQIm9bJihwQYSCwkEvLBD4zga6xHCw== X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean The patch configures the display DPLL using the functions provided by the driver model API for the clock. The device tree contains everything needed to get the DPLL clock. The round rate function developed for calculating the DPLL multiplier and divisor and the platform routines for accessing the DPLL registers are removed from the LCD driver code because they are implemented inside the DPLL clock driver. Signed-off-by: Dario Binacchi --- (no changes since v3) Changes in v3: - Add clk.h header. - Fix an error code returned by the probe function. drivers/video/am335x-fb.c | 129 ++++++++++++++++++++++++++++++-------- 1 file changed, 103 insertions(+), 26 deletions(-) diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c index dc959baa27..a0a635cc29 100644 --- a/drivers/video/am335x-fb.c +++ b/drivers/video/am335x-fb.c @@ -12,6 +12,7 @@ * - starts output DMA from gd->fb_base buffer */ #include +#include #include #include #include @@ -112,6 +113,27 @@ struct am335x_lcdhw { unsigned int clkc_reset; /* 0x70 */ }; +DECLARE_GLOBAL_DATA_PTR; + +#if !CONFIG_IS_ENABLED(DM_VIDEO) + +#if !defined(LCD_CNTL_BASE) +#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!" +#endif + +/* Macro definitions */ +#define FBSIZE(x) (((x)->hactive * (x)->vactive * (x)->bpp) >> 3) + +#define LCDC_RASTER_TIMING_2_INVMASK(x) ((x) & GENMASK(25, 20)) + +static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE; + +int lcd_get_size(int *line_length) +{ + *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; + return *line_length * panel_info.vl_row + 0x20; +} + struct dpll_data { unsigned long rounded_rate; u16 rounded_m; @@ -119,8 +141,6 @@ struct dpll_data { u8 rounded_div; }; -DECLARE_GLOBAL_DATA_PTR; - /** * am335x_dpll_round_rate() - Round a target rate for an OMAP DPLL * @@ -199,25 +219,6 @@ static ulong am335x_fb_set_pixel_clk_rate(struct am335x_lcdhw *regs, ulong rate) return round_rate; } -#if !CONFIG_IS_ENABLED(DM_VIDEO) - -#if !defined(LCD_CNTL_BASE) -#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!" -#endif - -/* Macro definitions */ -#define FBSIZE(x) (((x)->hactive * (x)->vactive * (x)->bpp) >> 3) - -#define LCDC_RASTER_TIMING_2_INVMASK(x) ((x) & GENMASK(25, 20)) - -static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE; - -int lcd_get_size(int *line_length) -{ - *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; - return *line_length * panel_info.vl_row + 0x20; -} - int am335xfb_init(struct am335x_lcdpanel *panel) { u32 raster_ctrl = 0; @@ -335,14 +336,58 @@ enum { struct am335x_fb_priv { struct am335x_lcdhw *regs; + struct clk gclk; + struct clk dpll_m2_clk; }; +static ulong tilcdc_set_pixel_clk_rate(struct udevice *dev, ulong rate) +{ + struct am335x_fb_priv *priv = dev_get_priv(dev); + struct am335x_lcdhw *regs = priv->regs; + ulong mult_rate, mult_round_rate, best_err, err; + u32 v; + int div, i; + + best_err = rate; + div = 0; + for (i = 2; i <= 255; i++) { + mult_rate = rate * i; + mult_round_rate = clk_round_rate(&priv->gclk, mult_rate); + if (IS_ERR_VALUE(mult_round_rate)) + return mult_round_rate; + + err = mult_rate - mult_round_rate; + if (err < best_err) { + best_err = err; + div = i; + if (err == 0) + break; + } + } + + if (div == 0) { + dev_err(dev, "failed to find a divisor\n"); + return -EFAULT; + } + + mult_rate = clk_set_rate(&priv->gclk, rate * div); + v = readl(®s->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK; + v |= LCDC_CTRL_CLK_DIVISOR(div); + writel(v, ®s->ctrl); + rate = mult_rate / div; + dev_dbg(dev, "rate=%ld, div=%d, err=%ld\n", rate, div, err); + return rate; +} + static int am335x_fb_remove(struct udevice *dev) { struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + struct am335x_fb_priv *priv = dev_get_priv(dev); uc_plat->base -= 0x20; uc_plat->size += 0x20; + clk_release_all(&priv->gclk, 1); + clk_release_all(&priv->dpll_m2_clk, 1); return 0; } @@ -352,10 +397,10 @@ static int am335x_fb_probe(struct udevice *dev) struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct am335x_fb_priv *priv = dev_get_priv(dev); struct am335x_lcdhw *regs = priv->regs; - struct udevice *panel; + struct udevice *panel, *clk_dev; struct tilcdc_panel_info info; struct display_timing timing; - struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL; + ulong rate; u32 reg; int err; @@ -416,10 +461,42 @@ static int am335x_fb_probe(struct udevice *dev) return -EINVAL; } - am335x_fb_set_pixel_clk_rate(regs, timing.pixelclock.typ); + err = uclass_get_device_by_name(UCLASS_CLK, "lcd_gclk@534", &clk_dev); + if (err) { + dev_err(dev, "failed to get lcd_gclk device\n"); + return err; + } - /* clock source for LCDC from dispPLL M2 */ - writel(0, &cmdpll->clklcdcpixelclk); + err = clk_request(clk_dev, &priv->gclk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + } + + rate = tilcdc_set_pixel_clk_rate(dev, timing.pixelclock.typ); + if (IS_ERR_VALUE(rate)) { + dev_err(dev, "failed to set pixel clock rate\n"); + return rate; + } + + err = uclass_get_device_by_name(UCLASS_CLK, "dpll_disp_m2_ck@4a4", &clk_dev); + if (err) { + dev_err(dev, "failed to get dpll_disp_m2 clock device\n"); + return err; + } + + err = clk_request(clk_dev, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + } + + err = clk_set_parent(&priv->gclk, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to set %s clock as %s's parent\n", + priv->dpll_m2_clk.dev->name, priv->gclk.dev->name); + return err; + } /* palette default entry */ memset((void *)uc_plat->base, 0, 0x20);