diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fimd.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 146 |
1 files changed, 74 insertions, 72 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 97c61dbffd82..3e106beca5b6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -63,14 +63,24 @@ struct fimd_driver_data { unsigned int timing_base; + + unsigned int has_shadowcon:1; + unsigned int has_clksel:1; +}; + +static struct fimd_driver_data s3c64xx_fimd_driver_data = { + .timing_base = 0x0, + .has_clksel = 1, }; static struct fimd_driver_data exynos4_fimd_driver_data = { .timing_base = 0x0, + .has_shadowcon = 1, }; static struct fimd_driver_data exynos5_fimd_driver_data = { .timing_base = 0x20000, + .has_shadowcon = 1, }; struct fimd_win_data { @@ -107,10 +117,13 @@ struct fimd_context { atomic_t wait_vsync_event; struct exynos_drm_panel_info *panel; + struct fimd_driver_data *driver_data; }; #ifdef CONFIG_OF static const struct of_device_id fimd_driver_dt_match[] = { + { .compatible = "samsung,s3c6400-fimd", + .data = &s3c64xx_fimd_driver_data }, { .compatible = "samsung,exynos4210-fimd", .data = &exynos4_fimd_driver_data }, { .compatible = "samsung,exynos5250-fimd", @@ -137,8 +150,6 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data( static bool fimd_display_is_connected(struct device *dev) { - DRM_DEBUG_KMS("%s\n", __FILE__); - /* TODO. */ return true; @@ -148,15 +159,11 @@ static void *fimd_get_panel(struct device *dev) { struct fimd_context *ctx = get_fimd_context(dev); - DRM_DEBUG_KMS("%s\n", __FILE__); - return ctx->panel; } -static int fimd_check_timing(struct device *dev, void *timing) +static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode) { - DRM_DEBUG_KMS("%s\n", __FILE__); - /* TODO. */ return 0; @@ -164,8 +171,6 @@ static int fimd_check_timing(struct device *dev, void *timing) static int fimd_display_power_on(struct device *dev, int mode) { - DRM_DEBUG_KMS("%s\n", __FILE__); - /* TODO */ return 0; @@ -175,7 +180,7 @@ static struct exynos_drm_display_ops fimd_display_ops = { .type = EXYNOS_DISPLAY_TYPE_LCD, .is_connected = fimd_display_is_connected, .get_panel = fimd_get_panel, - .check_timing = fimd_check_timing, + .check_mode = fimd_check_mode, .power_on = fimd_display_power_on, }; @@ -183,7 +188,7 @@ static void fimd_dpms(struct device *subdrv_dev, int mode) { struct fimd_context *ctx = get_fimd_context(subdrv_dev); - DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode); + DRM_DEBUG_KMS("%d\n", mode); mutex_lock(&ctx->lock); @@ -221,8 +226,6 @@ static void fimd_apply(struct device *subdrv_dev) struct fimd_win_data *win_data; int i; - DRM_DEBUG_KMS("%s\n", __FILE__); - for (i = 0; i < WINDOWS_NR; i++) { win_data = &ctx->win_data[i]; if (win_data->enabled && (ovl_ops && ovl_ops->commit)) @@ -239,15 +242,12 @@ static void fimd_commit(struct device *dev) struct exynos_drm_panel_info *panel = ctx->panel; struct fb_videomode *timing = &panel->timing; struct fimd_driver_data *driver_data; - struct platform_device *pdev = to_platform_device(dev); u32 val; - driver_data = drm_fimd_get_driver_data(pdev); + driver_data = ctx->driver_data; if (ctx->suspended) return; - DRM_DEBUG_KMS("%s\n", __FILE__); - /* setup polarity values from machine code. */ writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1); @@ -274,6 +274,11 @@ static void fimd_commit(struct device *dev) val = ctx->vidcon0; val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); + if (ctx->driver_data->has_clksel) { + val &= ~VIDCON0_CLKSEL_MASK; + val |= VIDCON0_CLKSEL_LCD; + } + if (ctx->clkdiv > 1) val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR; else @@ -292,8 +297,6 @@ static int fimd_enable_vblank(struct device *dev) struct fimd_context *ctx = get_fimd_context(dev); u32 val; - DRM_DEBUG_KMS("%s\n", __FILE__); - if (ctx->suspended) return -EPERM; @@ -319,8 +322,6 @@ static void fimd_disable_vblank(struct device *dev) struct fimd_context *ctx = get_fimd_context(dev); u32 val; - DRM_DEBUG_KMS("%s\n", __FILE__); - if (ctx->suspended) return; @@ -370,8 +371,6 @@ static void fimd_win_mode_set(struct device *dev, int win; unsigned long offset; - DRM_DEBUG_KMS("%s\n", __FILE__); - if (!overlay) { dev_err(dev, "overlay is NULL\n"); return; @@ -381,7 +380,7 @@ static void fimd_win_mode_set(struct device *dev, if (win == DEFAULT_ZPOS) win = ctx->default_win; - if (win < 0 || win > WINDOWS_NR) + if (win < 0 || win >= WINDOWS_NR) return; offset = overlay->fb_x * (overlay->bpp >> 3); @@ -418,8 +417,6 @@ static void fimd_win_set_pixfmt(struct device *dev, unsigned int win) struct fimd_win_data *win_data = &ctx->win_data[win]; unsigned long val; - DRM_DEBUG_KMS("%s\n", __FILE__); - val = WINCONx_ENWIN; switch (win_data->bpp) { @@ -478,8 +475,6 @@ static void fimd_win_set_colkey(struct device *dev, unsigned int win) struct fimd_context *ctx = get_fimd_context(dev); unsigned int keycon0 = 0, keycon1 = 0; - DRM_DEBUG_KMS("%s\n", __FILE__); - keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F | WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0); @@ -489,6 +484,33 @@ static void fimd_win_set_colkey(struct device *dev, unsigned int win) writel(keycon1, ctx->regs + WKEYCON1_BASE(win)); } +/** + * shadow_protect_win() - disable updating values from shadow registers at vsync + * + * @win: window to protect registers for + * @protect: 1 to protect (disable updates) + */ +static void fimd_shadow_protect_win(struct fimd_context *ctx, + int win, bool protect) +{ + u32 reg, bits, val; + + if (ctx->driver_data->has_shadowcon) { + reg = SHADOWCON; + bits = SHADOWCON_WINx_PROTECT(win); + } else { + reg = PRTCON; + bits = PRTCON_PROTECT; + } + + val = readl(ctx->regs + reg); + if (protect) + val |= bits; + else + val &= ~bits; + writel(val, ctx->regs + reg); +} + static void fimd_win_commit(struct device *dev, int zpos) { struct fimd_context *ctx = get_fimd_context(dev); @@ -498,21 +520,19 @@ static void fimd_win_commit(struct device *dev, int zpos) unsigned int last_x; unsigned int last_y; - DRM_DEBUG_KMS("%s\n", __FILE__); - if (ctx->suspended) return; if (win == DEFAULT_ZPOS) win = ctx->default_win; - if (win < 0 || win > WINDOWS_NR) + if (win < 0 || win >= WINDOWS_NR) return; win_data = &ctx->win_data[win]; /* - * SHADOWCON register is used for enabling timing. + * SHADOWCON/PRTCON register is used for enabling timing. * * for example, once only width value of a register is set, * if the dma is started then fimd hardware could malfunction so @@ -522,9 +542,7 @@ static void fimd_win_commit(struct device *dev, int zpos) */ /* protect windows */ - val = readl(ctx->regs + SHADOWCON); - val |= SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); + fimd_shadow_protect_win(ctx, win, true); /* buffer start address */ val = (unsigned long)win_data->dma_addr; @@ -602,10 +620,13 @@ static void fimd_win_commit(struct device *dev, int zpos) writel(val, ctx->regs + WINCON(win)); /* Enable DMA channel and unprotect windows */ - val = readl(ctx->regs + SHADOWCON); - val |= SHADOWCON_CHx_ENABLE(win); - val &= ~SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); + fimd_shadow_protect_win(ctx, win, false); + + if (ctx->driver_data->has_shadowcon) { + val = readl(ctx->regs + SHADOWCON); + val |= SHADOWCON_CHx_ENABLE(win); + writel(val, ctx->regs + SHADOWCON); + } win_data->enabled = true; } @@ -617,12 +638,10 @@ static void fimd_win_disable(struct device *dev, int zpos) int win = zpos; u32 val; - DRM_DEBUG_KMS("%s\n", __FILE__); - if (win == DEFAULT_ZPOS) win = ctx->default_win; - if (win < 0 || win > WINDOWS_NR) + if (win < 0 || win >= WINDOWS_NR) return; win_data = &ctx->win_data[win]; @@ -634,9 +653,7 @@ static void fimd_win_disable(struct device *dev, int zpos) } /* protect windows */ - val = readl(ctx->regs + SHADOWCON); - val |= SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); + fimd_shadow_protect_win(ctx, win, true); /* wincon */ val = readl(ctx->regs + WINCON(win)); @@ -644,10 +661,13 @@ static void fimd_win_disable(struct device *dev, int zpos) writel(val, ctx->regs + WINCON(win)); /* unprotect windows */ - val = readl(ctx->regs + SHADOWCON); - val &= ~SHADOWCON_CHx_ENABLE(win); - val &= ~SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); + if (ctx->driver_data->has_shadowcon) { + val = readl(ctx->regs + SHADOWCON); + val &= ~SHADOWCON_CHx_ENABLE(win); + writel(val, ctx->regs + SHADOWCON); + } + + fimd_shadow_protect_win(ctx, win, false); win_data->enabled = false; } @@ -697,8 +717,6 @@ out: static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev) { - DRM_DEBUG_KMS("%s\n", __FILE__); - /* * enable drm irq mode. * - with irq_enabled = 1, we can use the vblank feature. @@ -725,8 +743,6 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev) static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev) { - DRM_DEBUG_KMS("%s\n", __FILE__); - /* detach this sub driver from iommu mapping if supported. */ if (is_drm_iommu_supported(drm_dev)) drm_iommu_detach_device(drm_dev, dev); @@ -741,8 +757,6 @@ static int fimd_calc_clkdiv(struct fimd_context *ctx, u32 best_framerate = 0; u32 framerate; - DRM_DEBUG_KMS("%s\n", __FILE__); - retrace = timing->left_margin + timing->hsync_len + timing->right_margin + timing->xres; retrace *= timing->upper_margin + timing->vsync_len + @@ -777,10 +791,6 @@ static int fimd_calc_clkdiv(struct fimd_context *ctx, static void fimd_clear_win(struct fimd_context *ctx, int win) { - u32 val; - - DRM_DEBUG_KMS("%s\n", __FILE__); - writel(0, ctx->regs + WINCON(win)); writel(0, ctx->regs + VIDOSD_A(win)); writel(0, ctx->regs + VIDOSD_B(win)); @@ -789,15 +799,11 @@ static void fimd_clear_win(struct fimd_context *ctx, int win) if (win == 1 || win == 2) writel(0, ctx->regs + VIDOSD_D(win)); - val = readl(ctx->regs + SHADOWCON); - val &= ~SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); + fimd_shadow_protect_win(ctx, win, false); } static int fimd_clock(struct fimd_context *ctx, bool enable) { - DRM_DEBUG_KMS("%s\n", __FILE__); - if (enable) { int ret; @@ -883,8 +889,6 @@ static int fimd_probe(struct platform_device *pdev) int win; int ret = -EINVAL; - DRM_DEBUG_KMS("%s\n", __FILE__); - if (dev->of_node) { pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { @@ -949,6 +953,7 @@ static int fimd_probe(struct platform_device *pdev) return ret; } + ctx->driver_data = drm_fimd_get_driver_data(pdev); ctx->vidcon0 = pdata->vidcon0; ctx->vidcon1 = pdata->vidcon1; ctx->default_win = pdata->default_win; @@ -989,8 +994,6 @@ static int fimd_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct fimd_context *ctx = platform_get_drvdata(pdev); - DRM_DEBUG_KMS("%s\n", __FILE__); - exynos_drm_subdrv_unregister(&ctx->subdrv); if (ctx->suspended) @@ -1055,8 +1058,6 @@ static int fimd_runtime_suspend(struct device *dev) { struct fimd_context *ctx = get_fimd_context(dev); - DRM_DEBUG_KMS("%s\n", __FILE__); - return fimd_activate(ctx, false); } @@ -1064,14 +1065,15 @@ static int fimd_runtime_resume(struct device *dev) { struct fimd_context *ctx = get_fimd_context(dev); - DRM_DEBUG_KMS("%s\n", __FILE__); - return fimd_activate(ctx, true); } #endif static struct platform_device_id fimd_driver_ids[] = { { + .name = "s3c64xx-fb", + .driver_data = (unsigned long)&s3c64xx_fimd_driver_data, + }, { .name = "exynos4-fb", .driver_data = (unsigned long)&exynos4_fimd_driver_data, }, { |