From patchwork Fri Oct 11 00:30:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 3020011 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.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 304E5BF924 for ; Fri, 11 Oct 2013 00:53:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 598C62021B for ; Fri, 11 Oct 2013 00:53:27 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 33AC020254 for ; Fri, 11 Oct 2013 00:53:26 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2CB1BE7B98 for ; Thu, 10 Oct 2013 17:53:26 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-ie0-f176.google.com (mail-ie0-f176.google.com [209.85.223.176]) by gabe.freedesktop.org (Postfix) with ESMTP id 8C0BEE6CE4 for ; Thu, 10 Oct 2013 17:31:22 -0700 (PDT) Received: by mail-ie0-f176.google.com with SMTP id ar20so6453014iec.7 for ; Thu, 10 Oct 2013 17:31:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qiJ3zQq+mLCoQPgcHIisLrgdRYnDTZRSEWTqKC4ikG4=; b=dRnwGHvASovAarW4INca4g1Kats0XCSitvAiMBbfB6j7sPLQSumApzNIHhQd4jlthq m78oBC0gzFPqVn3pe52wuPzH5VyLavQJurS6+LU/CL1+mQ3LDHXpd/wqokj0LFOmNYBP sO+g80d732/JFEdcA+mhHbnLypxXxWRqZYcRQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qiJ3zQq+mLCoQPgcHIisLrgdRYnDTZRSEWTqKC4ikG4=; b=WZQgHrke8D67TQ9hxi9+oIgJd6UG/UNK/lbPxFGFwY7QfjNkjdRVqpPjPg8uyv9X63 c5znuTqeeeH1e0hXCmE0s/BvZvaxAwy7v7YAzJXDcrrKqZFcLm396J14u3kt0dZDrBl7 E3IjH4BWrk+AT8xHnU7PtbGo332gbxJ5eZoOZvPeVJLnHTPpDv/uqW137jtAtvmGt9M6 YCgwJF8tdG2yN6jrU7SIYutrfMCtPiRKZRlWKsyqeYZFbtm+SPgQv3bt0jy/v+fkZEyb YLtubL72+pCQxSZObY4JxpxGh6KZ6TX+aKstm09EWrlhQCSTPSBLLlAVyXZWbx4A8fJl i5BA== X-Gm-Message-State: ALoCoQlyL9hGZ3PfGC1YYe2C85Tw4QSICB0D9bfZuad8XIWuqfzcVGRheRtQjBvtgk6jC5SnLSnZ X-Received: by 10.50.87.4 with SMTP id t4mr757250igz.18.1381451482133; Thu, 10 Oct 2013 17:31:22 -0700 (PDT) Received: from seanpaul-glaptop.corp.google.com (dhcp-172-19-29-233.mtv.corp.google.com [172.19.29.233]) by mx.google.com with ESMTPSA id p7sm420421iga.3.1969.12.31.16.00.00 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 10 Oct 2013 17:31:21 -0700 (PDT) From: Sean Paul To: dri-devel@lists.freedesktop.org, inki.dae@samsung.com Subject: [PATCH 19/23] drm/exynos: Use mode_set to configure fimd Date: Thu, 10 Oct 2013 20:30:32 -0400 Message-Id: <1381451436-10089-20-git-send-email-seanpaul@chromium.org> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1381451436-10089-1-git-send-email-seanpaul@chromium.org> References: <1381451436-10089-1-git-send-email-seanpaul@chromium.org> Cc: marcheu@chromium.org 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+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org X-Spam-Status: No, score=-4.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, 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 This patch uses the mode passed into mode_set to configure fimd instead of directly using the panel from context. This will allow us to move the exynos_drm_display implementation from fimd into the DP driver where it belongs. Signed-off-by: Sean Paul --- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 157 ++++++++++++++++++------------- 1 file changed, 89 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index f3dc808..1b128cf 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -104,6 +104,20 @@ struct fimd_win_data { bool resume; }; +struct fimd_mode_data { + unsigned vtotal; + unsigned vdisplay; + unsigned vsync_len; + unsigned vbpd; + unsigned vfpd; + unsigned htotal; + unsigned hdisplay; + unsigned hsync_len; + unsigned hbpd; + unsigned hfpd; + u32 clkdiv; +}; + struct fimd_context { struct device *dev; struct drm_device *drm_dev; @@ -112,8 +126,8 @@ struct fimd_context { struct clk *bus_clk; struct clk *lcd_clk; void __iomem *regs; + struct fimd_mode_data mode; struct fimd_win_data win_data[WINDOWS_NR]; - unsigned int clkdiv; unsigned int default_win; unsigned long irq_flags; u32 vidcon0; @@ -558,11 +572,54 @@ static void fimd_dpms(void *in_ctx, int mode) mutex_unlock(&ctx->lock); } +static u32 fimd_calc_clkdiv(struct fimd_context *ctx, + const struct drm_display_mode *mode) +{ + unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh; + u32 clkdiv; + + /* Find the clock divider value that gets us closest to ideal_clk */ + clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(ctx->lcd_clk), ideal_clk); + + return (clkdiv < 0x100) ? clkdiv : 0xff; +} + +static bool fimd_mode_fixup(void *in_ctx, const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + if (adjusted_mode->vrefresh == 0) + adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE; + + return true; +} + +static void fimd_mode_set(void *in_ctx, const struct drm_display_mode *in_mode) +{ + struct fimd_context *ctx = in_ctx; + struct fimd_mode_data *mode = &ctx->mode; + int hblank, vblank; + + vblank = in_mode->crtc_vblank_end - in_mode->crtc_vblank_start; + mode->vtotal = in_mode->crtc_vtotal; + mode->vdisplay = in_mode->crtc_vdisplay; + mode->vsync_len = in_mode->crtc_vsync_end - in_mode->crtc_vsync_start; + mode->vbpd = (vblank - mode->vsync_len) / 2; + mode->vfpd = vblank - mode->vsync_len - mode->vbpd; + + hblank = in_mode->crtc_hblank_end - in_mode->crtc_hblank_start; + mode->htotal = in_mode->crtc_htotal; + mode->hdisplay = in_mode->crtc_hdisplay; + mode->hsync_len = in_mode->crtc_hsync_end - in_mode->crtc_hsync_start; + mode->hbpd = (hblank - mode->hsync_len) / 2; + mode->hfpd = hblank - mode->hsync_len - mode->hbpd; + + mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode); +} + static void fimd_commit(void *in_ctx) { struct fimd_context *ctx = in_ctx; - struct exynos_drm_panel_info *panel = &ctx->panel; - struct videomode *vm = &panel->vm; + struct fimd_mode_data *mode = &ctx->mode; struct fimd_driver_data *driver_data; u32 val; @@ -570,26 +627,30 @@ static void fimd_commit(void *in_ctx) if (ctx->suspended) return; + /* nothing to do if we haven't set the mode yet */ + if (mode->htotal == 0 || mode->vtotal == 0) + return; + /* setup polarity values from machine code. */ writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1); /* setup vertical timing values. */ - val = VIDTCON0_VBPD(vm->vback_porch - 1) | - VIDTCON0_VFPD(vm->vfront_porch - 1) | - VIDTCON0_VSPW(vm->vsync_len - 1); + val = VIDTCON0_VBPD(mode->vbpd - 1) | + VIDTCON0_VFPD(mode->vfpd - 1) | + VIDTCON0_VSPW(mode->vsync_len - 1); writel(val, ctx->regs + driver_data->timing_base + VIDTCON0); /* setup horizontal timing values. */ - val = VIDTCON1_HBPD(vm->hback_porch - 1) | - VIDTCON1_HFPD(vm->hfront_porch - 1) | - VIDTCON1_HSPW(vm->hsync_len - 1); + val = VIDTCON1_HBPD(mode->hbpd - 1) | + VIDTCON1_HFPD(mode->hfpd - 1) | + VIDTCON1_HSPW(mode->hsync_len - 1); writel(val, ctx->regs + driver_data->timing_base + VIDTCON1); /* setup horizontal and vertical display size. */ - val = VIDTCON2_LINEVAL(vm->vactive - 1) | - VIDTCON2_HOZVAL(vm->hactive - 1) | - VIDTCON2_LINEVAL_E(vm->vactive - 1) | - VIDTCON2_HOZVAL_E(vm->hactive - 1); + val = VIDTCON2_LINEVAL(mode->vdisplay - 1) | + VIDTCON2_HOZVAL(mode->hdisplay - 1) | + VIDTCON2_LINEVAL_E(mode->vdisplay - 1) | + VIDTCON2_HOZVAL_E(mode->hdisplay - 1); writel(val, ctx->regs + driver_data->timing_base + VIDTCON2); /* setup clock source, clock divider, enable dma. */ @@ -601,8 +662,8 @@ static void fimd_commit(void *in_ctx) val |= VIDCON0_CLKSEL_LCD; } - if (ctx->clkdiv > 1) - val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR; + if (mode->clkdiv > 1) + val |= VIDCON0_CLKVAL_F(mode->clkdiv - 1) | VIDCON0_CLKDIR; else val &= ~VIDCON0_CLKDIR; /* 1:1 clock */ @@ -696,6 +757,8 @@ static struct exynos_drm_manager_ops fimd_manager_ops = { .remove = fimd_mgr_remove, .dpms = fimd_dpms, .apply = fimd_apply, + .mode_fixup = fimd_mode_fixup, + .mode_set = fimd_mode_set, .commit = fimd_commit, .enable_vblank = fimd_enable_vblank, .disable_vblank = fimd_disable_vblank, @@ -737,56 +800,6 @@ out: return IRQ_HANDLED; } -static int fimd_configure_clocks(struct fimd_context *ctx, struct device *dev) -{ - struct videomode *vm = &ctx->panel.vm; - unsigned long clk; - - ctx->bus_clk = devm_clk_get(dev, "fimd"); - if (IS_ERR(ctx->bus_clk)) { - dev_err(dev, "failed to get bus clock\n"); - return PTR_ERR(ctx->bus_clk); - } - - ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd"); - if (IS_ERR(ctx->lcd_clk)) { - dev_err(dev, "failed to get lcd clock\n"); - return PTR_ERR(ctx->lcd_clk); - } - - clk = clk_get_rate(ctx->lcd_clk); - if (clk == 0) { - dev_err(dev, "error getting sclk_fimd clock rate\n"); - return -EINVAL; - } - - if (vm->pixelclock == 0) { - unsigned long c; - c = vm->hactive + vm->hback_porch + vm->hfront_porch + - vm->hsync_len; - c *= vm->vactive + vm->vback_porch + vm->vfront_porch + - vm->vsync_len; - vm->pixelclock = c * FIMD_DEFAULT_FRAMERATE; - if (vm->pixelclock == 0) { - dev_err(dev, "incorrect display timings\n"); - return -EINVAL; - } - dev_warn(dev, "pixel clock recalculated to %luHz (%dHz frame rate)\n", - vm->pixelclock, FIMD_DEFAULT_FRAMERATE); - } - ctx->clkdiv = DIV_ROUND_UP(clk, vm->pixelclock); - if (ctx->clkdiv > 256) { - dev_warn(dev, "calculated pixel clock divider too high (%u), lowered to 256\n", - ctx->clkdiv); - ctx->clkdiv = 256; - } - vm->pixelclock = clk / ctx->clkdiv; - DRM_DEBUG_KMS("pixel clock = %lu, clkdiv = %d\n", vm->pixelclock, - ctx->clkdiv); - - return 0; -} - static void fimd_clear_win(struct fimd_context *ctx, int win) { writel(0, ctx->regs + WINCON(win)); @@ -916,9 +929,17 @@ static int fimd_probe(struct platform_device *pdev) if (ret) return ret; - ret = fimd_configure_clocks(ctx, dev); - if (ret) - return ret; + ctx->bus_clk = devm_clk_get(dev, "fimd"); + if (IS_ERR(ctx->bus_clk)) { + dev_err(dev, "failed to get bus clock\n"); + return PTR_ERR(ctx->bus_clk); + } + + ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd"); + if (IS_ERR(ctx->lcd_clk)) { + dev_err(dev, "failed to get lcd clock\n"); + return PTR_ERR(ctx->lcd_clk); + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0);