0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/clk.h>
0011 #include <linux/component.h>
0012 #include <linux/kernel.h>
0013 #include <linux/of.h>
0014 #include <linux/of_address.h>
0015 #include <linux/of_device.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/pm_runtime.h>
0018
0019 #include <video/of_display_timing.h>
0020 #include <video/of_videomode.h>
0021
0022 #include <drm/drm_fourcc.h>
0023 #include <drm/drm_framebuffer.h>
0024 #include <drm/drm_vblank.h>
0025 #include <drm/exynos_drm.h>
0026
0027 #include "exynos_drm_crtc.h"
0028 #include "exynos_drm_drv.h"
0029 #include "exynos_drm_fb.h"
0030 #include "exynos_drm_plane.h"
0031 #include "regs-decon7.h"
0032
0033
0034
0035
0036
0037 #define MIN_FB_WIDTH_FOR_16WORD_BURST 128
0038
0039 #define WINDOWS_NR 2
0040
0041 struct decon_context {
0042 struct device *dev;
0043 struct drm_device *drm_dev;
0044 void *dma_priv;
0045 struct exynos_drm_crtc *crtc;
0046 struct exynos_drm_plane planes[WINDOWS_NR];
0047 struct exynos_drm_plane_config configs[WINDOWS_NR];
0048 struct clk *pclk;
0049 struct clk *aclk;
0050 struct clk *eclk;
0051 struct clk *vclk;
0052 void __iomem *regs;
0053 unsigned long irq_flags;
0054 bool i80_if;
0055 bool suspended;
0056 wait_queue_head_t wait_vsync_queue;
0057 atomic_t wait_vsync_event;
0058
0059 struct drm_encoder *encoder;
0060 };
0061
0062 static const struct of_device_id decon_driver_dt_match[] = {
0063 {.compatible = "samsung,exynos7-decon"},
0064 {},
0065 };
0066 MODULE_DEVICE_TABLE(of, decon_driver_dt_match);
0067
0068 static const uint32_t decon_formats[] = {
0069 DRM_FORMAT_RGB565,
0070 DRM_FORMAT_XRGB8888,
0071 DRM_FORMAT_XBGR8888,
0072 DRM_FORMAT_RGBX8888,
0073 DRM_FORMAT_BGRX8888,
0074 DRM_FORMAT_ARGB8888,
0075 DRM_FORMAT_ABGR8888,
0076 DRM_FORMAT_RGBA8888,
0077 DRM_FORMAT_BGRA8888,
0078 };
0079
0080 static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
0081 DRM_PLANE_TYPE_PRIMARY,
0082 DRM_PLANE_TYPE_CURSOR,
0083 };
0084
0085 static void decon_wait_for_vblank(struct exynos_drm_crtc *crtc)
0086 {
0087 struct decon_context *ctx = crtc->ctx;
0088
0089 if (ctx->suspended)
0090 return;
0091
0092 atomic_set(&ctx->wait_vsync_event, 1);
0093
0094
0095
0096
0097
0098 if (!wait_event_timeout(ctx->wait_vsync_queue,
0099 !atomic_read(&ctx->wait_vsync_event),
0100 HZ/20))
0101 DRM_DEV_DEBUG_KMS(ctx->dev, "vblank wait timed out.\n");
0102 }
0103
0104 static void decon_clear_channels(struct exynos_drm_crtc *crtc)
0105 {
0106 struct decon_context *ctx = crtc->ctx;
0107 unsigned int win, ch_enabled = 0;
0108
0109
0110 for (win = 0; win < WINDOWS_NR; win++) {
0111 u32 val = readl(ctx->regs + WINCON(win));
0112
0113 if (val & WINCONx_ENWIN) {
0114 val &= ~WINCONx_ENWIN;
0115 writel(val, ctx->regs + WINCON(win));
0116 ch_enabled = 1;
0117 }
0118 }
0119
0120
0121 if (ch_enabled)
0122 decon_wait_for_vblank(ctx->crtc);
0123 }
0124
0125 static int decon_ctx_initialize(struct decon_context *ctx,
0126 struct drm_device *drm_dev)
0127 {
0128 ctx->drm_dev = drm_dev;
0129
0130 decon_clear_channels(ctx->crtc);
0131
0132 return exynos_drm_register_dma(drm_dev, ctx->dev, &ctx->dma_priv);
0133 }
0134
0135 static void decon_ctx_remove(struct decon_context *ctx)
0136 {
0137
0138 exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv);
0139 }
0140
0141 static u32 decon_calc_clkdiv(struct decon_context *ctx,
0142 const struct drm_display_mode *mode)
0143 {
0144 unsigned long ideal_clk = mode->clock;
0145 u32 clkdiv;
0146
0147
0148 clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->vclk), ideal_clk);
0149
0150 return (clkdiv < 0x100) ? clkdiv : 0xff;
0151 }
0152
0153 static void decon_commit(struct exynos_drm_crtc *crtc)
0154 {
0155 struct decon_context *ctx = crtc->ctx;
0156 struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
0157 u32 val, clkdiv;
0158
0159 if (ctx->suspended)
0160 return;
0161
0162
0163 if (mode->htotal == 0 || mode->vtotal == 0)
0164 return;
0165
0166 if (!ctx->i80_if) {
0167 int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
0168
0169 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
0170 vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
0171 vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
0172
0173 val = VIDTCON0_VBPD(vbpd - 1) | VIDTCON0_VFPD(vfpd - 1);
0174 writel(val, ctx->regs + VIDTCON0);
0175
0176 val = VIDTCON1_VSPW(vsync_len - 1);
0177 writel(val, ctx->regs + VIDTCON1);
0178
0179
0180 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
0181 hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
0182 hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
0183
0184
0185 val = VIDTCON2_HBPD(hbpd - 1) | VIDTCON2_HFPD(hfpd - 1);
0186 writel(val, ctx->regs + VIDTCON2);
0187
0188 val = VIDTCON3_HSPW(hsync_len - 1);
0189 writel(val, ctx->regs + VIDTCON3);
0190 }
0191
0192
0193 val = VIDTCON4_LINEVAL(mode->vdisplay - 1) |
0194 VIDTCON4_HOZVAL(mode->hdisplay - 1);
0195 writel(val, ctx->regs + VIDTCON4);
0196
0197 writel(mode->vdisplay - 1, ctx->regs + LINECNT_OP_THRESHOLD);
0198
0199
0200
0201
0202
0203 val = VIDCON0_ENVID | VIDCON0_ENVID_F;
0204 writel(val, ctx->regs + VIDCON0);
0205
0206 clkdiv = decon_calc_clkdiv(ctx, mode);
0207 if (clkdiv > 1) {
0208 val = VCLKCON1_CLKVAL_NUM_VCLK(clkdiv - 1);
0209 writel(val, ctx->regs + VCLKCON1);
0210 writel(val, ctx->regs + VCLKCON2);
0211 }
0212
0213 val = readl(ctx->regs + DECON_UPDATE);
0214 val |= DECON_UPDATE_STANDALONE_F;
0215 writel(val, ctx->regs + DECON_UPDATE);
0216 }
0217
0218 static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
0219 {
0220 struct decon_context *ctx = crtc->ctx;
0221 u32 val;
0222
0223 if (ctx->suspended)
0224 return -EPERM;
0225
0226 if (!test_and_set_bit(0, &ctx->irq_flags)) {
0227 val = readl(ctx->regs + VIDINTCON0);
0228
0229 val |= VIDINTCON0_INT_ENABLE;
0230
0231 if (!ctx->i80_if) {
0232 val |= VIDINTCON0_INT_FRAME;
0233 val &= ~VIDINTCON0_FRAMESEL0_MASK;
0234 val |= VIDINTCON0_FRAMESEL0_VSYNC;
0235 }
0236
0237 writel(val, ctx->regs + VIDINTCON0);
0238 }
0239
0240 return 0;
0241 }
0242
0243 static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
0244 {
0245 struct decon_context *ctx = crtc->ctx;
0246 u32 val;
0247
0248 if (ctx->suspended)
0249 return;
0250
0251 if (test_and_clear_bit(0, &ctx->irq_flags)) {
0252 val = readl(ctx->regs + VIDINTCON0);
0253
0254 val &= ~VIDINTCON0_INT_ENABLE;
0255 if (!ctx->i80_if)
0256 val &= ~VIDINTCON0_INT_FRAME;
0257
0258 writel(val, ctx->regs + VIDINTCON0);
0259 }
0260 }
0261
0262 static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
0263 struct drm_framebuffer *fb)
0264 {
0265 unsigned long val;
0266 int padding;
0267
0268 val = readl(ctx->regs + WINCON(win));
0269 val &= ~WINCONx_BPPMODE_MASK;
0270
0271 switch (fb->format->format) {
0272 case DRM_FORMAT_RGB565:
0273 val |= WINCONx_BPPMODE_16BPP_565;
0274 val |= WINCONx_BURSTLEN_16WORD;
0275 break;
0276 case DRM_FORMAT_XRGB8888:
0277 val |= WINCONx_BPPMODE_24BPP_xRGB;
0278 val |= WINCONx_BURSTLEN_16WORD;
0279 break;
0280 case DRM_FORMAT_XBGR8888:
0281 val |= WINCONx_BPPMODE_24BPP_xBGR;
0282 val |= WINCONx_BURSTLEN_16WORD;
0283 break;
0284 case DRM_FORMAT_RGBX8888:
0285 val |= WINCONx_BPPMODE_24BPP_RGBx;
0286 val |= WINCONx_BURSTLEN_16WORD;
0287 break;
0288 case DRM_FORMAT_BGRX8888:
0289 val |= WINCONx_BPPMODE_24BPP_BGRx;
0290 val |= WINCONx_BURSTLEN_16WORD;
0291 break;
0292 case DRM_FORMAT_ARGB8888:
0293 val |= WINCONx_BPPMODE_32BPP_ARGB | WINCONx_BLD_PIX |
0294 WINCONx_ALPHA_SEL;
0295 val |= WINCONx_BURSTLEN_16WORD;
0296 break;
0297 case DRM_FORMAT_ABGR8888:
0298 val |= WINCONx_BPPMODE_32BPP_ABGR | WINCONx_BLD_PIX |
0299 WINCONx_ALPHA_SEL;
0300 val |= WINCONx_BURSTLEN_16WORD;
0301 break;
0302 case DRM_FORMAT_RGBA8888:
0303 val |= WINCONx_BPPMODE_32BPP_RGBA | WINCONx_BLD_PIX |
0304 WINCONx_ALPHA_SEL;
0305 val |= WINCONx_BURSTLEN_16WORD;
0306 break;
0307 case DRM_FORMAT_BGRA8888:
0308 default:
0309 val |= WINCONx_BPPMODE_32BPP_BGRA | WINCONx_BLD_PIX |
0310 WINCONx_ALPHA_SEL;
0311 val |= WINCONx_BURSTLEN_16WORD;
0312 break;
0313 }
0314
0315 DRM_DEV_DEBUG_KMS(ctx->dev, "cpp = %d\n", fb->format->cpp[0]);
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 padding = (fb->pitches[0] / fb->format->cpp[0]) - fb->width;
0326 if (fb->width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
0327 val &= ~WINCONx_BURSTLEN_MASK;
0328 val |= WINCONx_BURSTLEN_8WORD;
0329 }
0330
0331 writel(val, ctx->regs + WINCON(win));
0332 }
0333
0334 static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win)
0335 {
0336 unsigned int keycon0 = 0, keycon1 = 0;
0337
0338 keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
0339 WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
0340
0341 keycon1 = WxKEYCON1_COLVAL(0xffffffff);
0342
0343 writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
0344 writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
0345 }
0346
0347
0348
0349
0350
0351
0352
0353
0354 static void decon_shadow_protect_win(struct decon_context *ctx,
0355 unsigned int win, bool protect)
0356 {
0357 u32 bits, val;
0358
0359 bits = SHADOWCON_WINx_PROTECT(win);
0360
0361 val = readl(ctx->regs + SHADOWCON);
0362 if (protect)
0363 val |= bits;
0364 else
0365 val &= ~bits;
0366 writel(val, ctx->regs + SHADOWCON);
0367 }
0368
0369 static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
0370 {
0371 struct decon_context *ctx = crtc->ctx;
0372 int i;
0373
0374 if (ctx->suspended)
0375 return;
0376
0377 for (i = 0; i < WINDOWS_NR; i++)
0378 decon_shadow_protect_win(ctx, i, true);
0379 }
0380
0381 static void decon_update_plane(struct exynos_drm_crtc *crtc,
0382 struct exynos_drm_plane *plane)
0383 {
0384 struct exynos_drm_plane_state *state =
0385 to_exynos_plane_state(plane->base.state);
0386 struct decon_context *ctx = crtc->ctx;
0387 struct drm_framebuffer *fb = state->base.fb;
0388 int padding;
0389 unsigned long val, alpha;
0390 unsigned int last_x;
0391 unsigned int last_y;
0392 unsigned int win = plane->index;
0393 unsigned int cpp = fb->format->cpp[0];
0394 unsigned int pitch = fb->pitches[0];
0395
0396 if (ctx->suspended)
0397 return;
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410 val = (unsigned long)exynos_drm_fb_dma_addr(fb, 0);
0411 writel(val, ctx->regs + VIDW_BUF_START(win));
0412
0413 padding = (pitch / cpp) - fb->width;
0414
0415
0416 writel(fb->width + padding, ctx->regs + VIDW_WHOLE_X(win));
0417 writel(fb->height, ctx->regs + VIDW_WHOLE_Y(win));
0418
0419
0420 writel(state->src.x, ctx->regs + VIDW_OFFSET_X(win));
0421 writel(state->src.y, ctx->regs + VIDW_OFFSET_Y(win));
0422
0423 DRM_DEV_DEBUG_KMS(ctx->dev, "start addr = 0x%lx\n",
0424 (unsigned long)val);
0425 DRM_DEV_DEBUG_KMS(ctx->dev, "ovl_width = %d, ovl_height = %d\n",
0426 state->crtc.w, state->crtc.h);
0427
0428 val = VIDOSDxA_TOPLEFT_X(state->crtc.x) |
0429 VIDOSDxA_TOPLEFT_Y(state->crtc.y);
0430 writel(val, ctx->regs + VIDOSD_A(win));
0431
0432 last_x = state->crtc.x + state->crtc.w;
0433 if (last_x)
0434 last_x--;
0435 last_y = state->crtc.y + state->crtc.h;
0436 if (last_y)
0437 last_y--;
0438
0439 val = VIDOSDxB_BOTRIGHT_X(last_x) | VIDOSDxB_BOTRIGHT_Y(last_y);
0440
0441 writel(val, ctx->regs + VIDOSD_B(win));
0442
0443 DRM_DEV_DEBUG_KMS(ctx->dev, "osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
0444 state->crtc.x, state->crtc.y, last_x, last_y);
0445
0446
0447 alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
0448 VIDOSDxC_ALPHA0_G_F(0x0) |
0449 VIDOSDxC_ALPHA0_B_F(0x0);
0450
0451 writel(alpha, ctx->regs + VIDOSD_C(win));
0452
0453 alpha = VIDOSDxD_ALPHA1_R_F(0xff) |
0454 VIDOSDxD_ALPHA1_G_F(0xff) |
0455 VIDOSDxD_ALPHA1_B_F(0xff);
0456
0457 writel(alpha, ctx->regs + VIDOSD_D(win));
0458
0459 decon_win_set_pixfmt(ctx, win, fb);
0460
0461
0462 if (win != 0)
0463 decon_win_set_colkey(ctx, win);
0464
0465
0466 val = readl(ctx->regs + WINCON(win));
0467 val |= WINCONx_TRIPLE_BUF_MODE;
0468 val |= WINCONx_ENWIN;
0469 writel(val, ctx->regs + WINCON(win));
0470
0471
0472 decon_shadow_protect_win(ctx, win, false);
0473
0474 val = readl(ctx->regs + DECON_UPDATE);
0475 val |= DECON_UPDATE_STANDALONE_F;
0476 writel(val, ctx->regs + DECON_UPDATE);
0477 }
0478
0479 static void decon_disable_plane(struct exynos_drm_crtc *crtc,
0480 struct exynos_drm_plane *plane)
0481 {
0482 struct decon_context *ctx = crtc->ctx;
0483 unsigned int win = plane->index;
0484 u32 val;
0485
0486 if (ctx->suspended)
0487 return;
0488
0489
0490 decon_shadow_protect_win(ctx, win, true);
0491
0492
0493 val = readl(ctx->regs + WINCON(win));
0494 val &= ~WINCONx_ENWIN;
0495 writel(val, ctx->regs + WINCON(win));
0496
0497 val = readl(ctx->regs + DECON_UPDATE);
0498 val |= DECON_UPDATE_STANDALONE_F;
0499 writel(val, ctx->regs + DECON_UPDATE);
0500 }
0501
0502 static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
0503 {
0504 struct decon_context *ctx = crtc->ctx;
0505 int i;
0506
0507 if (ctx->suspended)
0508 return;
0509
0510 for (i = 0; i < WINDOWS_NR; i++)
0511 decon_shadow_protect_win(ctx, i, false);
0512 exynos_crtc_handle_event(crtc);
0513 }
0514
0515 static void decon_init(struct decon_context *ctx)
0516 {
0517 u32 val;
0518
0519 writel(VIDCON0_SWRESET, ctx->regs + VIDCON0);
0520
0521 val = VIDOUTCON0_DISP_IF_0_ON;
0522 if (!ctx->i80_if)
0523 val |= VIDOUTCON0_RGBIF;
0524 writel(val, ctx->regs + VIDOUTCON0);
0525
0526 writel(VCLKCON0_CLKVALUP | VCLKCON0_VCLKFREE, ctx->regs + VCLKCON0);
0527
0528 if (!ctx->i80_if)
0529 writel(VIDCON1_VCLK_HOLD, ctx->regs + VIDCON1(0));
0530 }
0531
0532 static void decon_atomic_enable(struct exynos_drm_crtc *crtc)
0533 {
0534 struct decon_context *ctx = crtc->ctx;
0535 int ret;
0536
0537 if (!ctx->suspended)
0538 return;
0539
0540 ret = pm_runtime_resume_and_get(ctx->dev);
0541 if (ret < 0) {
0542 DRM_DEV_ERROR(ctx->dev, "failed to enable DECON device.\n");
0543 return;
0544 }
0545
0546 decon_init(ctx);
0547
0548
0549 if (test_and_clear_bit(0, &ctx->irq_flags))
0550 decon_enable_vblank(ctx->crtc);
0551
0552 decon_commit(ctx->crtc);
0553
0554 ctx->suspended = false;
0555 }
0556
0557 static void decon_atomic_disable(struct exynos_drm_crtc *crtc)
0558 {
0559 struct decon_context *ctx = crtc->ctx;
0560 int i;
0561
0562 if (ctx->suspended)
0563 return;
0564
0565
0566
0567
0568
0569
0570 for (i = 0; i < WINDOWS_NR; i++)
0571 decon_disable_plane(crtc, &ctx->planes[i]);
0572
0573 pm_runtime_put_sync(ctx->dev);
0574
0575 ctx->suspended = true;
0576 }
0577
0578 static const struct exynos_drm_crtc_ops decon_crtc_ops = {
0579 .atomic_enable = decon_atomic_enable,
0580 .atomic_disable = decon_atomic_disable,
0581 .enable_vblank = decon_enable_vblank,
0582 .disable_vblank = decon_disable_vblank,
0583 .atomic_begin = decon_atomic_begin,
0584 .update_plane = decon_update_plane,
0585 .disable_plane = decon_disable_plane,
0586 .atomic_flush = decon_atomic_flush,
0587 };
0588
0589
0590 static irqreturn_t decon_irq_handler(int irq, void *dev_id)
0591 {
0592 struct decon_context *ctx = (struct decon_context *)dev_id;
0593 u32 val, clear_bit;
0594
0595 val = readl(ctx->regs + VIDINTCON1);
0596
0597 clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME;
0598 if (val & clear_bit)
0599 writel(clear_bit, ctx->regs + VIDINTCON1);
0600
0601
0602 if (!ctx->drm_dev)
0603 goto out;
0604
0605 if (!ctx->i80_if) {
0606 drm_crtc_handle_vblank(&ctx->crtc->base);
0607
0608
0609 if (atomic_read(&ctx->wait_vsync_event)) {
0610 atomic_set(&ctx->wait_vsync_event, 0);
0611 wake_up(&ctx->wait_vsync_queue);
0612 }
0613 }
0614 out:
0615 return IRQ_HANDLED;
0616 }
0617
0618 static int decon_bind(struct device *dev, struct device *master, void *data)
0619 {
0620 struct decon_context *ctx = dev_get_drvdata(dev);
0621 struct drm_device *drm_dev = data;
0622 struct exynos_drm_plane *exynos_plane;
0623 unsigned int i;
0624 int ret;
0625
0626 ret = decon_ctx_initialize(ctx, drm_dev);
0627 if (ret) {
0628 DRM_DEV_ERROR(dev, "decon_ctx_initialize failed.\n");
0629 return ret;
0630 }
0631
0632 for (i = 0; i < WINDOWS_NR; i++) {
0633 ctx->configs[i].pixel_formats = decon_formats;
0634 ctx->configs[i].num_pixel_formats = ARRAY_SIZE(decon_formats);
0635 ctx->configs[i].zpos = i;
0636 ctx->configs[i].type = decon_win_types[i];
0637
0638 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
0639 &ctx->configs[i]);
0640 if (ret)
0641 return ret;
0642 }
0643
0644 exynos_plane = &ctx->planes[DEFAULT_WIN];
0645 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
0646 EXYNOS_DISPLAY_TYPE_LCD, &decon_crtc_ops, ctx);
0647 if (IS_ERR(ctx->crtc)) {
0648 decon_ctx_remove(ctx);
0649 return PTR_ERR(ctx->crtc);
0650 }
0651
0652 if (ctx->encoder)
0653 exynos_dpi_bind(drm_dev, ctx->encoder);
0654
0655 return 0;
0656
0657 }
0658
0659 static void decon_unbind(struct device *dev, struct device *master,
0660 void *data)
0661 {
0662 struct decon_context *ctx = dev_get_drvdata(dev);
0663
0664 decon_atomic_disable(ctx->crtc);
0665
0666 if (ctx->encoder)
0667 exynos_dpi_remove(ctx->encoder);
0668
0669 decon_ctx_remove(ctx);
0670 }
0671
0672 static const struct component_ops decon_component_ops = {
0673 .bind = decon_bind,
0674 .unbind = decon_unbind,
0675 };
0676
0677 static int decon_probe(struct platform_device *pdev)
0678 {
0679 struct device *dev = &pdev->dev;
0680 struct decon_context *ctx;
0681 struct device_node *i80_if_timings;
0682 int ret;
0683
0684 if (!dev->of_node)
0685 return -ENODEV;
0686
0687 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0688 if (!ctx)
0689 return -ENOMEM;
0690
0691 ctx->dev = dev;
0692 ctx->suspended = true;
0693
0694 i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
0695 if (i80_if_timings)
0696 ctx->i80_if = true;
0697 of_node_put(i80_if_timings);
0698
0699 ctx->regs = of_iomap(dev->of_node, 0);
0700 if (!ctx->regs)
0701 return -ENOMEM;
0702
0703 ctx->pclk = devm_clk_get(dev, "pclk_decon0");
0704 if (IS_ERR(ctx->pclk)) {
0705 dev_err(dev, "failed to get bus clock pclk\n");
0706 ret = PTR_ERR(ctx->pclk);
0707 goto err_iounmap;
0708 }
0709
0710 ctx->aclk = devm_clk_get(dev, "aclk_decon0");
0711 if (IS_ERR(ctx->aclk)) {
0712 dev_err(dev, "failed to get bus clock aclk\n");
0713 ret = PTR_ERR(ctx->aclk);
0714 goto err_iounmap;
0715 }
0716
0717 ctx->eclk = devm_clk_get(dev, "decon0_eclk");
0718 if (IS_ERR(ctx->eclk)) {
0719 dev_err(dev, "failed to get eclock\n");
0720 ret = PTR_ERR(ctx->eclk);
0721 goto err_iounmap;
0722 }
0723
0724 ctx->vclk = devm_clk_get(dev, "decon0_vclk");
0725 if (IS_ERR(ctx->vclk)) {
0726 dev_err(dev, "failed to get vclock\n");
0727 ret = PTR_ERR(ctx->vclk);
0728 goto err_iounmap;
0729 }
0730
0731 ret = platform_get_irq_byname(pdev, ctx->i80_if ? "lcd_sys" : "vsync");
0732 if (ret < 0)
0733 goto err_iounmap;
0734
0735 ret = devm_request_irq(dev, ret, decon_irq_handler, 0, "drm_decon", ctx);
0736 if (ret) {
0737 dev_err(dev, "irq request failed.\n");
0738 goto err_iounmap;
0739 }
0740
0741 init_waitqueue_head(&ctx->wait_vsync_queue);
0742 atomic_set(&ctx->wait_vsync_event, 0);
0743
0744 platform_set_drvdata(pdev, ctx);
0745
0746 ctx->encoder = exynos_dpi_probe(dev);
0747 if (IS_ERR(ctx->encoder)) {
0748 ret = PTR_ERR(ctx->encoder);
0749 goto err_iounmap;
0750 }
0751
0752 pm_runtime_enable(dev);
0753
0754 ret = component_add(dev, &decon_component_ops);
0755 if (ret)
0756 goto err_disable_pm_runtime;
0757
0758 return ret;
0759
0760 err_disable_pm_runtime:
0761 pm_runtime_disable(dev);
0762
0763 err_iounmap:
0764 iounmap(ctx->regs);
0765
0766 return ret;
0767 }
0768
0769 static int decon_remove(struct platform_device *pdev)
0770 {
0771 struct decon_context *ctx = dev_get_drvdata(&pdev->dev);
0772
0773 pm_runtime_disable(&pdev->dev);
0774
0775 iounmap(ctx->regs);
0776
0777 component_del(&pdev->dev, &decon_component_ops);
0778
0779 return 0;
0780 }
0781
0782 #ifdef CONFIG_PM
0783 static int exynos7_decon_suspend(struct device *dev)
0784 {
0785 struct decon_context *ctx = dev_get_drvdata(dev);
0786
0787 clk_disable_unprepare(ctx->vclk);
0788 clk_disable_unprepare(ctx->eclk);
0789 clk_disable_unprepare(ctx->aclk);
0790 clk_disable_unprepare(ctx->pclk);
0791
0792 return 0;
0793 }
0794
0795 static int exynos7_decon_resume(struct device *dev)
0796 {
0797 struct decon_context *ctx = dev_get_drvdata(dev);
0798 int ret;
0799
0800 ret = clk_prepare_enable(ctx->pclk);
0801 if (ret < 0) {
0802 DRM_DEV_ERROR(dev, "Failed to prepare_enable the pclk [%d]\n",
0803 ret);
0804 goto err_pclk_enable;
0805 }
0806
0807 ret = clk_prepare_enable(ctx->aclk);
0808 if (ret < 0) {
0809 DRM_DEV_ERROR(dev, "Failed to prepare_enable the aclk [%d]\n",
0810 ret);
0811 goto err_aclk_enable;
0812 }
0813
0814 ret = clk_prepare_enable(ctx->eclk);
0815 if (ret < 0) {
0816 DRM_DEV_ERROR(dev, "Failed to prepare_enable the eclk [%d]\n",
0817 ret);
0818 goto err_eclk_enable;
0819 }
0820
0821 ret = clk_prepare_enable(ctx->vclk);
0822 if (ret < 0) {
0823 DRM_DEV_ERROR(dev, "Failed to prepare_enable the vclk [%d]\n",
0824 ret);
0825 goto err_vclk_enable;
0826 }
0827
0828 return 0;
0829
0830 err_vclk_enable:
0831 clk_disable_unprepare(ctx->eclk);
0832 err_eclk_enable:
0833 clk_disable_unprepare(ctx->aclk);
0834 err_aclk_enable:
0835 clk_disable_unprepare(ctx->pclk);
0836 err_pclk_enable:
0837 return ret;
0838 }
0839 #endif
0840
0841 static const struct dev_pm_ops exynos7_decon_pm_ops = {
0842 SET_RUNTIME_PM_OPS(exynos7_decon_suspend, exynos7_decon_resume,
0843 NULL)
0844 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
0845 pm_runtime_force_resume)
0846 };
0847
0848 struct platform_driver decon_driver = {
0849 .probe = decon_probe,
0850 .remove = decon_remove,
0851 .driver = {
0852 .name = "exynos-decon",
0853 .pm = &exynos7_decon_pm_ops,
0854 .of_match_table = decon_driver_dt_match,
0855 },
0856 };