From: Sean Paul <seanpaul@chromium.org>
To: dri-devel@lists.freedesktop.org, inki.dae@samsung.com
Cc: marcheu@chromium.org
Subject: [PATCH 19/23] drm/exynos: Use mode_set to configure fimd
Date: Thu, 10 Oct 2013 20:30:32 -0400 [thread overview]
Message-ID: <1381451436-10089-20-git-send-email-seanpaul@chromium.org> (raw)
In-Reply-To: <1381451436-10089-1-git-send-email-seanpaul@chromium.org>
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 <seanpaul@chromium.org>
---
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);
--
1.8.4
next prev parent reply other threads:[~2013-10-11 0:31 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-11 0:30 [PATCH 00/23] drm/exynos: Refactor parts of the exynos driver Sean Paul
2013-10-11 0:30 ` [PATCH 01/23] drm/exynos: Remove useless slab.h include Sean Paul
2013-10-11 0:30 ` [PATCH 02/23] drm/exynos: Merge overlay_ops into manager_ops Sean Paul
2013-10-11 0:30 ` [PATCH 03/23] drm/exynos: Add an initialize function to manager and display Sean Paul
2013-10-11 0:30 ` [PATCH 04/23] drm/exynos: Use manager_op initialize in fimd Sean Paul
2013-10-11 0:30 ` [PATCH 05/23] drm/exynos: hdmi: Implement initialize op for hdmi Sean Paul
2013-10-11 0:30 ` [PATCH 06/23] drm/exynos: Pass context in manager ops instead of dev Sean Paul
2013-10-12 6:44 ` Inki Dae
2013-10-14 12:42 ` Inki Dae
2013-10-14 14:18 ` Sean Paul
2013-10-14 15:07 ` Inki Dae
2013-10-11 0:30 ` [PATCH 07/23] drm/exynos: Pass context in display_ops " Sean Paul
2013-10-11 0:30 ` [PATCH 08/23] drm/exynos: Remove dpms link between encoder/connector Sean Paul
2013-10-11 0:30 ` [PATCH 09/23] drm/exynos: Rename display_op power_on to dpms Sean Paul
2013-10-11 0:30 ` [PATCH 10/23] drm/exynos: Don't keep dpms state in encoder Sean Paul
2013-10-11 0:30 ` [PATCH 11/23] drm/exynos: Use unsigned long for possible_crtcs Sean Paul
2013-10-11 0:30 ` [PATCH 12/23] drm/exynos: Split manager/display/subdrv Sean Paul
2013-10-12 0:42 ` Inki Dae
2013-10-12 2:06 ` Sean Paul
2013-10-12 3:49 ` Inki Dae
2013-10-12 4:19 ` Sean Paul
2013-10-12 4:30 ` Inki Dae
2013-10-14 15:24 ` Inki Dae
2013-10-15 4:09 ` Inki Dae
2013-10-15 18:12 ` Sean Paul
2013-10-16 2:17 ` Inki Dae
2013-10-11 0:30 ` [PATCH 13/23] drm/exynos: hdmi: remove the i2c drivers and use devtree Sean Paul
2013-10-11 0:30 ` [PATCH 14/23] drm/exynos: Remove exynos_drm_hdmi shim Sean Paul
2013-10-11 0:30 ` [PATCH 15/23] drm/exynos: Use drm_mode_copy to copy modes Sean Paul
2013-10-11 0:30 ` [PATCH 16/23] drm/exynos: Disable unused crtc planes from crtc Sean Paul
2013-10-11 0:30 ` [PATCH 17/23] drm/exynos: Add mode_set manager operation Sean Paul
2013-10-11 0:30 ` [PATCH 18/23] drm/exynos: Implement mode_fixup " Sean Paul
2013-10-11 0:30 ` Sean Paul [this message]
2013-10-11 0:30 ` [PATCH 20/23] drm/exynos: Remove unused/useless fimd_context members Sean Paul
2013-10-11 0:30 ` [PATCH 21/23] drm/exynos: Move dp driver from video/ to drm/ Sean Paul
2013-10-11 0:30 ` [PATCH 22/23] drm/exynos: Move display implementation into dp Sean Paul
2013-10-11 0:30 ` [PATCH 23/23] ARM: dts: Move display-timings node from fimd to dp Sean Paul
2013-10-12 2:26 ` [PATCH 00/23] drm/exynos: Refactor parts of the exynos driver Tomasz Figa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1381451436-10089-20-git-send-email-seanpaul@chromium.org \
--to=seanpaul@chromium.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=inki.dae@samsung.com \
--cc=marcheu@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.