linux/drivers/gpu/drm/exynos/exynos_drm_fimd.c
<<
>>
Prefs
   1/* exynos_drm_fimd.c
   2 *
   3 * Copyright (C) 2011 Samsung Electronics Co.Ltd
   4 * Authors:
   5 *      Joonyoung Shim <jy0922.shim@samsung.com>
   6 *      Inki Dae <inki.dae@samsung.com>
   7 *
   8 * This program is free software; you can redistribute  it and/or modify it
   9 * under  the terms of  the GNU General  Public License as published by the
  10 * Free Software Foundation;  either version 2 of the  License, or (at your
  11 * option) any later version.
  12 *
  13 */
  14#include <drm/drmP.h>
  15
  16#include <linux/kernel.h>
  17#include <linux/platform_device.h>
  18#include <linux/clk.h>
  19#include <linux/of.h>
  20#include <linux/of_device.h>
  21#include <linux/pm_runtime.h>
  22#include <linux/component.h>
  23#include <linux/mfd/syscon.h>
  24#include <linux/regmap.h>
  25
  26#include <video/of_display_timing.h>
  27#include <video/of_videomode.h>
  28#include <video/samsung_fimd.h>
  29#include <drm/exynos_drm.h>
  30
  31#include "exynos_drm_drv.h"
  32#include "exynos_drm_fb.h"
  33#include "exynos_drm_crtc.h"
  34#include "exynos_drm_plane.h"
  35#include "exynos_drm_iommu.h"
  36
  37/*
  38 * FIMD stands for Fully Interactive Mobile Display and
  39 * as a display controller, it transfers contents drawn on memory
  40 * to a LCD Panel through Display Interfaces such as RGB or
  41 * CPU Interface.
  42 */
  43
  44#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
  45
  46/* position control register for hardware window 0, 2 ~ 4.*/
  47#define VIDOSD_A(win)           (VIDOSD_BASE + 0x00 + (win) * 16)
  48#define VIDOSD_B(win)           (VIDOSD_BASE + 0x04 + (win) * 16)
  49/*
  50 * size control register for hardware windows 0 and alpha control register
  51 * for hardware windows 1 ~ 4
  52 */
  53#define VIDOSD_C(win)           (VIDOSD_BASE + 0x08 + (win) * 16)
  54/* size control register for hardware windows 1 ~ 2. */
  55#define VIDOSD_D(win)           (VIDOSD_BASE + 0x0C + (win) * 16)
  56
  57#define VIDWnALPHA0(win)        (VIDW_ALPHA + 0x00 + (win) * 8)
  58#define VIDWnALPHA1(win)        (VIDW_ALPHA + 0x04 + (win) * 8)
  59
  60#define VIDWx_BUF_START(win, buf)       (VIDW_BUF_START(buf) + (win) * 8)
  61#define VIDWx_BUF_START_S(win, buf)     (VIDW_BUF_START_S(buf) + (win) * 8)
  62#define VIDWx_BUF_END(win, buf)         (VIDW_BUF_END(buf) + (win) * 8)
  63#define VIDWx_BUF_SIZE(win, buf)        (VIDW_BUF_SIZE(buf) + (win) * 4)
  64
  65/* color key control register for hardware window 1 ~ 4. */
  66#define WKEYCON0_BASE(x)                ((WKEYCON0 + 0x140) + ((x - 1) * 8))
  67/* color key value register for hardware window 1 ~ 4. */
  68#define WKEYCON1_BASE(x)                ((WKEYCON1 + 0x140) + ((x - 1) * 8))
  69
  70/* I80 trigger control register */
  71#define TRIGCON                         0x1A4
  72#define TRGMODE_ENABLE                  (1 << 0)
  73#define SWTRGCMD_ENABLE                 (1 << 1)
  74/* Exynos3250, 3472, 4415, 5260 5410, 5420 and 5422 only supported. */
  75#define HWTRGEN_ENABLE                  (1 << 3)
  76#define HWTRGMASK_ENABLE                (1 << 4)
  77/* Exynos3250, 3472, 4415, 5260, 5420 and 5422 only supported. */
  78#define HWTRIGEN_PER_ENABLE             (1 << 31)
  79
  80/* display mode change control register except exynos4 */
  81#define VIDOUT_CON                      0x000
  82#define VIDOUT_CON_F_I80_LDI0           (0x2 << 8)
  83
  84/* I80 interface control for main LDI register */
  85#define I80IFCONFAx(x)                  (0x1B0 + (x) * 4)
  86#define I80IFCONFBx(x)                  (0x1B8 + (x) * 4)
  87#define LCD_CS_SETUP(x)                 ((x) << 16)
  88#define LCD_WR_SETUP(x)                 ((x) << 12)
  89#define LCD_WR_ACTIVE(x)                ((x) << 8)
  90#define LCD_WR_HOLD(x)                  ((x) << 4)
  91#define I80IFEN_ENABLE                  (1 << 0)
  92
  93/* FIMD has totally five hardware windows. */
  94#define WINDOWS_NR      5
  95
  96/* HW trigger flag on i80 panel. */
  97#define I80_HW_TRG     (1 << 1)
  98
  99struct fimd_driver_data {
 100        unsigned int timing_base;
 101        unsigned int lcdblk_offset;
 102        unsigned int lcdblk_vt_shift;
 103        unsigned int lcdblk_bypass_shift;
 104        unsigned int lcdblk_mic_bypass_shift;
 105        unsigned int trg_type;
 106
 107        unsigned int has_shadowcon:1;
 108        unsigned int has_clksel:1;
 109        unsigned int has_limited_fmt:1;
 110        unsigned int has_vidoutcon:1;
 111        unsigned int has_vtsel:1;
 112        unsigned int has_mic_bypass:1;
 113        unsigned int has_dp_clk:1;
 114        unsigned int has_hw_trigger:1;
 115        unsigned int has_trigger_per_te:1;
 116};
 117
 118static struct fimd_driver_data s3c64xx_fimd_driver_data = {
 119        .timing_base = 0x0,
 120        .has_clksel = 1,
 121        .has_limited_fmt = 1,
 122};
 123
 124static struct fimd_driver_data exynos3_fimd_driver_data = {
 125        .timing_base = 0x20000,
 126        .lcdblk_offset = 0x210,
 127        .lcdblk_bypass_shift = 1,
 128        .trg_type = I80_HW_TRG,
 129        .has_shadowcon = 1,
 130        .has_vidoutcon = 1,
 131        .has_trigger_per_te = 1,
 132};
 133
 134static struct fimd_driver_data exynos4_fimd_driver_data = {
 135        .timing_base = 0x0,
 136        .lcdblk_offset = 0x210,
 137        .lcdblk_vt_shift = 10,
 138        .lcdblk_bypass_shift = 1,
 139        .has_shadowcon = 1,
 140        .has_vtsel = 1,
 141};
 142
 143static struct fimd_driver_data exynos4415_fimd_driver_data = {
 144        .timing_base = 0x20000,
 145        .lcdblk_offset = 0x210,
 146        .lcdblk_vt_shift = 10,
 147        .lcdblk_bypass_shift = 1,
 148        .trg_type = I80_HW_TRG,
 149        .has_shadowcon = 1,
 150        .has_vidoutcon = 1,
 151        .has_vtsel = 1,
 152        .has_trigger_per_te = 1,
 153};
 154
 155static struct fimd_driver_data exynos5_fimd_driver_data = {
 156        .timing_base = 0x20000,
 157        .lcdblk_offset = 0x214,
 158        .lcdblk_vt_shift = 24,
 159        .lcdblk_bypass_shift = 15,
 160        .has_shadowcon = 1,
 161        .has_vidoutcon = 1,
 162        .has_vtsel = 1,
 163        .has_dp_clk = 1,
 164};
 165
 166static struct fimd_driver_data exynos5420_fimd_driver_data = {
 167        .timing_base = 0x20000,
 168        .lcdblk_offset = 0x214,
 169        .lcdblk_vt_shift = 24,
 170        .lcdblk_bypass_shift = 15,
 171        .lcdblk_mic_bypass_shift = 11,
 172        .has_shadowcon = 1,
 173        .has_vidoutcon = 1,
 174        .has_vtsel = 1,
 175        .has_mic_bypass = 1,
 176        .has_dp_clk = 1,
 177};
 178
 179struct fimd_context {
 180        struct device                   *dev;
 181        struct drm_device               *drm_dev;
 182        struct exynos_drm_crtc          *crtc;
 183        struct exynos_drm_plane         planes[WINDOWS_NR];
 184        struct exynos_drm_plane_config  configs[WINDOWS_NR];
 185        struct clk                      *bus_clk;
 186        struct clk                      *lcd_clk;
 187        void __iomem                    *regs;
 188        struct regmap                   *sysreg;
 189        unsigned long                   irq_flags;
 190        u32                             vidcon0;
 191        u32                             vidcon1;
 192        u32                             vidout_con;
 193        u32                             i80ifcon;
 194        bool                            i80_if;
 195        bool                            suspended;
 196        int                             pipe;
 197        wait_queue_head_t               wait_vsync_queue;
 198        atomic_t                        wait_vsync_event;
 199        atomic_t                        win_updated;
 200        atomic_t                        triggering;
 201        u32                             clkdiv;
 202
 203        const struct fimd_driver_data *driver_data;
 204        struct drm_encoder *encoder;
 205        struct exynos_drm_clk           dp_clk;
 206};
 207
 208static const struct of_device_id fimd_driver_dt_match[] = {
 209        { .compatible = "samsung,s3c6400-fimd",
 210          .data = &s3c64xx_fimd_driver_data },
 211        { .compatible = "samsung,exynos3250-fimd",
 212          .data = &exynos3_fimd_driver_data },
 213        { .compatible = "samsung,exynos4210-fimd",
 214          .data = &exynos4_fimd_driver_data },
 215        { .compatible = "samsung,exynos4415-fimd",
 216          .data = &exynos4415_fimd_driver_data },
 217        { .compatible = "samsung,exynos5250-fimd",
 218          .data = &exynos5_fimd_driver_data },
 219        { .compatible = "samsung,exynos5420-fimd",
 220          .data = &exynos5420_fimd_driver_data },
 221        {},
 222};
 223MODULE_DEVICE_TABLE(of, fimd_driver_dt_match);
 224
 225static const enum drm_plane_type fimd_win_types[WINDOWS_NR] = {
 226        DRM_PLANE_TYPE_PRIMARY,
 227        DRM_PLANE_TYPE_OVERLAY,
 228        DRM_PLANE_TYPE_OVERLAY,
 229        DRM_PLANE_TYPE_OVERLAY,
 230        DRM_PLANE_TYPE_CURSOR,
 231};
 232
 233static const uint32_t fimd_formats[] = {
 234        DRM_FORMAT_C8,
 235        DRM_FORMAT_XRGB1555,
 236        DRM_FORMAT_RGB565,
 237        DRM_FORMAT_XRGB8888,
 238        DRM_FORMAT_ARGB8888,
 239};
 240
 241static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
 242{
 243        struct fimd_context *ctx = crtc->ctx;
 244        u32 val;
 245
 246        if (ctx->suspended)
 247                return -EPERM;
 248
 249        if (!test_and_set_bit(0, &ctx->irq_flags)) {
 250                val = readl(ctx->regs + VIDINTCON0);
 251
 252                val |= VIDINTCON0_INT_ENABLE;
 253
 254                if (ctx->i80_if) {
 255                        val |= VIDINTCON0_INT_I80IFDONE;
 256                        val |= VIDINTCON0_INT_SYSMAINCON;
 257                        val &= ~VIDINTCON0_INT_SYSSUBCON;
 258                } else {
 259                        val |= VIDINTCON0_INT_FRAME;
 260
 261                        val &= ~VIDINTCON0_FRAMESEL0_MASK;
 262                        val |= VIDINTCON0_FRAMESEL0_VSYNC;
 263                        val &= ~VIDINTCON0_FRAMESEL1_MASK;
 264                        val |= VIDINTCON0_FRAMESEL1_NONE;
 265                }
 266
 267                writel(val, ctx->regs + VIDINTCON0);
 268        }
 269
 270        return 0;
 271}
 272
 273static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
 274{
 275        struct fimd_context *ctx = crtc->ctx;
 276        u32 val;
 277
 278        if (ctx->suspended)
 279                return;
 280
 281        if (test_and_clear_bit(0, &ctx->irq_flags)) {
 282                val = readl(ctx->regs + VIDINTCON0);
 283
 284                val &= ~VIDINTCON0_INT_ENABLE;
 285
 286                if (ctx->i80_if) {
 287                        val &= ~VIDINTCON0_INT_I80IFDONE;
 288                        val &= ~VIDINTCON0_INT_SYSMAINCON;
 289                        val &= ~VIDINTCON0_INT_SYSSUBCON;
 290                } else
 291                        val &= ~VIDINTCON0_INT_FRAME;
 292
 293                writel(val, ctx->regs + VIDINTCON0);
 294        }
 295}
 296
 297static void fimd_wait_for_vblank(struct exynos_drm_crtc *crtc)
 298{
 299        struct fimd_context *ctx = crtc->ctx;
 300
 301        if (ctx->suspended)
 302                return;
 303
 304        atomic_set(&ctx->wait_vsync_event, 1);
 305
 306        /*
 307         * wait for FIMD to signal VSYNC interrupt or return after
 308         * timeout which is set to 50ms (refresh rate of 20).
 309         */
 310        if (!wait_event_timeout(ctx->wait_vsync_queue,
 311                                !atomic_read(&ctx->wait_vsync_event),
 312                                HZ/20))
 313                DRM_DEBUG_KMS("vblank wait timed out.\n");
 314}
 315
 316static void fimd_enable_video_output(struct fimd_context *ctx, unsigned int win,
 317                                        bool enable)
 318{
 319        u32 val = readl(ctx->regs + WINCON(win));
 320
 321        if (enable)
 322                val |= WINCONx_ENWIN;
 323        else
 324                val &= ~WINCONx_ENWIN;
 325
 326        writel(val, ctx->regs + WINCON(win));
 327}
 328
 329static void fimd_enable_shadow_channel_path(struct fimd_context *ctx,
 330                                                unsigned int win,
 331                                                bool enable)
 332{
 333        u32 val = readl(ctx->regs + SHADOWCON);
 334
 335        if (enable)
 336                val |= SHADOWCON_CHx_ENABLE(win);
 337        else
 338                val &= ~SHADOWCON_CHx_ENABLE(win);
 339
 340        writel(val, ctx->regs + SHADOWCON);
 341}
 342
 343static void fimd_clear_channels(struct exynos_drm_crtc *crtc)
 344{
 345        struct fimd_context *ctx = crtc->ctx;
 346        unsigned int win, ch_enabled = 0;
 347
 348        DRM_DEBUG_KMS("%s\n", __FILE__);
 349
 350        /* Hardware is in unknown state, so ensure it gets enabled properly */
 351        pm_runtime_get_sync(ctx->dev);
 352
 353        clk_prepare_enable(ctx->bus_clk);
 354        clk_prepare_enable(ctx->lcd_clk);
 355
 356        /* Check if any channel is enabled. */
 357        for (win = 0; win < WINDOWS_NR; win++) {
 358                u32 val = readl(ctx->regs + WINCON(win));
 359
 360                if (val & WINCONx_ENWIN) {
 361                        fimd_enable_video_output(ctx, win, false);
 362
 363                        if (ctx->driver_data->has_shadowcon)
 364                                fimd_enable_shadow_channel_path(ctx, win,
 365                                                                false);
 366
 367                        ch_enabled = 1;
 368                }
 369        }
 370
 371        /* Wait for vsync, as disable channel takes effect at next vsync */
 372        if (ch_enabled) {
 373                int pipe = ctx->pipe;
 374
 375                /* ensure that vblank interrupt won't be reported to core */
 376                ctx->suspended = false;
 377                ctx->pipe = -1;
 378
 379                fimd_enable_vblank(ctx->crtc);
 380                fimd_wait_for_vblank(ctx->crtc);
 381                fimd_disable_vblank(ctx->crtc);
 382
 383                ctx->suspended = true;
 384                ctx->pipe = pipe;
 385        }
 386
 387        clk_disable_unprepare(ctx->lcd_clk);
 388        clk_disable_unprepare(ctx->bus_clk);
 389
 390        pm_runtime_put(ctx->dev);
 391}
 392
 393
 394static int fimd_atomic_check(struct exynos_drm_crtc *crtc,
 395                struct drm_crtc_state *state)
 396{
 397        struct drm_display_mode *mode = &state->adjusted_mode;
 398        struct fimd_context *ctx = crtc->ctx;
 399        unsigned long ideal_clk, lcd_rate;
 400        u32 clkdiv;
 401
 402        if (mode->clock == 0) {
 403                DRM_INFO("Mode has zero clock value.\n");
 404                return -EINVAL;
 405        }
 406
 407        ideal_clk = mode->clock * 1000;
 408
 409        if (ctx->i80_if) {
 410                /*
 411                 * The frame done interrupt should be occurred prior to the
 412                 * next TE signal.
 413                 */
 414                ideal_clk *= 2;
 415        }
 416
 417        lcd_rate = clk_get_rate(ctx->lcd_clk);
 418        if (2 * lcd_rate < ideal_clk) {
 419                DRM_INFO("sclk_fimd clock too low(%lu) for requested pixel clock(%lu)\n",
 420                         lcd_rate, ideal_clk);
 421                return -EINVAL;
 422        }
 423
 424        /* Find the clock divider value that gets us closest to ideal_clk */
 425        clkdiv = DIV_ROUND_CLOSEST(lcd_rate, ideal_clk);
 426        if (clkdiv >= 0x200) {
 427                DRM_INFO("requested pixel clock(%lu) too low\n", ideal_clk);
 428                return -EINVAL;
 429        }
 430
 431        ctx->clkdiv = (clkdiv < 0x100) ? clkdiv : 0xff;
 432
 433        return 0;
 434}
 435
 436static void fimd_setup_trigger(struct fimd_context *ctx)
 437{
 438        void __iomem *timing_base = ctx->regs + ctx->driver_data->timing_base;
 439        u32 trg_type = ctx->driver_data->trg_type;
 440        u32 val = readl(timing_base + TRIGCON);
 441
 442        val &= ~(TRGMODE_ENABLE);
 443
 444        if (trg_type == I80_HW_TRG) {
 445                if (ctx->driver_data->has_hw_trigger)
 446                        val |= HWTRGEN_ENABLE | HWTRGMASK_ENABLE;
 447                if (ctx->driver_data->has_trigger_per_te)
 448                        val |= HWTRIGEN_PER_ENABLE;
 449        } else {
 450                val |= TRGMODE_ENABLE;
 451        }
 452
 453        writel(val, timing_base + TRIGCON);
 454}
 455
 456static void fimd_commit(struct exynos_drm_crtc *crtc)
 457{
 458        struct fimd_context *ctx = crtc->ctx;
 459        struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
 460        const struct fimd_driver_data *driver_data = ctx->driver_data;
 461        void *timing_base = ctx->regs + driver_data->timing_base;
 462        u32 val;
 463
 464        if (ctx->suspended)
 465                return;
 466
 467        /* nothing to do if we haven't set the mode yet */
 468        if (mode->htotal == 0 || mode->vtotal == 0)
 469                return;
 470
 471        if (ctx->i80_if) {
 472                val = ctx->i80ifcon | I80IFEN_ENABLE;
 473                writel(val, timing_base + I80IFCONFAx(0));
 474
 475                /* disable auto frame rate */
 476                writel(0, timing_base + I80IFCONFBx(0));
 477
 478                /* set video type selection to I80 interface */
 479                if (driver_data->has_vtsel && ctx->sysreg &&
 480                                regmap_update_bits(ctx->sysreg,
 481                                        driver_data->lcdblk_offset,
 482                                        0x3 << driver_data->lcdblk_vt_shift,
 483                                        0x1 << driver_data->lcdblk_vt_shift)) {
 484                        DRM_ERROR("Failed to update sysreg for I80 i/f.\n");
 485                        return;
 486                }
 487        } else {
 488                int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
 489                u32 vidcon1;
 490
 491                /* setup polarity values */
 492                vidcon1 = ctx->vidcon1;
 493                if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 494                        vidcon1 |= VIDCON1_INV_VSYNC;
 495                if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 496                        vidcon1 |= VIDCON1_INV_HSYNC;
 497                writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
 498
 499                /* setup vertical timing values. */
 500                vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
 501                vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
 502                vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
 503
 504                val = VIDTCON0_VBPD(vbpd - 1) |
 505                        VIDTCON0_VFPD(vfpd - 1) |
 506                        VIDTCON0_VSPW(vsync_len - 1);
 507                writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
 508
 509                /* setup horizontal timing values.  */
 510                hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
 511                hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
 512                hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
 513
 514                val = VIDTCON1_HBPD(hbpd - 1) |
 515                        VIDTCON1_HFPD(hfpd - 1) |
 516                        VIDTCON1_HSPW(hsync_len - 1);
 517                writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
 518        }
 519
 520        if (driver_data->has_vidoutcon)
 521                writel(ctx->vidout_con, timing_base + VIDOUT_CON);
 522
 523        /* set bypass selection */
 524        if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
 525                                driver_data->lcdblk_offset,
 526                                0x1 << driver_data->lcdblk_bypass_shift,
 527                                0x1 << driver_data->lcdblk_bypass_shift)) {
 528                DRM_ERROR("Failed to update sysreg for bypass setting.\n");
 529                return;
 530        }
 531
 532        /* TODO: When MIC is enabled for display path, the lcdblk_mic_bypass
 533         * bit should be cleared.
 534         */
 535        if (driver_data->has_mic_bypass && ctx->sysreg &&
 536            regmap_update_bits(ctx->sysreg,
 537                                driver_data->lcdblk_offset,
 538                                0x1 << driver_data->lcdblk_mic_bypass_shift,
 539                                0x1 << driver_data->lcdblk_mic_bypass_shift)) {
 540                DRM_ERROR("Failed to update sysreg for bypass mic.\n");
 541                return;
 542        }
 543
 544        /* setup horizontal and vertical display size. */
 545        val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
 546               VIDTCON2_HOZVAL(mode->hdisplay - 1) |
 547               VIDTCON2_LINEVAL_E(mode->vdisplay - 1) |
 548               VIDTCON2_HOZVAL_E(mode->hdisplay - 1);
 549        writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
 550
 551        fimd_setup_trigger(ctx);
 552
 553        /*
 554         * fields of register with prefix '_F' would be updated
 555         * at vsync(same as dma start)
 556         */
 557        val = ctx->vidcon0;
 558        val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
 559
 560        if (ctx->driver_data->has_clksel)
 561                val |= VIDCON0_CLKSEL_LCD;
 562
 563        if (ctx->clkdiv > 1)
 564                val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
 565
 566        writel(val, ctx->regs + VIDCON0);
 567}
 568
 569
 570static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
 571                                uint32_t pixel_format, int width)
 572{
 573        unsigned long val;
 574
 575        val = WINCONx_ENWIN;
 576
 577        /*
 578         * In case of s3c64xx, window 0 doesn't support alpha channel.
 579         * So the request format is ARGB8888 then change it to XRGB8888.
 580         */
 581        if (ctx->driver_data->has_limited_fmt && !win) {
 582                if (pixel_format == DRM_FORMAT_ARGB8888)
 583                        pixel_format = DRM_FORMAT_XRGB8888;
 584        }
 585
 586        switch (pixel_format) {
 587        case DRM_FORMAT_C8:
 588                val |= WINCON0_BPPMODE_8BPP_PALETTE;
 589                val |= WINCONx_BURSTLEN_8WORD;
 590                val |= WINCONx_BYTSWP;
 591                break;
 592        case DRM_FORMAT_XRGB1555:
 593                val |= WINCON0_BPPMODE_16BPP_1555;
 594                val |= WINCONx_HAWSWP;
 595                val |= WINCONx_BURSTLEN_16WORD;
 596                break;
 597        case DRM_FORMAT_RGB565:
 598                val |= WINCON0_BPPMODE_16BPP_565;
 599                val |= WINCONx_HAWSWP;
 600                val |= WINCONx_BURSTLEN_16WORD;
 601                break;
 602        case DRM_FORMAT_XRGB8888:
 603                val |= WINCON0_BPPMODE_24BPP_888;
 604                val |= WINCONx_WSWP;
 605                val |= WINCONx_BURSTLEN_16WORD;
 606                break;
 607        case DRM_FORMAT_ARGB8888:
 608                val |= WINCON1_BPPMODE_25BPP_A1888
 609                        | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
 610                val |= WINCONx_WSWP;
 611                val |= WINCONx_BURSTLEN_16WORD;
 612                break;
 613        default:
 614                DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
 615
 616                val |= WINCON0_BPPMODE_24BPP_888;
 617                val |= WINCONx_WSWP;
 618                val |= WINCONx_BURSTLEN_16WORD;
 619                break;
 620        }
 621
 622        /*
 623         * Setting dma-burst to 16Word causes permanent tearing for very small
 624         * buffers, e.g. cursor buffer. Burst Mode switching which based on
 625         * plane size is not recommended as plane size varies alot towards the
 626         * end of the screen and rapid movement causes unstable DMA, but it is
 627         * still better to change dma-burst than displaying garbage.
 628         */
 629
 630        if (width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
 631                val &= ~WINCONx_BURSTLEN_MASK;
 632                val |= WINCONx_BURSTLEN_4WORD;
 633        }
 634
 635        writel(val, ctx->regs + WINCON(win));
 636
 637        /* hardware window 0 doesn't support alpha channel. */
 638        if (win != 0) {
 639                /* OSD alpha */
 640                val = VIDISD14C_ALPHA0_R(0xf) |
 641                        VIDISD14C_ALPHA0_G(0xf) |
 642                        VIDISD14C_ALPHA0_B(0xf) |
 643                        VIDISD14C_ALPHA1_R(0xf) |
 644                        VIDISD14C_ALPHA1_G(0xf) |
 645                        VIDISD14C_ALPHA1_B(0xf);
 646
 647                writel(val, ctx->regs + VIDOSD_C(win));
 648
 649                val = VIDW_ALPHA_R(0xf) | VIDW_ALPHA_G(0xf) |
 650                        VIDW_ALPHA_G(0xf);
 651                writel(val, ctx->regs + VIDWnALPHA0(win));
 652                writel(val, ctx->regs + VIDWnALPHA1(win));
 653        }
 654}
 655
 656static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win)
 657{
 658        unsigned int keycon0 = 0, keycon1 = 0;
 659
 660        keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
 661                        WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
 662
 663        keycon1 = WxKEYCON1_COLVAL(0xffffffff);
 664
 665        writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
 666        writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
 667}
 668
 669/**
 670 * shadow_protect_win() - disable updating values from shadow registers at vsync
 671 *
 672 * @win: window to protect registers for
 673 * @protect: 1 to protect (disable updates)
 674 */
 675static void fimd_shadow_protect_win(struct fimd_context *ctx,
 676                                    unsigned int win, bool protect)
 677{
 678        u32 reg, bits, val;
 679
 680        /*
 681         * SHADOWCON/PRTCON register is used for enabling timing.
 682         *
 683         * for example, once only width value of a register is set,
 684         * if the dma is started then fimd hardware could malfunction so
 685         * with protect window setting, the register fields with prefix '_F'
 686         * wouldn't be updated at vsync also but updated once unprotect window
 687         * is set.
 688         */
 689
 690        if (ctx->driver_data->has_shadowcon) {
 691                reg = SHADOWCON;
 692                bits = SHADOWCON_WINx_PROTECT(win);
 693        } else {
 694                reg = PRTCON;
 695                bits = PRTCON_PROTECT;
 696        }
 697
 698        val = readl(ctx->regs + reg);
 699        if (protect)
 700                val |= bits;
 701        else
 702                val &= ~bits;
 703        writel(val, ctx->regs + reg);
 704}
 705
 706static void fimd_atomic_begin(struct exynos_drm_crtc *crtc)
 707{
 708        struct fimd_context *ctx = crtc->ctx;
 709        int i;
 710
 711        if (ctx->suspended)
 712                return;
 713
 714        for (i = 0; i < WINDOWS_NR; i++)
 715                fimd_shadow_protect_win(ctx, i, true);
 716}
 717
 718static void fimd_atomic_flush(struct exynos_drm_crtc *crtc)
 719{
 720        struct fimd_context *ctx = crtc->ctx;
 721        int i;
 722
 723        if (ctx->suspended)
 724                return;
 725
 726        for (i = 0; i < WINDOWS_NR; i++)
 727                fimd_shadow_protect_win(ctx, i, false);
 728}
 729
 730static void fimd_update_plane(struct exynos_drm_crtc *crtc,
 731                              struct exynos_drm_plane *plane)
 732{
 733        struct exynos_drm_plane_state *state =
 734                                to_exynos_plane_state(plane->base.state);
 735        struct fimd_context *ctx = crtc->ctx;
 736        struct drm_framebuffer *fb = state->base.fb;
 737        dma_addr_t dma_addr;
 738        unsigned long val, size, offset;
 739        unsigned int last_x, last_y, buf_offsize, line_size;
 740        unsigned int win = plane->index;
 741        unsigned int bpp = fb->bits_per_pixel >> 3;
 742        unsigned int pitch = fb->pitches[0];
 743
 744        if (ctx->suspended)
 745                return;
 746
 747        offset = state->src.x * bpp;
 748        offset += state->src.y * pitch;
 749
 750        /* buffer start address */
 751        dma_addr = exynos_drm_fb_dma_addr(fb, 0) + offset;
 752        val = (unsigned long)dma_addr;
 753        writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 754
 755        /* buffer end address */
 756        size = pitch * state->crtc.h;
 757        val = (unsigned long)(dma_addr + size);
 758        writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
 759
 760        DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
 761                        (unsigned long)dma_addr, val, size);
 762        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
 763                        state->crtc.w, state->crtc.h);
 764
 765        /* buffer size */
 766        buf_offsize = pitch - (state->crtc.w * bpp);
 767        line_size = state->crtc.w * bpp;
 768        val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
 769                VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
 770                VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
 771                VIDW_BUF_SIZE_PAGEWIDTH_E(line_size);
 772        writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
 773
 774        /* OSD position */
 775        val = VIDOSDxA_TOPLEFT_X(state->crtc.x) |
 776                VIDOSDxA_TOPLEFT_Y(state->crtc.y) |
 777                VIDOSDxA_TOPLEFT_X_E(state->crtc.x) |
 778                VIDOSDxA_TOPLEFT_Y_E(state->crtc.y);
 779        writel(val, ctx->regs + VIDOSD_A(win));
 780
 781        last_x = state->crtc.x + state->crtc.w;
 782        if (last_x)
 783                last_x--;
 784        last_y = state->crtc.y + state->crtc.h;
 785        if (last_y)
 786                last_y--;
 787
 788        val = VIDOSDxB_BOTRIGHT_X(last_x) | VIDOSDxB_BOTRIGHT_Y(last_y) |
 789                VIDOSDxB_BOTRIGHT_X_E(last_x) | VIDOSDxB_BOTRIGHT_Y_E(last_y);
 790
 791        writel(val, ctx->regs + VIDOSD_B(win));
 792
 793        DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
 794                        state->crtc.x, state->crtc.y, last_x, last_y);
 795
 796        /* OSD size */
 797        if (win != 3 && win != 4) {
 798                u32 offset = VIDOSD_D(win);
 799                if (win == 0)
 800                        offset = VIDOSD_C(win);
 801                val = state->crtc.w * state->crtc.h;
 802                writel(val, ctx->regs + offset);
 803
 804                DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
 805        }
 806
 807        fimd_win_set_pixfmt(ctx, win, fb->pixel_format, state->src.w);
 808
 809        /* hardware window 0 doesn't support color key. */
 810        if (win != 0)
 811                fimd_win_set_colkey(ctx, win);
 812
 813        fimd_enable_video_output(ctx, win, true);
 814
 815        if (ctx->driver_data->has_shadowcon)
 816                fimd_enable_shadow_channel_path(ctx, win, true);
 817
 818        if (ctx->i80_if)
 819                atomic_set(&ctx->win_updated, 1);
 820}
 821
 822static void fimd_disable_plane(struct exynos_drm_crtc *crtc,
 823                               struct exynos_drm_plane *plane)
 824{
 825        struct fimd_context *ctx = crtc->ctx;
 826        unsigned int win = plane->index;
 827
 828        if (ctx->suspended)
 829                return;
 830
 831        fimd_enable_video_output(ctx, win, false);
 832
 833        if (ctx->driver_data->has_shadowcon)
 834                fimd_enable_shadow_channel_path(ctx, win, false);
 835}
 836
 837static void fimd_enable(struct exynos_drm_crtc *crtc)
 838{
 839        struct fimd_context *ctx = crtc->ctx;
 840
 841        if (!ctx->suspended)
 842                return;
 843
 844        ctx->suspended = false;
 845
 846        pm_runtime_get_sync(ctx->dev);
 847
 848        /* if vblank was enabled status, enable it again. */
 849        if (test_and_clear_bit(0, &ctx->irq_flags))
 850                fimd_enable_vblank(ctx->crtc);
 851
 852        fimd_commit(ctx->crtc);
 853}
 854
 855static void fimd_disable(struct exynos_drm_crtc *crtc)
 856{
 857        struct fimd_context *ctx = crtc->ctx;
 858        int i;
 859
 860        if (ctx->suspended)
 861                return;
 862
 863        /*
 864         * We need to make sure that all windows are disabled before we
 865         * suspend that connector. Otherwise we might try to scan from
 866         * a destroyed buffer later.
 867         */
 868        for (i = 0; i < WINDOWS_NR; i++)
 869                fimd_disable_plane(crtc, &ctx->planes[i]);
 870
 871        fimd_enable_vblank(crtc);
 872        fimd_wait_for_vblank(crtc);
 873        fimd_disable_vblank(crtc);
 874
 875        writel(0, ctx->regs + VIDCON0);
 876
 877        pm_runtime_put_sync(ctx->dev);
 878        ctx->suspended = true;
 879}
 880
 881static void fimd_trigger(struct device *dev)
 882{
 883        struct fimd_context *ctx = dev_get_drvdata(dev);
 884        const struct fimd_driver_data *driver_data = ctx->driver_data;
 885        void *timing_base = ctx->regs + driver_data->timing_base;
 886        u32 reg;
 887
 888         /*
 889          * Skips triggering if in triggering state, because multiple triggering
 890          * requests can cause panel reset.
 891          */
 892        if (atomic_read(&ctx->triggering))
 893                return;
 894
 895        /* Enters triggering mode */
 896        atomic_set(&ctx->triggering, 1);
 897
 898        reg = readl(timing_base + TRIGCON);
 899        reg |= (TRGMODE_ENABLE | SWTRGCMD_ENABLE);
 900        writel(reg, timing_base + TRIGCON);
 901
 902        /*
 903         * Exits triggering mode if vblank is not enabled yet, because when the
 904         * VIDINTCON0 register is not set, it can not exit from triggering mode.
 905         */
 906        if (!test_bit(0, &ctx->irq_flags))
 907                atomic_set(&ctx->triggering, 0);
 908}
 909
 910static void fimd_te_handler(struct exynos_drm_crtc *crtc)
 911{
 912        struct fimd_context *ctx = crtc->ctx;
 913        u32 trg_type = ctx->driver_data->trg_type;
 914
 915        /* Checks the crtc is detached already from encoder */
 916        if (ctx->pipe < 0 || !ctx->drm_dev)
 917                return;
 918
 919        if (trg_type == I80_HW_TRG)
 920                goto out;
 921
 922        /*
 923         * If there is a page flip request, triggers and handles the page flip
 924         * event so that current fb can be updated into panel GRAM.
 925         */
 926        if (atomic_add_unless(&ctx->win_updated, -1, 0))
 927                fimd_trigger(ctx->dev);
 928
 929out:
 930        /* Wakes up vsync event queue */
 931        if (atomic_read(&ctx->wait_vsync_event)) {
 932                atomic_set(&ctx->wait_vsync_event, 0);
 933                wake_up(&ctx->wait_vsync_queue);
 934        }
 935
 936        if (test_bit(0, &ctx->irq_flags))
 937                drm_crtc_handle_vblank(&ctx->crtc->base);
 938}
 939
 940static void fimd_dp_clock_enable(struct exynos_drm_clk *clk, bool enable)
 941{
 942        struct fimd_context *ctx = container_of(clk, struct fimd_context,
 943                                                dp_clk);
 944        u32 val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
 945        writel(val, ctx->regs + DP_MIE_CLKCON);
 946}
 947
 948static const struct exynos_drm_crtc_ops fimd_crtc_ops = {
 949        .enable = fimd_enable,
 950        .disable = fimd_disable,
 951        .commit = fimd_commit,
 952        .enable_vblank = fimd_enable_vblank,
 953        .disable_vblank = fimd_disable_vblank,
 954        .atomic_begin = fimd_atomic_begin,
 955        .update_plane = fimd_update_plane,
 956        .disable_plane = fimd_disable_plane,
 957        .atomic_flush = fimd_atomic_flush,
 958        .atomic_check = fimd_atomic_check,
 959        .te_handler = fimd_te_handler,
 960};
 961
 962static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
 963{
 964        struct fimd_context *ctx = (struct fimd_context *)dev_id;
 965        u32 val, clear_bit;
 966
 967        val = readl(ctx->regs + VIDINTCON1);
 968
 969        clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME;
 970        if (val & clear_bit)
 971                writel(clear_bit, ctx->regs + VIDINTCON1);
 972
 973        /* check the crtc is detached already from encoder */
 974        if (ctx->pipe < 0 || !ctx->drm_dev)
 975                goto out;
 976
 977        if (!ctx->i80_if)
 978                drm_crtc_handle_vblank(&ctx->crtc->base);
 979
 980        if (ctx->i80_if) {
 981                /* Exits triggering mode */
 982                atomic_set(&ctx->triggering, 0);
 983        } else {
 984                /* set wait vsync event to zero and wake up queue. */
 985                if (atomic_read(&ctx->wait_vsync_event)) {
 986                        atomic_set(&ctx->wait_vsync_event, 0);
 987                        wake_up(&ctx->wait_vsync_queue);
 988                }
 989        }
 990
 991out:
 992        return IRQ_HANDLED;
 993}
 994
 995static int fimd_bind(struct device *dev, struct device *master, void *data)
 996{
 997        struct fimd_context *ctx = dev_get_drvdata(dev);
 998        struct drm_device *drm_dev = data;
 999        struct exynos_drm_private *priv = drm_dev->dev_private;
1000        struct exynos_drm_plane *exynos_plane;
1001        unsigned int i;
1002        int ret;
1003
1004        ctx->drm_dev = drm_dev;
1005        ctx->pipe = priv->pipe++;
1006
1007        for (i = 0; i < WINDOWS_NR; i++) {
1008                ctx->configs[i].pixel_formats = fimd_formats;
1009                ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats);
1010                ctx->configs[i].zpos = i;
1011                ctx->configs[i].type = fimd_win_types[i];
1012                ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
1013                                        1 << ctx->pipe, &ctx->configs[i]);
1014                if (ret)
1015                        return ret;
1016        }
1017
1018        exynos_plane = &ctx->planes[DEFAULT_WIN];
1019        ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1020                                           ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
1021                                           &fimd_crtc_ops, ctx);
1022        if (IS_ERR(ctx->crtc))
1023                return PTR_ERR(ctx->crtc);
1024
1025        if (ctx->driver_data->has_dp_clk) {
1026                ctx->dp_clk.enable = fimd_dp_clock_enable;
1027                ctx->crtc->pipe_clk = &ctx->dp_clk;
1028        }
1029
1030        if (ctx->encoder)
1031                exynos_dpi_bind(drm_dev, ctx->encoder);
1032
1033        if (is_drm_iommu_supported(drm_dev))
1034                fimd_clear_channels(ctx->crtc);
1035
1036        ret = drm_iommu_attach_device(drm_dev, dev);
1037        if (ret)
1038                priv->pipe--;
1039
1040        return ret;
1041}
1042
1043static void fimd_unbind(struct device *dev, struct device *master,
1044                        void *data)
1045{
1046        struct fimd_context *ctx = dev_get_drvdata(dev);
1047
1048        fimd_disable(ctx->crtc);
1049
1050        drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
1051
1052        if (ctx->encoder)
1053                exynos_dpi_remove(ctx->encoder);
1054}
1055
1056static const struct component_ops fimd_component_ops = {
1057        .bind   = fimd_bind,
1058        .unbind = fimd_unbind,
1059};
1060
1061static int fimd_probe(struct platform_device *pdev)
1062{
1063        struct device *dev = &pdev->dev;
1064        struct fimd_context *ctx;
1065        struct device_node *i80_if_timings;
1066        struct resource *res;
1067        int ret;
1068
1069        if (!dev->of_node)
1070                return -ENODEV;
1071
1072        ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1073        if (!ctx)
1074                return -ENOMEM;
1075
1076        ctx->dev = dev;
1077        ctx->suspended = true;
1078        ctx->driver_data = of_device_get_match_data(dev);
1079
1080        if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
1081                ctx->vidcon1 |= VIDCON1_INV_VDEN;
1082        if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
1083                ctx->vidcon1 |= VIDCON1_INV_VCLK;
1084
1085        i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
1086        if (i80_if_timings) {
1087                u32 val;
1088
1089                ctx->i80_if = true;
1090
1091                if (ctx->driver_data->has_vidoutcon)
1092                        ctx->vidout_con |= VIDOUT_CON_F_I80_LDI0;
1093                else
1094                        ctx->vidcon0 |= VIDCON0_VIDOUT_I80_LDI0;
1095                /*
1096                 * The user manual describes that this "DSI_EN" bit is required
1097                 * to enable I80 24-bit data interface.
1098                 */
1099                ctx->vidcon0 |= VIDCON0_DSI_EN;
1100
1101                if (of_property_read_u32(i80_if_timings, "cs-setup", &val))
1102                        val = 0;
1103                ctx->i80ifcon = LCD_CS_SETUP(val);
1104                if (of_property_read_u32(i80_if_timings, "wr-setup", &val))
1105                        val = 0;
1106                ctx->i80ifcon |= LCD_WR_SETUP(val);
1107                if (of_property_read_u32(i80_if_timings, "wr-active", &val))
1108                        val = 1;
1109                ctx->i80ifcon |= LCD_WR_ACTIVE(val);
1110                if (of_property_read_u32(i80_if_timings, "wr-hold", &val))
1111                        val = 0;
1112                ctx->i80ifcon |= LCD_WR_HOLD(val);
1113        }
1114        of_node_put(i80_if_timings);
1115
1116        ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1117                                                        "samsung,sysreg");
1118        if (IS_ERR(ctx->sysreg)) {
1119                dev_warn(dev, "failed to get system register.\n");
1120                ctx->sysreg = NULL;
1121        }
1122
1123        ctx->bus_clk = devm_clk_get(dev, "fimd");
1124        if (IS_ERR(ctx->bus_clk)) {
1125                dev_err(dev, "failed to get bus clock\n");
1126                return PTR_ERR(ctx->bus_clk);
1127        }
1128
1129        ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
1130        if (IS_ERR(ctx->lcd_clk)) {
1131                dev_err(dev, "failed to get lcd clock\n");
1132                return PTR_ERR(ctx->lcd_clk);
1133        }
1134
1135        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1136
1137        ctx->regs = devm_ioremap_resource(dev, res);
1138        if (IS_ERR(ctx->regs))
1139                return PTR_ERR(ctx->regs);
1140
1141        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1142                                           ctx->i80_if ? "lcd_sys" : "vsync");
1143        if (!res) {
1144                dev_err(dev, "irq request failed.\n");
1145                return -ENXIO;
1146        }
1147
1148        ret = devm_request_irq(dev, res->start, fimd_irq_handler,
1149                                                        0, "drm_fimd", ctx);
1150        if (ret) {
1151                dev_err(dev, "irq request failed.\n");
1152                return ret;
1153        }
1154
1155        init_waitqueue_head(&ctx->wait_vsync_queue);
1156        atomic_set(&ctx->wait_vsync_event, 0);
1157
1158        platform_set_drvdata(pdev, ctx);
1159
1160        ctx->encoder = exynos_dpi_probe(dev);
1161        if (IS_ERR(ctx->encoder))
1162                return PTR_ERR(ctx->encoder);
1163
1164        pm_runtime_enable(dev);
1165
1166        ret = component_add(dev, &fimd_component_ops);
1167        if (ret)
1168                goto err_disable_pm_runtime;
1169
1170        return ret;
1171
1172err_disable_pm_runtime:
1173        pm_runtime_disable(dev);
1174
1175        return ret;
1176}
1177
1178static int fimd_remove(struct platform_device *pdev)
1179{
1180        pm_runtime_disable(&pdev->dev);
1181
1182        component_del(&pdev->dev, &fimd_component_ops);
1183
1184        return 0;
1185}
1186
1187#ifdef CONFIG_PM
1188static int exynos_fimd_suspend(struct device *dev)
1189{
1190        struct fimd_context *ctx = dev_get_drvdata(dev);
1191
1192        clk_disable_unprepare(ctx->lcd_clk);
1193        clk_disable_unprepare(ctx->bus_clk);
1194
1195        return 0;
1196}
1197
1198static int exynos_fimd_resume(struct device *dev)
1199{
1200        struct fimd_context *ctx = dev_get_drvdata(dev);
1201        int ret;
1202
1203        ret = clk_prepare_enable(ctx->bus_clk);
1204        if (ret < 0) {
1205                DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
1206                return ret;
1207        }
1208
1209        ret = clk_prepare_enable(ctx->lcd_clk);
1210        if  (ret < 0) {
1211                DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
1212                return ret;
1213        }
1214
1215        return 0;
1216}
1217#endif
1218
1219static const struct dev_pm_ops exynos_fimd_pm_ops = {
1220        SET_RUNTIME_PM_OPS(exynos_fimd_suspend, exynos_fimd_resume, NULL)
1221};
1222
1223struct platform_driver fimd_driver = {
1224        .probe          = fimd_probe,
1225        .remove         = fimd_remove,
1226        .driver         = {
1227                .name   = "exynos4-fb",
1228                .owner  = THIS_MODULE,
1229                .pm     = &exynos_fimd_pm_ops,
1230                .of_match_table = fimd_driver_dt_match,
1231        },
1232};
1233