linux/drivers/gpu/drm/exynos/exynos7_drm_decon.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* drivers/gpu/drm/exynos/exynos7_drm_decon.c
   3 *
   4 * Copyright (C) 2014 Samsung Electronics Co.Ltd
   5 * Authors:
   6 *      Akshu Agarwal <akshua@gmail.com>
   7 *      Ajay Kumar <ajaykumar.rs@samsung.com>
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/component.h>
  12#include <linux/kernel.h>
  13#include <linux/of.h>
  14#include <linux/of_address.h>
  15#include <linux/of_device.h>
  16#include <linux/platform_device.h>
  17#include <linux/pm_runtime.h>
  18
  19#include <video/of_display_timing.h>
  20#include <video/of_videomode.h>
  21
  22#include <drm/drm_fourcc.h>
  23#include <drm/drm_vblank.h>
  24#include <drm/exynos_drm.h>
  25
  26#include "exynos_drm_crtc.h"
  27#include "exynos_drm_drv.h"
  28#include "exynos_drm_fb.h"
  29#include "exynos_drm_plane.h"
  30#include "regs-decon7.h"
  31
  32/*
  33 * DECON stands for Display and Enhancement controller.
  34 */
  35
  36#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
  37
  38#define WINDOWS_NR      2
  39
  40struct decon_context {
  41        struct device                   *dev;
  42        struct drm_device               *drm_dev;
  43        struct exynos_drm_crtc          *crtc;
  44        struct exynos_drm_plane         planes[WINDOWS_NR];
  45        struct exynos_drm_plane_config  configs[WINDOWS_NR];
  46        struct clk                      *pclk;
  47        struct clk                      *aclk;
  48        struct clk                      *eclk;
  49        struct clk                      *vclk;
  50        void __iomem                    *regs;
  51        unsigned long                   irq_flags;
  52        bool                            i80_if;
  53        bool                            suspended;
  54        wait_queue_head_t               wait_vsync_queue;
  55        atomic_t                        wait_vsync_event;
  56
  57        struct drm_encoder *encoder;
  58};
  59
  60static const struct of_device_id decon_driver_dt_match[] = {
  61        {.compatible = "samsung,exynos7-decon"},
  62        {},
  63};
  64MODULE_DEVICE_TABLE(of, decon_driver_dt_match);
  65
  66static const uint32_t decon_formats[] = {
  67        DRM_FORMAT_RGB565,
  68        DRM_FORMAT_XRGB8888,
  69        DRM_FORMAT_XBGR8888,
  70        DRM_FORMAT_RGBX8888,
  71        DRM_FORMAT_BGRX8888,
  72        DRM_FORMAT_ARGB8888,
  73        DRM_FORMAT_ABGR8888,
  74        DRM_FORMAT_RGBA8888,
  75        DRM_FORMAT_BGRA8888,
  76};
  77
  78static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
  79        DRM_PLANE_TYPE_PRIMARY,
  80        DRM_PLANE_TYPE_CURSOR,
  81};
  82
  83static void decon_wait_for_vblank(struct exynos_drm_crtc *crtc)
  84{
  85        struct decon_context *ctx = crtc->ctx;
  86
  87        if (ctx->suspended)
  88                return;
  89
  90        atomic_set(&ctx->wait_vsync_event, 1);
  91
  92        /*
  93         * wait for DECON to signal VSYNC interrupt or return after
  94         * timeout which is set to 50ms (refresh rate of 20).
  95         */
  96        if (!wait_event_timeout(ctx->wait_vsync_queue,
  97                                !atomic_read(&ctx->wait_vsync_event),
  98                                HZ/20))
  99                DRM_DEV_DEBUG_KMS(ctx->dev, "vblank wait timed out.\n");
 100}
 101
 102static void decon_clear_channels(struct exynos_drm_crtc *crtc)
 103{
 104        struct decon_context *ctx = crtc->ctx;
 105        unsigned int win, ch_enabled = 0;
 106
 107        /* Check if any channel is enabled. */
 108        for (win = 0; win < WINDOWS_NR; win++) {
 109                u32 val = readl(ctx->regs + WINCON(win));
 110
 111                if (val & WINCONx_ENWIN) {
 112                        val &= ~WINCONx_ENWIN;
 113                        writel(val, ctx->regs + WINCON(win));
 114                        ch_enabled = 1;
 115                }
 116        }
 117
 118        /* Wait for vsync, as disable channel takes effect at next vsync */
 119        if (ch_enabled)
 120                decon_wait_for_vblank(ctx->crtc);
 121}
 122
 123static int decon_ctx_initialize(struct decon_context *ctx,
 124                        struct drm_device *drm_dev)
 125{
 126        ctx->drm_dev = drm_dev;
 127
 128        decon_clear_channels(ctx->crtc);
 129
 130        return exynos_drm_register_dma(drm_dev, ctx->dev);
 131}
 132
 133static void decon_ctx_remove(struct decon_context *ctx)
 134{
 135        /* detach this sub driver from iommu mapping if supported. */
 136        exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
 137}
 138
 139static u32 decon_calc_clkdiv(struct decon_context *ctx,
 140                const struct drm_display_mode *mode)
 141{
 142        unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
 143        u32 clkdiv;
 144
 145        /* Find the clock divider value that gets us closest to ideal_clk */
 146        clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->vclk), ideal_clk);
 147
 148        return (clkdiv < 0x100) ? clkdiv : 0xff;
 149}
 150
 151static void decon_commit(struct exynos_drm_crtc *crtc)
 152{
 153        struct decon_context *ctx = crtc->ctx;
 154        struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
 155        u32 val, clkdiv;
 156
 157        if (ctx->suspended)
 158                return;
 159
 160        /* nothing to do if we haven't set the mode yet */
 161        if (mode->htotal == 0 || mode->vtotal == 0)
 162                return;
 163
 164        if (!ctx->i80_if) {
 165                int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
 166              /* setup vertical timing values. */
 167                vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
 168                vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
 169                vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
 170
 171                val = VIDTCON0_VBPD(vbpd - 1) | VIDTCON0_VFPD(vfpd - 1);
 172                writel(val, ctx->regs + VIDTCON0);
 173
 174                val = VIDTCON1_VSPW(vsync_len - 1);
 175                writel(val, ctx->regs + VIDTCON1);
 176
 177                /* setup horizontal timing values.  */
 178                hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
 179                hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
 180                hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
 181
 182                /* setup horizontal timing values.  */
 183                val = VIDTCON2_HBPD(hbpd - 1) | VIDTCON2_HFPD(hfpd - 1);
 184                writel(val, ctx->regs + VIDTCON2);
 185
 186                val = VIDTCON3_HSPW(hsync_len - 1);
 187                writel(val, ctx->regs + VIDTCON3);
 188        }
 189
 190        /* setup horizontal and vertical display size. */
 191        val = VIDTCON4_LINEVAL(mode->vdisplay - 1) |
 192               VIDTCON4_HOZVAL(mode->hdisplay - 1);
 193        writel(val, ctx->regs + VIDTCON4);
 194
 195        writel(mode->vdisplay - 1, ctx->regs + LINECNT_OP_THRESHOLD);
 196
 197        /*
 198         * fields of register with prefix '_F' would be updated
 199         * at vsync(same as dma start)
 200         */
 201        val = VIDCON0_ENVID | VIDCON0_ENVID_F;
 202        writel(val, ctx->regs + VIDCON0);
 203
 204        clkdiv = decon_calc_clkdiv(ctx, mode);
 205        if (clkdiv > 1) {
 206                val = VCLKCON1_CLKVAL_NUM_VCLK(clkdiv - 1);
 207                writel(val, ctx->regs + VCLKCON1);
 208                writel(val, ctx->regs + VCLKCON2);
 209        }
 210
 211        val = readl(ctx->regs + DECON_UPDATE);
 212        val |= DECON_UPDATE_STANDALONE_F;
 213        writel(val, ctx->regs + DECON_UPDATE);
 214}
 215
 216static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
 217{
 218        struct decon_context *ctx = crtc->ctx;
 219        u32 val;
 220
 221        if (ctx->suspended)
 222                return -EPERM;
 223
 224        if (!test_and_set_bit(0, &ctx->irq_flags)) {
 225                val = readl(ctx->regs + VIDINTCON0);
 226
 227                val |= VIDINTCON0_INT_ENABLE;
 228
 229                if (!ctx->i80_if) {
 230                        val |= VIDINTCON0_INT_FRAME;
 231                        val &= ~VIDINTCON0_FRAMESEL0_MASK;
 232                        val |= VIDINTCON0_FRAMESEL0_VSYNC;
 233                }
 234
 235                writel(val, ctx->regs + VIDINTCON0);
 236        }
 237
 238        return 0;
 239}
 240
 241static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
 242{
 243        struct decon_context *ctx = crtc->ctx;
 244        u32 val;
 245
 246        if (ctx->suspended)
 247                return;
 248
 249        if (test_and_clear_bit(0, &ctx->irq_flags)) {
 250                val = readl(ctx->regs + VIDINTCON0);
 251
 252                val &= ~VIDINTCON0_INT_ENABLE;
 253                if (!ctx->i80_if)
 254                        val &= ~VIDINTCON0_INT_FRAME;
 255
 256                writel(val, ctx->regs + VIDINTCON0);
 257        }
 258}
 259
 260static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
 261                                 struct drm_framebuffer *fb)
 262{
 263        unsigned long val;
 264        int padding;
 265
 266        val = readl(ctx->regs + WINCON(win));
 267        val &= ~WINCONx_BPPMODE_MASK;
 268
 269        switch (fb->format->format) {
 270        case DRM_FORMAT_RGB565:
 271                val |= WINCONx_BPPMODE_16BPP_565;
 272                val |= WINCONx_BURSTLEN_16WORD;
 273                break;
 274        case DRM_FORMAT_XRGB8888:
 275                val |= WINCONx_BPPMODE_24BPP_xRGB;
 276                val |= WINCONx_BURSTLEN_16WORD;
 277                break;
 278        case DRM_FORMAT_XBGR8888:
 279                val |= WINCONx_BPPMODE_24BPP_xBGR;
 280                val |= WINCONx_BURSTLEN_16WORD;
 281                break;
 282        case DRM_FORMAT_RGBX8888:
 283                val |= WINCONx_BPPMODE_24BPP_RGBx;
 284                val |= WINCONx_BURSTLEN_16WORD;
 285                break;
 286        case DRM_FORMAT_BGRX8888:
 287                val |= WINCONx_BPPMODE_24BPP_BGRx;
 288                val |= WINCONx_BURSTLEN_16WORD;
 289                break;
 290        case DRM_FORMAT_ARGB8888:
 291                val |= WINCONx_BPPMODE_32BPP_ARGB | WINCONx_BLD_PIX |
 292                        WINCONx_ALPHA_SEL;
 293                val |= WINCONx_BURSTLEN_16WORD;
 294                break;
 295        case DRM_FORMAT_ABGR8888:
 296                val |= WINCONx_BPPMODE_32BPP_ABGR | WINCONx_BLD_PIX |
 297                        WINCONx_ALPHA_SEL;
 298                val |= WINCONx_BURSTLEN_16WORD;
 299                break;
 300        case DRM_FORMAT_RGBA8888:
 301                val |= WINCONx_BPPMODE_32BPP_RGBA | WINCONx_BLD_PIX |
 302                        WINCONx_ALPHA_SEL;
 303                val |= WINCONx_BURSTLEN_16WORD;
 304                break;
 305        case DRM_FORMAT_BGRA8888:
 306        default:
 307                val |= WINCONx_BPPMODE_32BPP_BGRA | WINCONx_BLD_PIX |
 308                        WINCONx_ALPHA_SEL;
 309                val |= WINCONx_BURSTLEN_16WORD;
 310                break;
 311        }
 312
 313        DRM_DEV_DEBUG_KMS(ctx->dev, "cpp = %d\n", fb->format->cpp[0]);
 314
 315        /*
 316         * In case of exynos, setting dma-burst to 16Word causes permanent
 317         * tearing for very small buffers, e.g. cursor buffer. Burst Mode
 318         * switching which is based on plane size is not recommended as
 319         * plane size varies a lot towards the end of the screen and rapid
 320         * movement causes unstable DMA which results into iommu crash/tear.
 321         */
 322
 323        padding = (fb->pitches[0] / fb->format->cpp[0]) - fb->width;
 324        if (fb->width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
 325                val &= ~WINCONx_BURSTLEN_MASK;
 326                val |= WINCONx_BURSTLEN_8WORD;
 327        }
 328
 329        writel(val, ctx->regs + WINCON(win));
 330}
 331
 332static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win)
 333{
 334        unsigned int keycon0 = 0, keycon1 = 0;
 335
 336        keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
 337                        WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
 338
 339        keycon1 = WxKEYCON1_COLVAL(0xffffffff);
 340
 341        writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
 342        writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
 343}
 344
 345/**
 346 * shadow_protect_win() - disable updating values from shadow registers at vsync
 347 *
 348 * @win: window to protect registers for
 349 * @protect: 1 to protect (disable updates)
 350 */
 351static void decon_shadow_protect_win(struct decon_context *ctx,
 352                                     unsigned int win, bool protect)
 353{
 354        u32 bits, val;
 355
 356        bits = SHADOWCON_WINx_PROTECT(win);
 357
 358        val = readl(ctx->regs + SHADOWCON);
 359        if (protect)
 360                val |= bits;
 361        else
 362                val &= ~bits;
 363        writel(val, ctx->regs + SHADOWCON);
 364}
 365
 366static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
 367{
 368        struct decon_context *ctx = crtc->ctx;
 369        int i;
 370
 371        if (ctx->suspended)
 372                return;
 373
 374        for (i = 0; i < WINDOWS_NR; i++)
 375                decon_shadow_protect_win(ctx, i, true);
 376}
 377
 378static void decon_update_plane(struct exynos_drm_crtc *crtc,
 379                               struct exynos_drm_plane *plane)
 380{
 381        struct exynos_drm_plane_state *state =
 382                                to_exynos_plane_state(plane->base.state);
 383        struct decon_context *ctx = crtc->ctx;
 384        struct drm_framebuffer *fb = state->base.fb;
 385        int padding;
 386        unsigned long val, alpha;
 387        unsigned int last_x;
 388        unsigned int last_y;
 389        unsigned int win = plane->index;
 390        unsigned int cpp = fb->format->cpp[0];
 391        unsigned int pitch = fb->pitches[0];
 392
 393        if (ctx->suspended)
 394                return;
 395
 396        /*
 397         * SHADOWCON/PRTCON register is used for enabling timing.
 398         *
 399         * for example, once only width value of a register is set,
 400         * if the dma is started then decon hardware could malfunction so
 401         * with protect window setting, the register fields with prefix '_F'
 402         * wouldn't be updated at vsync also but updated once unprotect window
 403         * is set.
 404         */
 405
 406        /* buffer start address */
 407        val = (unsigned long)exynos_drm_fb_dma_addr(fb, 0);
 408        writel(val, ctx->regs + VIDW_BUF_START(win));
 409
 410        padding = (pitch / cpp) - fb->width;
 411
 412        /* buffer size */
 413        writel(fb->width + padding, ctx->regs + VIDW_WHOLE_X(win));
 414        writel(fb->height, ctx->regs + VIDW_WHOLE_Y(win));
 415
 416        /* offset from the start of the buffer to read */
 417        writel(state->src.x, ctx->regs + VIDW_OFFSET_X(win));
 418        writel(state->src.y, ctx->regs + VIDW_OFFSET_Y(win));
 419
 420        DRM_DEV_DEBUG_KMS(ctx->dev, "start addr = 0x%lx\n",
 421                        (unsigned long)val);
 422        DRM_DEV_DEBUG_KMS(ctx->dev, "ovl_width = %d, ovl_height = %d\n",
 423                        state->crtc.w, state->crtc.h);
 424
 425        val = VIDOSDxA_TOPLEFT_X(state->crtc.x) |
 426                VIDOSDxA_TOPLEFT_Y(state->crtc.y);
 427        writel(val, ctx->regs + VIDOSD_A(win));
 428
 429        last_x = state->crtc.x + state->crtc.w;
 430        if (last_x)
 431                last_x--;
 432        last_y = state->crtc.y + state->crtc.h;
 433        if (last_y)
 434                last_y--;
 435
 436        val = VIDOSDxB_BOTRIGHT_X(last_x) | VIDOSDxB_BOTRIGHT_Y(last_y);
 437
 438        writel(val, ctx->regs + VIDOSD_B(win));
 439
 440        DRM_DEV_DEBUG_KMS(ctx->dev, "osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
 441                        state->crtc.x, state->crtc.y, last_x, last_y);
 442
 443        /* OSD alpha */
 444        alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
 445                        VIDOSDxC_ALPHA0_G_F(0x0) |
 446                        VIDOSDxC_ALPHA0_B_F(0x0);
 447
 448        writel(alpha, ctx->regs + VIDOSD_C(win));
 449
 450        alpha = VIDOSDxD_ALPHA1_R_F(0xff) |
 451                        VIDOSDxD_ALPHA1_G_F(0xff) |
 452                        VIDOSDxD_ALPHA1_B_F(0xff);
 453
 454        writel(alpha, ctx->regs + VIDOSD_D(win));
 455
 456        decon_win_set_pixfmt(ctx, win, fb);
 457
 458        /* hardware window 0 doesn't support color key. */
 459        if (win != 0)
 460                decon_win_set_colkey(ctx, win);
 461
 462        /* wincon */
 463        val = readl(ctx->regs + WINCON(win));
 464        val |= WINCONx_TRIPLE_BUF_MODE;
 465        val |= WINCONx_ENWIN;
 466        writel(val, ctx->regs + WINCON(win));
 467
 468        /* Enable DMA channel and unprotect windows */
 469        decon_shadow_protect_win(ctx, win, false);
 470
 471        val = readl(ctx->regs + DECON_UPDATE);
 472        val |= DECON_UPDATE_STANDALONE_F;
 473        writel(val, ctx->regs + DECON_UPDATE);
 474}
 475
 476static void decon_disable_plane(struct exynos_drm_crtc *crtc,
 477                                struct exynos_drm_plane *plane)
 478{
 479        struct decon_context *ctx = crtc->ctx;
 480        unsigned int win = plane->index;
 481        u32 val;
 482
 483        if (ctx->suspended)
 484                return;
 485
 486        /* protect windows */
 487        decon_shadow_protect_win(ctx, win, true);
 488
 489        /* wincon */
 490        val = readl(ctx->regs + WINCON(win));
 491        val &= ~WINCONx_ENWIN;
 492        writel(val, ctx->regs + WINCON(win));
 493
 494        val = readl(ctx->regs + DECON_UPDATE);
 495        val |= DECON_UPDATE_STANDALONE_F;
 496        writel(val, ctx->regs + DECON_UPDATE);
 497}
 498
 499static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
 500{
 501        struct decon_context *ctx = crtc->ctx;
 502        int i;
 503
 504        if (ctx->suspended)
 505                return;
 506
 507        for (i = 0; i < WINDOWS_NR; i++)
 508                decon_shadow_protect_win(ctx, i, false);
 509        exynos_crtc_handle_event(crtc);
 510}
 511
 512static void decon_init(struct decon_context *ctx)
 513{
 514        u32 val;
 515
 516        writel(VIDCON0_SWRESET, ctx->regs + VIDCON0);
 517
 518        val = VIDOUTCON0_DISP_IF_0_ON;
 519        if (!ctx->i80_if)
 520                val |= VIDOUTCON0_RGBIF;
 521        writel(val, ctx->regs + VIDOUTCON0);
 522
 523        writel(VCLKCON0_CLKVALUP | VCLKCON0_VCLKFREE, ctx->regs + VCLKCON0);
 524
 525        if (!ctx->i80_if)
 526                writel(VIDCON1_VCLK_HOLD, ctx->regs + VIDCON1(0));
 527}
 528
 529static void decon_enable(struct exynos_drm_crtc *crtc)
 530{
 531        struct decon_context *ctx = crtc->ctx;
 532
 533        if (!ctx->suspended)
 534                return;
 535
 536        pm_runtime_get_sync(ctx->dev);
 537
 538        decon_init(ctx);
 539
 540        /* if vblank was enabled status, enable it again. */
 541        if (test_and_clear_bit(0, &ctx->irq_flags))
 542                decon_enable_vblank(ctx->crtc);
 543
 544        decon_commit(ctx->crtc);
 545
 546        ctx->suspended = false;
 547}
 548
 549static void decon_disable(struct exynos_drm_crtc *crtc)
 550{
 551        struct decon_context *ctx = crtc->ctx;
 552        int i;
 553
 554        if (ctx->suspended)
 555                return;
 556
 557        /*
 558         * We need to make sure that all windows are disabled before we
 559         * suspend that connector. Otherwise we might try to scan from
 560         * a destroyed buffer later.
 561         */
 562        for (i = 0; i < WINDOWS_NR; i++)
 563                decon_disable_plane(crtc, &ctx->planes[i]);
 564
 565        pm_runtime_put_sync(ctx->dev);
 566
 567        ctx->suspended = true;
 568}
 569
 570static const struct exynos_drm_crtc_ops decon_crtc_ops = {
 571        .enable = decon_enable,
 572        .disable = decon_disable,
 573        .enable_vblank = decon_enable_vblank,
 574        .disable_vblank = decon_disable_vblank,
 575        .atomic_begin = decon_atomic_begin,
 576        .update_plane = decon_update_plane,
 577        .disable_plane = decon_disable_plane,
 578        .atomic_flush = decon_atomic_flush,
 579};
 580
 581
 582static irqreturn_t decon_irq_handler(int irq, void *dev_id)
 583{
 584        struct decon_context *ctx = (struct decon_context *)dev_id;
 585        u32 val, clear_bit;
 586
 587        val = readl(ctx->regs + VIDINTCON1);
 588
 589        clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME;
 590        if (val & clear_bit)
 591                writel(clear_bit, ctx->regs + VIDINTCON1);
 592
 593        /* check the crtc is detached already from encoder */
 594        if (!ctx->drm_dev)
 595                goto out;
 596
 597        if (!ctx->i80_if) {
 598                drm_crtc_handle_vblank(&ctx->crtc->base);
 599
 600                /* set wait vsync event to zero and wake up queue. */
 601                if (atomic_read(&ctx->wait_vsync_event)) {
 602                        atomic_set(&ctx->wait_vsync_event, 0);
 603                        wake_up(&ctx->wait_vsync_queue);
 604                }
 605        }
 606out:
 607        return IRQ_HANDLED;
 608}
 609
 610static int decon_bind(struct device *dev, struct device *master, void *data)
 611{
 612        struct decon_context *ctx = dev_get_drvdata(dev);
 613        struct drm_device *drm_dev = data;
 614        struct exynos_drm_plane *exynos_plane;
 615        unsigned int i;
 616        int ret;
 617
 618        ret = decon_ctx_initialize(ctx, drm_dev);
 619        if (ret) {
 620                DRM_DEV_ERROR(dev, "decon_ctx_initialize failed.\n");
 621                return ret;
 622        }
 623
 624        for (i = 0; i < WINDOWS_NR; i++) {
 625                ctx->configs[i].pixel_formats = decon_formats;
 626                ctx->configs[i].num_pixel_formats = ARRAY_SIZE(decon_formats);
 627                ctx->configs[i].zpos = i;
 628                ctx->configs[i].type = decon_win_types[i];
 629
 630                ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
 631                                        &ctx->configs[i]);
 632                if (ret)
 633                        return ret;
 634        }
 635
 636        exynos_plane = &ctx->planes[DEFAULT_WIN];
 637        ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
 638                        EXYNOS_DISPLAY_TYPE_LCD, &decon_crtc_ops, ctx);
 639        if (IS_ERR(ctx->crtc)) {
 640                decon_ctx_remove(ctx);
 641                return PTR_ERR(ctx->crtc);
 642        }
 643
 644        if (ctx->encoder)
 645                exynos_dpi_bind(drm_dev, ctx->encoder);
 646
 647        return 0;
 648
 649}
 650
 651static void decon_unbind(struct device *dev, struct device *master,
 652                        void *data)
 653{
 654        struct decon_context *ctx = dev_get_drvdata(dev);
 655
 656        decon_disable(ctx->crtc);
 657
 658        if (ctx->encoder)
 659                exynos_dpi_remove(ctx->encoder);
 660
 661        decon_ctx_remove(ctx);
 662}
 663
 664static const struct component_ops decon_component_ops = {
 665        .bind   = decon_bind,
 666        .unbind = decon_unbind,
 667};
 668
 669static int decon_probe(struct platform_device *pdev)
 670{
 671        struct device *dev = &pdev->dev;
 672        struct decon_context *ctx;
 673        struct device_node *i80_if_timings;
 674        struct resource *res;
 675        int ret;
 676
 677        if (!dev->of_node)
 678                return -ENODEV;
 679
 680        ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
 681        if (!ctx)
 682                return -ENOMEM;
 683
 684        ctx->dev = dev;
 685        ctx->suspended = true;
 686
 687        i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
 688        if (i80_if_timings)
 689                ctx->i80_if = true;
 690        of_node_put(i80_if_timings);
 691
 692        ctx->regs = of_iomap(dev->of_node, 0);
 693        if (!ctx->regs)
 694                return -ENOMEM;
 695
 696        ctx->pclk = devm_clk_get(dev, "pclk_decon0");
 697        if (IS_ERR(ctx->pclk)) {
 698                dev_err(dev, "failed to get bus clock pclk\n");
 699                ret = PTR_ERR(ctx->pclk);
 700                goto err_iounmap;
 701        }
 702
 703        ctx->aclk = devm_clk_get(dev, "aclk_decon0");
 704        if (IS_ERR(ctx->aclk)) {
 705                dev_err(dev, "failed to get bus clock aclk\n");
 706                ret = PTR_ERR(ctx->aclk);
 707                goto err_iounmap;
 708        }
 709
 710        ctx->eclk = devm_clk_get(dev, "decon0_eclk");
 711        if (IS_ERR(ctx->eclk)) {
 712                dev_err(dev, "failed to get eclock\n");
 713                ret = PTR_ERR(ctx->eclk);
 714                goto err_iounmap;
 715        }
 716
 717        ctx->vclk = devm_clk_get(dev, "decon0_vclk");
 718        if (IS_ERR(ctx->vclk)) {
 719                dev_err(dev, "failed to get vclock\n");
 720                ret = PTR_ERR(ctx->vclk);
 721                goto err_iounmap;
 722        }
 723
 724        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
 725                                           ctx->i80_if ? "lcd_sys" : "vsync");
 726        if (!res) {
 727                dev_err(dev, "irq request failed.\n");
 728                ret = -ENXIO;
 729                goto err_iounmap;
 730        }
 731
 732        ret = devm_request_irq(dev, res->start, decon_irq_handler,
 733                                                        0, "drm_decon", ctx);
 734        if (ret) {
 735                dev_err(dev, "irq request failed.\n");
 736                goto err_iounmap;
 737        }
 738
 739        init_waitqueue_head(&ctx->wait_vsync_queue);
 740        atomic_set(&ctx->wait_vsync_event, 0);
 741
 742        platform_set_drvdata(pdev, ctx);
 743
 744        ctx->encoder = exynos_dpi_probe(dev);
 745        if (IS_ERR(ctx->encoder)) {
 746                ret = PTR_ERR(ctx->encoder);
 747                goto err_iounmap;
 748        }
 749
 750        pm_runtime_enable(dev);
 751
 752        ret = component_add(dev, &decon_component_ops);
 753        if (ret)
 754                goto err_disable_pm_runtime;
 755
 756        return ret;
 757
 758err_disable_pm_runtime:
 759        pm_runtime_disable(dev);
 760
 761err_iounmap:
 762        iounmap(ctx->regs);
 763
 764        return ret;
 765}
 766
 767static int decon_remove(struct platform_device *pdev)
 768{
 769        struct decon_context *ctx = dev_get_drvdata(&pdev->dev);
 770
 771        pm_runtime_disable(&pdev->dev);
 772
 773        iounmap(ctx->regs);
 774
 775        component_del(&pdev->dev, &decon_component_ops);
 776
 777        return 0;
 778}
 779
 780#ifdef CONFIG_PM
 781static int exynos7_decon_suspend(struct device *dev)
 782{
 783        struct decon_context *ctx = dev_get_drvdata(dev);
 784
 785        clk_disable_unprepare(ctx->vclk);
 786        clk_disable_unprepare(ctx->eclk);
 787        clk_disable_unprepare(ctx->aclk);
 788        clk_disable_unprepare(ctx->pclk);
 789
 790        return 0;
 791}
 792
 793static int exynos7_decon_resume(struct device *dev)
 794{
 795        struct decon_context *ctx = dev_get_drvdata(dev);
 796        int ret;
 797
 798        ret = clk_prepare_enable(ctx->pclk);
 799        if (ret < 0) {
 800                DRM_DEV_ERROR(dev, "Failed to prepare_enable the pclk [%d]\n",
 801                              ret);
 802                return ret;
 803        }
 804
 805        ret = clk_prepare_enable(ctx->aclk);
 806        if (ret < 0) {
 807                DRM_DEV_ERROR(dev, "Failed to prepare_enable the aclk [%d]\n",
 808                              ret);
 809                return ret;
 810        }
 811
 812        ret = clk_prepare_enable(ctx->eclk);
 813        if  (ret < 0) {
 814                DRM_DEV_ERROR(dev, "Failed to prepare_enable the eclk [%d]\n",
 815                              ret);
 816                return ret;
 817        }
 818
 819        ret = clk_prepare_enable(ctx->vclk);
 820        if  (ret < 0) {
 821                DRM_DEV_ERROR(dev, "Failed to prepare_enable the vclk [%d]\n",
 822                              ret);
 823                return ret;
 824        }
 825
 826        return 0;
 827}
 828#endif
 829
 830static const struct dev_pm_ops exynos7_decon_pm_ops = {
 831        SET_RUNTIME_PM_OPS(exynos7_decon_suspend, exynos7_decon_resume,
 832                           NULL)
 833        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
 834                                pm_runtime_force_resume)
 835};
 836
 837struct platform_driver decon_driver = {
 838        .probe          = decon_probe,
 839        .remove         = decon_remove,
 840        .driver         = {
 841                .name   = "exynos-decon",
 842                .pm     = &exynos7_decon_pm_ops,
 843                .of_match_table = decon_driver_dt_match,
 844        },
 845};
 846