root/drivers/gpu/drm/exynos/exynos7_drm_decon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. decon_wait_for_vblank
  2. decon_clear_channels
  3. decon_ctx_initialize
  4. decon_ctx_remove
  5. decon_calc_clkdiv
  6. decon_commit
  7. decon_enable_vblank
  8. decon_disable_vblank
  9. decon_win_set_pixfmt
  10. decon_win_set_colkey
  11. decon_shadow_protect_win
  12. decon_atomic_begin
  13. decon_update_plane
  14. decon_disable_plane
  15. decon_atomic_flush
  16. decon_init
  17. decon_enable
  18. decon_disable
  19. decon_irq_handler
  20. decon_bind
  21. decon_unbind
  22. decon_probe
  23. decon_remove
  24. exynos7_decon_suspend
  25. exynos7_decon_resume

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

/* [<][>][^][v][top][bottom][index][help] */