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 "drmP.h"
  15
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/platform_device.h>
  19#include <linux/clk.h>
  20#include <linux/pm_runtime.h>
  21
  22#include <drm/exynos_drm.h>
  23#include <plat/regs-fb-v4.h>
  24
  25#include "exynos_drm_drv.h"
  26#include "exynos_drm_fbdev.h"
  27#include "exynos_drm_crtc.h"
  28
  29/*
  30 * FIMD is stand for Fully Interactive Mobile Display and
  31 * as a display controller, it transfers contents drawn on memory
  32 * to a LCD Panel through Display Interfaces such as RGB or
  33 * CPU Interface.
  34 */
  35
  36/* position control register for hardware window 0, 2 ~ 4.*/
  37#define VIDOSD_A(win)           (VIDOSD_BASE + 0x00 + (win) * 16)
  38#define VIDOSD_B(win)           (VIDOSD_BASE + 0x04 + (win) * 16)
  39/* size control register for hardware window 0. */
  40#define VIDOSD_C_SIZE_W0        (VIDOSD_BASE + 0x08)
  41/* alpha control register for hardware window 1 ~ 4. */
  42#define VIDOSD_C(win)           (VIDOSD_BASE + 0x18 + (win) * 16)
  43/* size control register for hardware window 1 ~ 4. */
  44#define VIDOSD_D(win)           (VIDOSD_BASE + 0x0C + (win) * 16)
  45
  46#define VIDWx_BUF_START(win, buf)       (VIDW_BUF_START(buf) + (win) * 8)
  47#define VIDWx_BUF_END(win, buf)         (VIDW_BUF_END(buf) + (win) * 8)
  48#define VIDWx_BUF_SIZE(win, buf)        (VIDW_BUF_SIZE(buf) + (win) * 4)
  49
  50/* color key control register for hardware window 1 ~ 4. */
  51#define WKEYCON0_BASE(x)                ((WKEYCON0 + 0x140) + (x * 8))
  52/* color key value register for hardware window 1 ~ 4. */
  53#define WKEYCON1_BASE(x)                ((WKEYCON1 + 0x140) + (x * 8))
  54
  55/* FIMD has totally five hardware windows. */
  56#define WINDOWS_NR      5
  57
  58#define get_fimd_context(dev)   platform_get_drvdata(to_platform_device(dev))
  59
  60struct fimd_win_data {
  61        unsigned int            offset_x;
  62        unsigned int            offset_y;
  63        unsigned int            ovl_width;
  64        unsigned int            ovl_height;
  65        unsigned int            fb_width;
  66        unsigned int            fb_height;
  67        unsigned int            bpp;
  68        dma_addr_t              dma_addr;
  69        void __iomem            *vaddr;
  70        unsigned int            buf_offsize;
  71        unsigned int            line_size;      /* bytes */
  72        bool                    enabled;
  73};
  74
  75struct fimd_context {
  76        struct exynos_drm_subdrv        subdrv;
  77        int                             irq;
  78        struct drm_crtc                 *crtc;
  79        struct clk                      *bus_clk;
  80        struct clk                      *lcd_clk;
  81        struct resource                 *regs_res;
  82        void __iomem                    *regs;
  83        struct fimd_win_data            win_data[WINDOWS_NR];
  84        unsigned int                    clkdiv;
  85        unsigned int                    default_win;
  86        unsigned long                   irq_flags;
  87        u32                             vidcon0;
  88        u32                             vidcon1;
  89        bool                            suspended;
  90        struct mutex                    lock;
  91
  92        struct exynos_drm_panel_info *panel;
  93};
  94
  95static bool fimd_display_is_connected(struct device *dev)
  96{
  97        DRM_DEBUG_KMS("%s\n", __FILE__);
  98
  99        /* TODO. */
 100
 101        return true;
 102}
 103
 104static void *fimd_get_panel(struct device *dev)
 105{
 106        struct fimd_context *ctx = get_fimd_context(dev);
 107
 108        DRM_DEBUG_KMS("%s\n", __FILE__);
 109
 110        return ctx->panel;
 111}
 112
 113static int fimd_check_timing(struct device *dev, void *timing)
 114{
 115        DRM_DEBUG_KMS("%s\n", __FILE__);
 116
 117        /* TODO. */
 118
 119        return 0;
 120}
 121
 122static int fimd_display_power_on(struct device *dev, int mode)
 123{
 124        DRM_DEBUG_KMS("%s\n", __FILE__);
 125
 126        /* TODO */
 127
 128        return 0;
 129}
 130
 131static struct exynos_drm_display_ops fimd_display_ops = {
 132        .type = EXYNOS_DISPLAY_TYPE_LCD,
 133        .is_connected = fimd_display_is_connected,
 134        .get_panel = fimd_get_panel,
 135        .check_timing = fimd_check_timing,
 136        .power_on = fimd_display_power_on,
 137};
 138
 139static void fimd_dpms(struct device *subdrv_dev, int mode)
 140{
 141        struct fimd_context *ctx = get_fimd_context(subdrv_dev);
 142
 143        DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
 144
 145        mutex_lock(&ctx->lock);
 146
 147        switch (mode) {
 148        case DRM_MODE_DPMS_ON:
 149                /*
 150                 * enable fimd hardware only if suspended status.
 151                 *
 152                 * P.S. fimd_dpms function would be called at booting time so
 153                 * clk_enable could be called double time.
 154                 */
 155                if (ctx->suspended)
 156                        pm_runtime_get_sync(subdrv_dev);
 157                break;
 158        case DRM_MODE_DPMS_STANDBY:
 159        case DRM_MODE_DPMS_SUSPEND:
 160        case DRM_MODE_DPMS_OFF:
 161                if (!ctx->suspended)
 162                        pm_runtime_put_sync(subdrv_dev);
 163                break;
 164        default:
 165                DRM_DEBUG_KMS("unspecified mode %d\n", mode);
 166                break;
 167        }
 168
 169        mutex_unlock(&ctx->lock);
 170}
 171
 172static void fimd_apply(struct device *subdrv_dev)
 173{
 174        struct fimd_context *ctx = get_fimd_context(subdrv_dev);
 175        struct exynos_drm_manager *mgr = ctx->subdrv.manager;
 176        struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
 177        struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
 178        struct fimd_win_data *win_data;
 179        int i;
 180
 181        DRM_DEBUG_KMS("%s\n", __FILE__);
 182
 183        for (i = 0; i < WINDOWS_NR; i++) {
 184                win_data = &ctx->win_data[i];
 185                if (win_data->enabled && (ovl_ops && ovl_ops->commit))
 186                        ovl_ops->commit(subdrv_dev, i);
 187        }
 188
 189        if (mgr_ops && mgr_ops->commit)
 190                mgr_ops->commit(subdrv_dev);
 191}
 192
 193static void fimd_commit(struct device *dev)
 194{
 195        struct fimd_context *ctx = get_fimd_context(dev);
 196        struct exynos_drm_panel_info *panel = ctx->panel;
 197        struct fb_videomode *timing = &panel->timing;
 198        u32 val;
 199
 200        if (ctx->suspended)
 201                return;
 202
 203        DRM_DEBUG_KMS("%s\n", __FILE__);
 204
 205        /* setup polarity values from machine code. */
 206        writel(ctx->vidcon1, ctx->regs + VIDCON1);
 207
 208        /* setup vertical timing values. */
 209        val = VIDTCON0_VBPD(timing->upper_margin - 1) |
 210               VIDTCON0_VFPD(timing->lower_margin - 1) |
 211               VIDTCON0_VSPW(timing->vsync_len - 1);
 212        writel(val, ctx->regs + VIDTCON0);
 213
 214        /* setup horizontal timing values.  */
 215        val = VIDTCON1_HBPD(timing->left_margin - 1) |
 216               VIDTCON1_HFPD(timing->right_margin - 1) |
 217               VIDTCON1_HSPW(timing->hsync_len - 1);
 218        writel(val, ctx->regs + VIDTCON1);
 219
 220        /* setup horizontal and vertical display size. */
 221        val = VIDTCON2_LINEVAL(timing->yres - 1) |
 222               VIDTCON2_HOZVAL(timing->xres - 1);
 223        writel(val, ctx->regs + VIDTCON2);
 224
 225        /* setup clock source, clock divider, enable dma. */
 226        val = ctx->vidcon0;
 227        val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
 228
 229        if (ctx->clkdiv > 1)
 230                val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
 231        else
 232                val &= ~VIDCON0_CLKDIR; /* 1:1 clock */
 233
 234        /*
 235         * fields of register with prefix '_F' would be updated
 236         * at vsync(same as dma start)
 237         */
 238        val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
 239        writel(val, ctx->regs + VIDCON0);
 240}
 241
 242static int fimd_enable_vblank(struct device *dev)
 243{
 244        struct fimd_context *ctx = get_fimd_context(dev);
 245        u32 val;
 246
 247        DRM_DEBUG_KMS("%s\n", __FILE__);
 248
 249        if (ctx->suspended)
 250                return -EPERM;
 251
 252        if (!test_and_set_bit(0, &ctx->irq_flags)) {
 253                val = readl(ctx->regs + VIDINTCON0);
 254
 255                val |= VIDINTCON0_INT_ENABLE;
 256                val |= VIDINTCON0_INT_FRAME;
 257
 258                val &= ~VIDINTCON0_FRAMESEL0_MASK;
 259                val |= VIDINTCON0_FRAMESEL0_VSYNC;
 260                val &= ~VIDINTCON0_FRAMESEL1_MASK;
 261                val |= VIDINTCON0_FRAMESEL1_NONE;
 262
 263                writel(val, ctx->regs + VIDINTCON0);
 264        }
 265
 266        return 0;
 267}
 268
 269static void fimd_disable_vblank(struct device *dev)
 270{
 271        struct fimd_context *ctx = get_fimd_context(dev);
 272        u32 val;
 273
 274        DRM_DEBUG_KMS("%s\n", __FILE__);
 275
 276        if (ctx->suspended)
 277                return;
 278
 279        if (test_and_clear_bit(0, &ctx->irq_flags)) {
 280                val = readl(ctx->regs + VIDINTCON0);
 281
 282                val &= ~VIDINTCON0_INT_FRAME;
 283                val &= ~VIDINTCON0_INT_ENABLE;
 284
 285                writel(val, ctx->regs + VIDINTCON0);
 286        }
 287}
 288
 289static struct exynos_drm_manager_ops fimd_manager_ops = {
 290        .dpms = fimd_dpms,
 291        .apply = fimd_apply,
 292        .commit = fimd_commit,
 293        .enable_vblank = fimd_enable_vblank,
 294        .disable_vblank = fimd_disable_vblank,
 295};
 296
 297static void fimd_win_mode_set(struct device *dev,
 298                              struct exynos_drm_overlay *overlay)
 299{
 300        struct fimd_context *ctx = get_fimd_context(dev);
 301        struct fimd_win_data *win_data;
 302        int win;
 303        unsigned long offset;
 304
 305        DRM_DEBUG_KMS("%s\n", __FILE__);
 306
 307        if (!overlay) {
 308                dev_err(dev, "overlay is NULL\n");
 309                return;
 310        }
 311
 312        win = overlay->zpos;
 313        if (win == DEFAULT_ZPOS)
 314                win = ctx->default_win;
 315
 316        if (win < 0 || win > WINDOWS_NR)
 317                return;
 318
 319        offset = overlay->fb_x * (overlay->bpp >> 3);
 320        offset += overlay->fb_y * overlay->pitch;
 321
 322        DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
 323
 324        win_data = &ctx->win_data[win];
 325
 326        win_data->offset_x = overlay->crtc_x;
 327        win_data->offset_y = overlay->crtc_y;
 328        win_data->ovl_width = overlay->crtc_width;
 329        win_data->ovl_height = overlay->crtc_height;
 330        win_data->fb_width = overlay->fb_width;
 331        win_data->fb_height = overlay->fb_height;
 332        win_data->dma_addr = overlay->dma_addr[0] + offset;
 333        win_data->vaddr = overlay->vaddr[0] + offset;
 334        win_data->bpp = overlay->bpp;
 335        win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
 336                                (overlay->bpp >> 3);
 337        win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
 338
 339        DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
 340                        win_data->offset_x, win_data->offset_y);
 341        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
 342                        win_data->ovl_width, win_data->ovl_height);
 343        DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
 344                        (unsigned long)win_data->dma_addr,
 345                        (unsigned long)win_data->vaddr);
 346        DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
 347                        overlay->fb_width, overlay->crtc_width);
 348}
 349
 350static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
 351{
 352        struct fimd_context *ctx = get_fimd_context(dev);
 353        struct fimd_win_data *win_data = &ctx->win_data[win];
 354        unsigned long val;
 355
 356        DRM_DEBUG_KMS("%s\n", __FILE__);
 357
 358        val = WINCONx_ENWIN;
 359
 360        switch (win_data->bpp) {
 361        case 1:
 362                val |= WINCON0_BPPMODE_1BPP;
 363                val |= WINCONx_BITSWP;
 364                val |= WINCONx_BURSTLEN_4WORD;
 365                break;
 366        case 2:
 367                val |= WINCON0_BPPMODE_2BPP;
 368                val |= WINCONx_BITSWP;
 369                val |= WINCONx_BURSTLEN_8WORD;
 370                break;
 371        case 4:
 372                val |= WINCON0_BPPMODE_4BPP;
 373                val |= WINCONx_BITSWP;
 374                val |= WINCONx_BURSTLEN_8WORD;
 375                break;
 376        case 8:
 377                val |= WINCON0_BPPMODE_8BPP_PALETTE;
 378                val |= WINCONx_BURSTLEN_8WORD;
 379                val |= WINCONx_BYTSWP;
 380                break;
 381        case 16:
 382                val |= WINCON0_BPPMODE_16BPP_565;
 383                val |= WINCONx_HAWSWP;
 384                val |= WINCONx_BURSTLEN_16WORD;
 385                break;
 386        case 24:
 387                val |= WINCON0_BPPMODE_24BPP_888;
 388                val |= WINCONx_WSWP;
 389                val |= WINCONx_BURSTLEN_16WORD;
 390                break;
 391        case 32:
 392                val |= WINCON1_BPPMODE_28BPP_A4888
 393                        | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
 394                val |= WINCONx_WSWP;
 395                val |= WINCONx_BURSTLEN_16WORD;
 396                break;
 397        default:
 398                DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
 399
 400                val |= WINCON0_BPPMODE_24BPP_888;
 401                val |= WINCONx_WSWP;
 402                val |= WINCONx_BURSTLEN_16WORD;
 403                break;
 404        }
 405
 406        DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
 407
 408        writel(val, ctx->regs + WINCON(win));
 409}
 410
 411static void fimd_win_set_colkey(struct device *dev, unsigned int win)
 412{
 413        struct fimd_context *ctx = get_fimd_context(dev);
 414        unsigned int keycon0 = 0, keycon1 = 0;
 415
 416        DRM_DEBUG_KMS("%s\n", __FILE__);
 417
 418        keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
 419                        WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
 420
 421        keycon1 = WxKEYCON1_COLVAL(0xffffffff);
 422
 423        writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
 424        writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
 425}
 426
 427static void fimd_win_commit(struct device *dev, int zpos)
 428{
 429        struct fimd_context *ctx = get_fimd_context(dev);
 430        struct fimd_win_data *win_data;
 431        int win = zpos;
 432        unsigned long val, alpha, size;
 433
 434        DRM_DEBUG_KMS("%s\n", __FILE__);
 435
 436        if (ctx->suspended)
 437                return;
 438
 439        if (win == DEFAULT_ZPOS)
 440                win = ctx->default_win;
 441
 442        if (win < 0 || win > WINDOWS_NR)
 443                return;
 444
 445        win_data = &ctx->win_data[win];
 446
 447        /*
 448         * SHADOWCON register is used for enabling timing.
 449         *
 450         * for example, once only width value of a register is set,
 451         * if the dma is started then fimd hardware could malfunction so
 452         * with protect window setting, the register fields with prefix '_F'
 453         * wouldn't be updated at vsync also but updated once unprotect window
 454         * is set.
 455         */
 456
 457        /* protect windows */
 458        val = readl(ctx->regs + SHADOWCON);
 459        val |= SHADOWCON_WINx_PROTECT(win);
 460        writel(val, ctx->regs + SHADOWCON);
 461
 462        /* buffer start address */
 463        val = (unsigned long)win_data->dma_addr;
 464        writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 465
 466        /* buffer end address */
 467        size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
 468        val = (unsigned long)(win_data->dma_addr + size);
 469        writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
 470
 471        DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
 472                        (unsigned long)win_data->dma_addr, val, size);
 473        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
 474                        win_data->ovl_width, win_data->ovl_height);
 475
 476        /* buffer size */
 477        val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
 478                VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size);
 479        writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
 480
 481        /* OSD position */
 482        val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
 483                VIDOSDxA_TOPLEFT_Y(win_data->offset_y);
 484        writel(val, ctx->regs + VIDOSD_A(win));
 485
 486        val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x +
 487                                        win_data->ovl_width - 1) |
 488                VIDOSDxB_BOTRIGHT_Y(win_data->offset_y +
 489                                        win_data->ovl_height - 1);
 490        writel(val, ctx->regs + VIDOSD_B(win));
 491
 492        DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
 493                        win_data->offset_x, win_data->offset_y,
 494                        win_data->offset_x + win_data->ovl_width - 1,
 495                        win_data->offset_y + win_data->ovl_height - 1);
 496
 497        /* hardware window 0 doesn't support alpha channel. */
 498        if (win != 0) {
 499                /* OSD alpha */
 500                alpha = VIDISD14C_ALPHA1_R(0xf) |
 501                        VIDISD14C_ALPHA1_G(0xf) |
 502                        VIDISD14C_ALPHA1_B(0xf);
 503
 504                writel(alpha, ctx->regs + VIDOSD_C(win));
 505        }
 506
 507        /* OSD size */
 508        if (win != 3 && win != 4) {
 509                u32 offset = VIDOSD_D(win);
 510                if (win == 0)
 511                        offset = VIDOSD_C_SIZE_W0;
 512                val = win_data->ovl_width * win_data->ovl_height;
 513                writel(val, ctx->regs + offset);
 514
 515                DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
 516        }
 517
 518        fimd_win_set_pixfmt(dev, win);
 519
 520        /* hardware window 0 doesn't support color key. */
 521        if (win != 0)
 522                fimd_win_set_colkey(dev, win);
 523
 524        /* wincon */
 525        val = readl(ctx->regs + WINCON(win));
 526        val |= WINCONx_ENWIN;
 527        writel(val, ctx->regs + WINCON(win));
 528
 529        /* Enable DMA channel and unprotect windows */
 530        val = readl(ctx->regs + SHADOWCON);
 531        val |= SHADOWCON_CHx_ENABLE(win);
 532        val &= ~SHADOWCON_WINx_PROTECT(win);
 533        writel(val, ctx->regs + SHADOWCON);
 534
 535        win_data->enabled = true;
 536}
 537
 538static void fimd_win_disable(struct device *dev, int zpos)
 539{
 540        struct fimd_context *ctx = get_fimd_context(dev);
 541        struct fimd_win_data *win_data;
 542        int win = zpos;
 543        u32 val;
 544
 545        DRM_DEBUG_KMS("%s\n", __FILE__);
 546
 547        if (win == DEFAULT_ZPOS)
 548                win = ctx->default_win;
 549
 550        if (win < 0 || win > WINDOWS_NR)
 551                return;
 552
 553        win_data = &ctx->win_data[win];
 554
 555        /* protect windows */
 556        val = readl(ctx->regs + SHADOWCON);
 557        val |= SHADOWCON_WINx_PROTECT(win);
 558        writel(val, ctx->regs + SHADOWCON);
 559
 560        /* wincon */
 561        val = readl(ctx->regs + WINCON(win));
 562        val &= ~WINCONx_ENWIN;
 563        writel(val, ctx->regs + WINCON(win));
 564
 565        /* unprotect windows */
 566        val = readl(ctx->regs + SHADOWCON);
 567        val &= ~SHADOWCON_CHx_ENABLE(win);
 568        val &= ~SHADOWCON_WINx_PROTECT(win);
 569        writel(val, ctx->regs + SHADOWCON);
 570
 571        win_data->enabled = false;
 572}
 573
 574static struct exynos_drm_overlay_ops fimd_overlay_ops = {
 575        .mode_set = fimd_win_mode_set,
 576        .commit = fimd_win_commit,
 577        .disable = fimd_win_disable,
 578};
 579
 580static struct exynos_drm_manager fimd_manager = {
 581        .pipe           = -1,
 582        .ops            = &fimd_manager_ops,
 583        .overlay_ops    = &fimd_overlay_ops,
 584        .display_ops    = &fimd_display_ops,
 585};
 586
 587static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
 588{
 589        struct exynos_drm_private *dev_priv = drm_dev->dev_private;
 590        struct drm_pending_vblank_event *e, *t;
 591        struct timeval now;
 592        unsigned long flags;
 593        bool is_checked = false;
 594
 595        spin_lock_irqsave(&drm_dev->event_lock, flags);
 596
 597        list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
 598                        base.link) {
 599                /* if event's pipe isn't same as crtc then ignore it. */
 600                if (crtc != e->pipe)
 601                        continue;
 602
 603                is_checked = true;
 604
 605                do_gettimeofday(&now);
 606                e->event.sequence = 0;
 607                e->event.tv_sec = now.tv_sec;
 608                e->event.tv_usec = now.tv_usec;
 609
 610                list_move_tail(&e->base.link, &e->base.file_priv->event_list);
 611                wake_up_interruptible(&e->base.file_priv->event_wait);
 612        }
 613
 614        if (is_checked) {
 615                /*
 616                 * call drm_vblank_put only in case that drm_vblank_get was
 617                 * called.
 618                 */
 619                if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
 620                        drm_vblank_put(drm_dev, crtc);
 621
 622                /*
 623                 * don't off vblank if vblank_disable_allowed is 1,
 624                 * because vblank would be off by timer handler.
 625                 */
 626                if (!drm_dev->vblank_disable_allowed)
 627                        drm_vblank_off(drm_dev, crtc);
 628        }
 629
 630        spin_unlock_irqrestore(&drm_dev->event_lock, flags);
 631}
 632
 633static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
 634{
 635        struct fimd_context *ctx = (struct fimd_context *)dev_id;
 636        struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
 637        struct drm_device *drm_dev = subdrv->drm_dev;
 638        struct exynos_drm_manager *manager = subdrv->manager;
 639        u32 val;
 640
 641        val = readl(ctx->regs + VIDINTCON1);
 642
 643        if (val & VIDINTCON1_INT_FRAME)
 644                /* VSYNC interrupt */
 645                writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
 646
 647        /* check the crtc is detached already from encoder */
 648        if (manager->pipe < 0)
 649                goto out;
 650
 651        drm_handle_vblank(drm_dev, manager->pipe);
 652        fimd_finish_pageflip(drm_dev, manager->pipe);
 653
 654out:
 655        return IRQ_HANDLED;
 656}
 657
 658static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 659{
 660        DRM_DEBUG_KMS("%s\n", __FILE__);
 661
 662        /*
 663         * enable drm irq mode.
 664         * - with irq_enabled = 1, we can use the vblank feature.
 665         *
 666         * P.S. note that we wouldn't use drm irq handler but
 667         *      just specific driver own one instead because
 668         *      drm framework supports only one irq handler.
 669         */
 670        drm_dev->irq_enabled = 1;
 671
 672        /*
 673         * with vblank_disable_allowed = 1, vblank interrupt will be disabled
 674         * by drm timer once a current process gives up ownership of
 675         * vblank event.(after drm_vblank_put function is called)
 676         */
 677        drm_dev->vblank_disable_allowed = 1;
 678
 679        return 0;
 680}
 681
 682static void fimd_subdrv_remove(struct drm_device *drm_dev)
 683{
 684        DRM_DEBUG_KMS("%s\n", __FILE__);
 685
 686        /* TODO. */
 687}
 688
 689static int fimd_calc_clkdiv(struct fimd_context *ctx,
 690                            struct fb_videomode *timing)
 691{
 692        unsigned long clk = clk_get_rate(ctx->lcd_clk);
 693        u32 retrace;
 694        u32 clkdiv;
 695        u32 best_framerate = 0;
 696        u32 framerate;
 697
 698        DRM_DEBUG_KMS("%s\n", __FILE__);
 699
 700        retrace = timing->left_margin + timing->hsync_len +
 701                                timing->right_margin + timing->xres;
 702        retrace *= timing->upper_margin + timing->vsync_len +
 703                                timing->lower_margin + timing->yres;
 704
 705        /* default framerate is 60Hz */
 706        if (!timing->refresh)
 707                timing->refresh = 60;
 708
 709        clk /= retrace;
 710
 711        for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
 712                int tmp;
 713
 714                /* get best framerate */
 715                framerate = clk / clkdiv;
 716                tmp = timing->refresh - framerate;
 717                if (tmp < 0) {
 718                        best_framerate = framerate;
 719                        continue;
 720                } else {
 721                        if (!best_framerate)
 722                                best_framerate = framerate;
 723                        else if (tmp < (best_framerate - framerate))
 724                                best_framerate = framerate;
 725                        break;
 726                }
 727        }
 728
 729        return clkdiv;
 730}
 731
 732static void fimd_clear_win(struct fimd_context *ctx, int win)
 733{
 734        u32 val;
 735
 736        DRM_DEBUG_KMS("%s\n", __FILE__);
 737
 738        writel(0, ctx->regs + WINCON(win));
 739        writel(0, ctx->regs + VIDOSD_A(win));
 740        writel(0, ctx->regs + VIDOSD_B(win));
 741        writel(0, ctx->regs + VIDOSD_C(win));
 742
 743        if (win == 1 || win == 2)
 744                writel(0, ctx->regs + VIDOSD_D(win));
 745
 746        val = readl(ctx->regs + SHADOWCON);
 747        val &= ~SHADOWCON_WINx_PROTECT(win);
 748        writel(val, ctx->regs + SHADOWCON);
 749}
 750
 751static int fimd_power_on(struct fimd_context *ctx, bool enable)
 752{
 753        struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
 754        struct device *dev = subdrv->dev;
 755
 756        DRM_DEBUG_KMS("%s\n", __FILE__);
 757
 758        if (enable != false && enable != true)
 759                return -EINVAL;
 760
 761        if (enable) {
 762                int ret;
 763
 764                ret = clk_enable(ctx->bus_clk);
 765                if (ret < 0)
 766                        return ret;
 767
 768                ret = clk_enable(ctx->lcd_clk);
 769                if  (ret < 0) {
 770                        clk_disable(ctx->bus_clk);
 771                        return ret;
 772                }
 773
 774                ctx->suspended = false;
 775
 776                /* if vblank was enabled status, enable it again. */
 777                if (test_and_clear_bit(0, &ctx->irq_flags))
 778                        fimd_enable_vblank(dev);
 779
 780                fimd_apply(dev);
 781        } else {
 782                clk_disable(ctx->lcd_clk);
 783                clk_disable(ctx->bus_clk);
 784
 785                ctx->suspended = true;
 786        }
 787
 788        return 0;
 789}
 790
 791static int __devinit fimd_probe(struct platform_device *pdev)
 792{
 793        struct device *dev = &pdev->dev;
 794        struct fimd_context *ctx;
 795        struct exynos_drm_subdrv *subdrv;
 796        struct exynos_drm_fimd_pdata *pdata;
 797        struct exynos_drm_panel_info *panel;
 798        struct resource *res;
 799        int win;
 800        int ret = -EINVAL;
 801
 802        DRM_DEBUG_KMS("%s\n", __FILE__);
 803
 804        pdata = pdev->dev.platform_data;
 805        if (!pdata) {
 806                dev_err(dev, "no platform data specified\n");
 807                return -EINVAL;
 808        }
 809
 810        panel = &pdata->panel;
 811        if (!panel) {
 812                dev_err(dev, "panel is null.\n");
 813                return -EINVAL;
 814        }
 815
 816        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 817        if (!ctx)
 818                return -ENOMEM;
 819
 820        ctx->bus_clk = clk_get(dev, "fimd");
 821        if (IS_ERR(ctx->bus_clk)) {
 822                dev_err(dev, "failed to get bus clock\n");
 823                ret = PTR_ERR(ctx->bus_clk);
 824                goto err_clk_get;
 825        }
 826
 827        ctx->lcd_clk = clk_get(dev, "sclk_fimd");
 828        if (IS_ERR(ctx->lcd_clk)) {
 829                dev_err(dev, "failed to get lcd clock\n");
 830                ret = PTR_ERR(ctx->lcd_clk);
 831                goto err_bus_clk;
 832        }
 833
 834        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 835        if (!res) {
 836                dev_err(dev, "failed to find registers\n");
 837                ret = -ENOENT;
 838                goto err_clk;
 839        }
 840
 841        ctx->regs_res = request_mem_region(res->start, resource_size(res),
 842                                           dev_name(dev));
 843        if (!ctx->regs_res) {
 844                dev_err(dev, "failed to claim register region\n");
 845                ret = -ENOENT;
 846                goto err_clk;
 847        }
 848
 849        ctx->regs = ioremap(res->start, resource_size(res));
 850        if (!ctx->regs) {
 851                dev_err(dev, "failed to map registers\n");
 852                ret = -ENXIO;
 853                goto err_req_region_io;
 854        }
 855
 856        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 857        if (!res) {
 858                dev_err(dev, "irq request failed.\n");
 859                goto err_req_region_irq;
 860        }
 861
 862        ctx->irq = res->start;
 863
 864        ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx);
 865        if (ret < 0) {
 866                dev_err(dev, "irq request failed.\n");
 867                goto err_req_irq;
 868        }
 869
 870        ctx->vidcon0 = pdata->vidcon0;
 871        ctx->vidcon1 = pdata->vidcon1;
 872        ctx->default_win = pdata->default_win;
 873        ctx->panel = panel;
 874
 875        subdrv = &ctx->subdrv;
 876
 877        subdrv->dev = dev;
 878        subdrv->manager = &fimd_manager;
 879        subdrv->probe = fimd_subdrv_probe;
 880        subdrv->remove = fimd_subdrv_remove;
 881
 882        mutex_init(&ctx->lock);
 883
 884        platform_set_drvdata(pdev, ctx);
 885
 886        pm_runtime_enable(dev);
 887        pm_runtime_get_sync(dev);
 888
 889        ctx->clkdiv = fimd_calc_clkdiv(ctx, &panel->timing);
 890        panel->timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
 891
 892        DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
 893                        panel->timing.pixclock, ctx->clkdiv);
 894
 895        for (win = 0; win < WINDOWS_NR; win++)
 896                fimd_clear_win(ctx, win);
 897
 898        exynos_drm_subdrv_register(subdrv);
 899
 900        return 0;
 901
 902err_req_irq:
 903err_req_region_irq:
 904        iounmap(ctx->regs);
 905
 906err_req_region_io:
 907        release_resource(ctx->regs_res);
 908        kfree(ctx->regs_res);
 909
 910err_clk:
 911        clk_disable(ctx->lcd_clk);
 912        clk_put(ctx->lcd_clk);
 913
 914err_bus_clk:
 915        clk_disable(ctx->bus_clk);
 916        clk_put(ctx->bus_clk);
 917
 918err_clk_get:
 919        kfree(ctx);
 920        return ret;
 921}
 922
 923static int __devexit fimd_remove(struct platform_device *pdev)
 924{
 925        struct device *dev = &pdev->dev;
 926        struct fimd_context *ctx = platform_get_drvdata(pdev);
 927
 928        DRM_DEBUG_KMS("%s\n", __FILE__);
 929
 930        exynos_drm_subdrv_unregister(&ctx->subdrv);
 931
 932        if (ctx->suspended)
 933                goto out;
 934
 935        clk_disable(ctx->lcd_clk);
 936        clk_disable(ctx->bus_clk);
 937
 938        pm_runtime_set_suspended(dev);
 939        pm_runtime_put_sync(dev);
 940
 941out:
 942        pm_runtime_disable(dev);
 943
 944        clk_put(ctx->lcd_clk);
 945        clk_put(ctx->bus_clk);
 946
 947        iounmap(ctx->regs);
 948        release_resource(ctx->regs_res);
 949        kfree(ctx->regs_res);
 950        free_irq(ctx->irq, ctx);
 951
 952        kfree(ctx);
 953
 954        return 0;
 955}
 956
 957#ifdef CONFIG_PM_SLEEP
 958static int fimd_suspend(struct device *dev)
 959{
 960        struct fimd_context *ctx = get_fimd_context(dev);
 961
 962        if (pm_runtime_suspended(dev))
 963                return 0;
 964
 965        /*
 966         * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
 967         * called here, an error would be returned by that interface
 968         * because the usage_count of pm runtime is more than 1.
 969         */
 970        return fimd_power_on(ctx, false);
 971}
 972
 973static int fimd_resume(struct device *dev)
 974{
 975        struct fimd_context *ctx = get_fimd_context(dev);
 976
 977        /*
 978         * if entered to sleep when lcd panel was on, the usage_count
 979         * of pm runtime would still be 1 so in this case, fimd driver
 980         * should be on directly not drawing on pm runtime interface.
 981         */
 982        if (!pm_runtime_suspended(dev))
 983                return fimd_power_on(ctx, true);
 984
 985        return 0;
 986}
 987#endif
 988
 989#ifdef CONFIG_PM_RUNTIME
 990static int fimd_runtime_suspend(struct device *dev)
 991{
 992        struct fimd_context *ctx = get_fimd_context(dev);
 993
 994        DRM_DEBUG_KMS("%s\n", __FILE__);
 995
 996        return fimd_power_on(ctx, false);
 997}
 998
 999static int fimd_runtime_resume(struct device *dev)
1000{
1001        struct fimd_context *ctx = get_fimd_context(dev);
1002
1003        DRM_DEBUG_KMS("%s\n", __FILE__);
1004
1005        return fimd_power_on(ctx, true);
1006}
1007#endif
1008
1009static const struct dev_pm_ops fimd_pm_ops = {
1010        SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
1011        SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
1012};
1013
1014struct platform_driver fimd_driver = {
1015        .probe          = fimd_probe,
1016        .remove         = __devexit_p(fimd_remove),
1017        .driver         = {
1018                .name   = "exynos4-fb",
1019                .owner  = THIS_MODULE,
1020                .pm     = &fimd_pm_ops,
1021        },
1022};
1023