3 * Copyright (C) 2011 Samsung Electronics Co.Ltd
5 * Joonyoung Shim <jy0922.shim@samsung.com>
6 * Inki Dae <inki.dae@samsung.com>
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.
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/clk.h>
21 #include <drm/exynos_drm.h>
22 #include <plat/regs-fb-v4.h>
24 #include "exynos_dp_core.h"
25 #include "exynos_drm_drv.h"
26 #include "exynos_drm_crtc.h"
27 #include "exynos_drm_fbdev.h"
28 #include "exynos_drm_display.h"
31 * FIMD is stand for Fully Interactive Mobile Display and
32 * as a display controller, it transfers contents drawn on memory
33 * to a LCD Panel through Display Interfaces such as RGB or
37 /* position control register for hardware window 0, 2 ~ 4.*/
38 #define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16)
39 #define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16)
40 /* size control register for hardware window 0. */
41 #define VIDOSD_C_SIZE_W0 (VIDOSD_BASE + 0x08)
42 /* alpha control register for hardware window 1 ~ 4. */
43 #define VIDOSD_C(win) (VIDOSD_BASE + 0x18 + (win) * 16)
44 /* size control register for hardware window 1 ~ 4. */
45 #define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16)
47 #define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8)
48 #define VIDWx_BUF_END(win, buf) (VIDW_BUF_END(buf) + (win) * 8)
49 #define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4)
51 /* color key control register for hardware window 1 ~ 4. */
52 #define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + (x * 8))
53 /* color key value register for hardware window 1 ~ 4. */
54 #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + (x * 8))
56 /* FIMD has totally five hardware windows. */
59 #define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev))
61 struct fimd_win_data {
62 unsigned int offset_x;
63 unsigned int offset_y;
64 unsigned int ovl_width;
65 unsigned int ovl_height;
66 unsigned int fb_width;
67 unsigned int fb_height;
68 unsigned int fb_pitch;
72 * TODO(seanpaul): These fields only really make sense for the 'default
73 * window', but we go through the same path for updating a plane as we
74 * do for setting the crtc mode. If/when/once these are decoupled, this
75 * code should be refactored to seperate plane/overlay/window settings
78 unsigned int hsync_len;
80 unsigned int vsync_len;
85 unsigned int buf_offsize;
86 unsigned int line_size; /* bytes */
92 struct drm_device *drm_dev;
93 enum disp_panel_type panel_type;
96 struct drm_crtc *crtc;
99 struct resource *regs_res;
101 void __iomem *regs_mie;
102 struct fimd_win_data win_data[WINDOWS_NR];
103 unsigned int default_win;
104 unsigned long irq_flags;
111 struct exynos_drm_panel_info *panel;
114 static struct exynos_drm_panel_info *fimd_get_panel(void *ctx)
116 struct fimd_context *fimd_ctx = ctx;
118 DRM_DEBUG_KMS("%s\n", __FILE__);
120 return fimd_ctx->panel;
123 static int fimd_power_on(struct fimd_context *ctx, bool enable);
125 static int fimd_power(void *ctx, int mode)
127 struct fimd_context *fimd_ctx = ctx;
130 DRM_DEBUG_KMS("%s\n", __FILE__);
133 case DRM_MODE_DPMS_ON:
136 case DRM_MODE_DPMS_STANDBY:
137 case DRM_MODE_DPMS_SUSPEND:
138 case DRM_MODE_DPMS_OFF:
142 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
146 fimd_power_on(fimd_ctx, enable);
151 static void fimd_commit(void *ctx)
153 struct fimd_context *fimd_ctx = ctx;
154 struct fimd_win_data *win_data;
157 if (fimd_ctx->suspended)
159 win_data = &fimd_ctx->win_data[fimd_ctx->default_win];
161 if (!win_data->ovl_width || !win_data->ovl_height)
164 DRM_DEBUG_KMS("%s\n", __FILE__);
166 /* setup polarity values from machine code. */
167 writel(fimd_ctx->vidcon1, fimd_ctx->regs + VIDCON1);
169 /* setup vertical timing values. */
170 val = VIDTCON0_VBPD(win_data->vmargin - 1) |
171 VIDTCON0_VFPD(win_data->vmargin - 1) |
172 VIDTCON0_VSPW(win_data->vsync_len - 1);
173 writel(val, fimd_ctx->regs + VIDTCON0);
175 /* setup horizontal timing values. */
176 val = VIDTCON1_HBPD(win_data->hmargin - 1) |
177 VIDTCON1_HFPD(win_data->hmargin - 1) |
178 VIDTCON1_HSPW(win_data->hsync_len - 1);
179 writel(val, fimd_ctx->regs + VIDTCON1);
181 /* setup horizontal and vertical display size. */
182 val = VIDTCON2_LINEVAL(win_data->ovl_height - 1) |
183 VIDTCON2_HOZVAL(win_data->ovl_width - 1);
184 writel(val, fimd_ctx->regs + VIDTCON2);
186 /* setup clock source, clock divider, enable dma. */
187 val = fimd_ctx->vidcon0;
188 val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
190 if (fimd_ctx->clkdiv)
191 val |= VIDCON0_CLKVAL_F(fimd_ctx->clkdiv - 1) | VIDCON0_CLKDIR;
193 val &= ~VIDCON0_CLKDIR; /* 1:1 clock */
196 * fields of register with prefix '_F' would be updated
197 * at vsync(same as dma start)
199 val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
200 writel(val, fimd_ctx->regs + VIDCON0);
203 static int fimd_enable_vblank(void *ctx, int pipe)
205 struct fimd_context *fimd_ctx = ctx;
208 DRM_DEBUG_KMS("%s\n", __FILE__);
210 fimd_ctx->pipe = pipe;
212 if (fimd_ctx->suspended)
215 if (!test_and_set_bit(0, &fimd_ctx->irq_flags)) {
216 val = readl(fimd_ctx->regs + VIDINTCON0);
218 val |= VIDINTCON0_INT_ENABLE;
219 val |= VIDINTCON0_INT_FRAME;
221 val &= ~VIDINTCON0_FRAMESEL0_MASK;
222 val |= VIDINTCON0_FRAMESEL0_VSYNC;
223 val &= ~VIDINTCON0_FRAMESEL1_MASK;
224 val |= VIDINTCON0_FRAMESEL1_NONE;
226 writel(val, fimd_ctx->regs + VIDINTCON0);
232 static void fimd_disable_vblank(void *ctx)
234 struct fimd_context *fimd_ctx = ctx;
237 DRM_DEBUG_KMS("%s\n", __FILE__);
239 if (fimd_ctx->suspended)
242 if (test_and_clear_bit(0, &fimd_ctx->irq_flags)) {
243 val = readl(fimd_ctx->regs + VIDINTCON0);
245 val &= ~VIDINTCON0_INT_FRAME;
246 val &= ~VIDINTCON0_INT_ENABLE;
248 writel(val, fimd_ctx->regs + VIDINTCON0);
252 static int fimd_calc_clkdiv(struct fimd_context *fimd_ctx,
253 struct fimd_win_data *win_data,
256 unsigned long clk = clk_get_rate(fimd_ctx->lcd_clk);
259 u32 best_framerate = 0;
262 DRM_DEBUG_KMS("%s\n", __FILE__);
264 retrace = win_data->hmargin * 2 + win_data->hsync_len +
266 retrace *= win_data->vmargin * 2 + win_data->vsync_len +
267 win_data->ovl_height;
269 /* default framerate is 60Hz */
275 for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
278 /* get best framerate */
279 framerate = clk / clkdiv;
280 tmp = refresh - framerate;
282 best_framerate = framerate;
286 best_framerate = framerate;
287 else if (tmp < (best_framerate - framerate))
288 best_framerate = framerate;
295 static void fimd_win_mode_set(void *ctx, struct exynos_drm_overlay *overlay)
297 struct fimd_context *fimd_ctx = ctx;
298 struct fimd_win_data *win_data;
300 unsigned long offset;
302 DRM_DEBUG_KMS("%s\n", __FILE__);
305 DRM_ERROR("overlay is NULL\n");
310 if (win == DEFAULT_ZPOS)
311 win = fimd_ctx->default_win;
313 if (win < 0 || win > WINDOWS_NR)
316 offset = overlay->fb_x * (overlay->bpp >> 3);
317 offset += overlay->fb_y * overlay->fb_pitch;
319 DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n",
320 offset, overlay->fb_pitch);
322 win_data = &fimd_ctx->win_data[win];
324 win_data->offset_x = overlay->crtc_x;
325 win_data->offset_y = overlay->crtc_y;
326 win_data->ovl_width = overlay->crtc_width;
327 win_data->ovl_height = overlay->crtc_height;
328 win_data->fb_width = overlay->fb_width;
329 win_data->fb_height = overlay->fb_height;
330 win_data->fb_pitch = overlay->fb_pitch;
331 win_data->hsync_len = overlay->crtc_hsync_len;
332 win_data->hmargin = (overlay->crtc_htotal - overlay->crtc_width -
333 overlay->crtc_hsync_len) / 2;
334 win_data->vsync_len = overlay->crtc_vsync_len;
335 win_data->vmargin = (overlay->crtc_vtotal - overlay->crtc_height -
336 overlay->crtc_vsync_len) / 2;
337 win_data->dma_addr = overlay->dma_addr[0] + offset;
338 win_data->vaddr = overlay->vaddr[0] + offset;
339 win_data->bpp = overlay->bpp;
340 win_data->buf_offsize = overlay->fb_pitch -
341 (overlay->fb_width * (overlay->bpp >> 3));
342 win_data->line_size = overlay->fb_width * (overlay->bpp >> 3);
344 if (win == fimd_ctx->default_win)
345 fimd_ctx->clkdiv = fimd_calc_clkdiv(fimd_ctx, win_data,
348 DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
349 win_data->offset_x, win_data->offset_y);
350 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
351 win_data->ovl_width, win_data->ovl_height);
352 DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
353 (unsigned long)win_data->dma_addr,
354 (unsigned long)win_data->vaddr);
355 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
356 overlay->fb_width, overlay->crtc_width);
359 static void fimd_win_set_pixfmt(struct fimd_context *fimd_ctx, unsigned int win)
361 struct fimd_win_data *win_data = &fimd_ctx->win_data[win];
365 DRM_DEBUG_KMS("%s\n", __FILE__);
369 switch (win_data->bpp) {
371 val |= WINCON0_BPPMODE_1BPP;
372 val |= WINCONx_BITSWP;
373 bytes = win_data->fb_width >> 3;
376 val |= WINCON0_BPPMODE_2BPP;
377 val |= WINCONx_BITSWP;
378 bytes = win_data->fb_width >> 2;
381 val |= WINCON0_BPPMODE_4BPP;
382 val |= WINCONx_BITSWP;
383 bytes = win_data->fb_width >> 1;
386 val |= WINCON0_BPPMODE_8BPP_PALETTE;
387 val |= WINCONx_BYTSWP;
388 bytes = win_data->fb_width;
391 val |= WINCON0_BPPMODE_16BPP_565;
392 val |= WINCONx_HAWSWP;
393 bytes = win_data->fb_width << 1;
396 val |= WINCON0_BPPMODE_24BPP_888;
398 bytes = win_data->fb_width * 3;
401 val |= WINCON1_BPPMODE_28BPP_A4888
402 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
404 bytes = win_data->fb_width << 2;
407 DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
408 bytes = win_data->fb_width * 3;
409 val |= WINCON0_BPPMODE_24BPP_888;
415 * Adjust the burst size based on the number of bytes to be read.
416 * Each WORD of the BURST is 8 bytes long. There are 3 BURST sizes
418 * WINCONx_BURSTLEN_4WORD = 32 bytes
419 * WINCONx_BURSTLEN_8WORD = 64 bytes
420 * WINCONx_BURSTLEN_16WORD = 128 bytes
422 if (win_data->fb_width <= 64)
423 val |= WINCONx_BURSTLEN_4WORD;
425 val |= WINCONx_BURSTLEN_16WORD;
427 DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
429 writel(val, fimd_ctx->regs + WINCON(win));
432 static void fimd_win_set_colkey(struct fimd_context *fimd_ctx, unsigned int win)
434 unsigned int keycon0 = 0, keycon1 = 0;
436 DRM_DEBUG_KMS("%s\n", __FILE__);
438 keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
439 WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
441 keycon1 = WxKEYCON1_COLVAL(0xffffffff);
443 writel(keycon0, fimd_ctx->regs + WKEYCON0_BASE(win));
444 writel(keycon1, fimd_ctx->regs + WKEYCON1_BASE(win));
447 static void mie_set_6bit_dithering(struct fimd_context *ctx, int win)
449 struct fimd_win_data *win_data = &ctx->win_data[win];
451 unsigned int width, height;
454 width = win_data->ovl_width;
455 height = win_data->ovl_height;
457 writel(MIE_HRESOL(width) | MIE_VRESOL(height) | MIE_MODE_UI,
458 ctx->regs_mie + MIE_CTRL1);
460 writel(MIE_WINHADDR0(0) | MIE_WINHADDR1(width),
461 ctx->regs_mie + MIE_WINHADDR);
462 writel(MIE_WINVADDR0(0) | MIE_WINVADDR1(height),
463 ctx->regs_mie + MIE_WINVADDR);
465 val = (width + win_data->hmargin * 2 + win_data->hsync_len) *
466 (height + win_data->vmargin * 2 + win_data->vsync_len) /
469 writel(PWMCLKCNT(val), ctx->regs_mie + MIE_PWMCLKCNT);
471 writel((MIE_VBPD(win_data->vmargin)) | MIE_VFPD(win_data->vmargin) |
472 MIE_VSPW(win_data->vsync_len), ctx->regs_mie + MIE_PWMVIDTCON1);
474 writel(MIE_HBPD(win_data->hmargin) | MIE_HFPD(win_data->hmargin) |
475 MIE_HSPW(win_data->hsync_len), ctx->regs_mie + MIE_PWMVIDTCON2);
477 writel(MIE_DITHCON_EN | MIE_RGB6MODE, ctx->regs_mie + MIE_AUXCON);
479 /* Bypass MIE image brightness enhancement */
480 for (i = 0; i <= 0x30; i += 4) {
481 writel(0, ctx->regs_mie + 0x100 + i);
482 writel(0, ctx->regs_mie + 0x200 + i);
486 static void fimd_win_commit(void *ctx, int zpos)
488 struct fimd_context *fimd_ctx = ctx;
489 struct fimd_win_data *win_data;
491 unsigned long val, alpha, size;
493 DRM_DEBUG_KMS("%s\n", __FILE__);
495 if (fimd_ctx->suspended)
498 if (win == DEFAULT_ZPOS)
499 win = fimd_ctx->default_win;
501 if (win < 0 || win > WINDOWS_NR)
504 win_data = &fimd_ctx->win_data[win];
507 * SHADOWCON register is used for enabling timing.
509 * for example, once only width value of a register is set,
510 * if the dma is started then fimd hardware could malfunction so
511 * with protect window setting, the register fields with prefix '_F'
512 * wouldn't be updated at vsync also but updated once unprotect window
516 /* protect windows */
517 val = readl(fimd_ctx->regs + SHADOWCON);
518 val |= SHADOWCON_WINx_PROTECT(win);
519 writel(val, fimd_ctx->regs + SHADOWCON);
521 /* buffer start address */
522 val = (unsigned long)win_data->dma_addr;
523 writel(val, fimd_ctx->regs + VIDWx_BUF_START(win, 0));
525 /* buffer end address */
526 size = win_data->fb_height * win_data->fb_pitch;
527 val = (unsigned long)(win_data->dma_addr + size);
528 writel(val, fimd_ctx->regs + VIDWx_BUF_END(win, 0));
530 DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
531 (unsigned long)win_data->dma_addr, val, size);
532 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
533 win_data->ovl_width, win_data->ovl_height);
536 val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
537 VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size);
538 writel(val, fimd_ctx->regs + VIDWx_BUF_SIZE(win, 0));
541 val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
542 VIDOSDxA_TOPLEFT_Y(win_data->offset_y);
543 writel(val, fimd_ctx->regs + VIDOSD_A(win));
545 val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x +
546 win_data->ovl_width - 1) |
547 VIDOSDxB_BOTRIGHT_Y(win_data->offset_y +
548 win_data->ovl_height - 1);
549 writel(val, fimd_ctx->regs + VIDOSD_B(win));
551 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
552 win_data->offset_x, win_data->offset_y,
553 win_data->offset_x + win_data->ovl_width - 1,
554 win_data->offset_y + win_data->ovl_height - 1);
556 /* hardware window 0 doesn't support alpha channel. */
559 alpha = VIDISD14C_ALPHA1_R(0xf) |
560 VIDISD14C_ALPHA1_G(0xf) |
561 VIDISD14C_ALPHA1_B(0xf);
563 writel(alpha, fimd_ctx->regs + VIDOSD_C(win));
567 if (win != 3 && win != 4) {
568 u32 offset = VIDOSD_D(win);
570 offset = VIDOSD_C_SIZE_W0;
571 val = win_data->ovl_width * win_data->ovl_height;
572 writel(val, fimd_ctx->regs + offset);
574 DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
577 fimd_win_set_pixfmt(fimd_ctx, win);
579 /* hardware window 0 doesn't support color key. */
581 fimd_win_set_colkey(fimd_ctx, win);
584 val = readl(fimd_ctx->regs + WINCON(win));
585 val |= WINCONx_ENWIN;
586 writel(val, fimd_ctx->regs + WINCON(win));
588 /* only apply dithering on hardware window 0. */
590 mie_set_6bit_dithering(fimd_ctx, win);
592 /* Enable DMA channel and unprotect windows */
593 val = readl(fimd_ctx->regs + SHADOWCON);
594 val |= SHADOWCON_CHx_ENABLE(win);
595 val &= ~SHADOWCON_WINx_PROTECT(win);
596 writel(val, fimd_ctx->regs + SHADOWCON);
598 win_data->enabled = true;
601 static void fimd_win_disable(void *ctx, int zpos)
603 struct fimd_context *fimd_ctx = ctx;
604 struct fimd_win_data *win_data;
608 DRM_DEBUG_KMS("%s\n", __FILE__);
609 if (fimd_ctx->suspended)
612 if (win == DEFAULT_ZPOS)
613 win = fimd_ctx->default_win;
615 if (win < 0 || win > WINDOWS_NR)
618 win_data = &fimd_ctx->win_data[win];
620 /* protect windows */
621 val = readl(fimd_ctx->regs + SHADOWCON);
622 val |= SHADOWCON_WINx_PROTECT(win);
623 writel(val, fimd_ctx->regs + SHADOWCON);
626 val = readl(fimd_ctx->regs + WINCON(win));
627 val &= ~WINCONx_ENWIN;
628 writel(val, fimd_ctx->regs + WINCON(win));
630 /* unprotect windows */
631 val = readl(fimd_ctx->regs + SHADOWCON);
632 val &= ~SHADOWCON_CHx_ENABLE(win);
633 val &= ~SHADOWCON_WINx_PROTECT(win);
634 writel(val, fimd_ctx->regs + SHADOWCON);
636 win_data->enabled = false;
639 static void fimd_apply(void *ctx)
641 struct fimd_context *fimd_ctx = ctx;
642 struct fimd_win_data *win_data;
645 for (i = 0; i < WINDOWS_NR; i++) {
646 win_data = &fimd_ctx->win_data[i];
647 if (win_data->enabled)
648 fimd_win_commit(ctx, i);
652 static irqreturn_t fimd_irq_handler(int irq, void *arg)
654 struct fimd_context *fimd_ctx = (struct fimd_context *)arg;
657 val = readl(fimd_ctx->regs + VIDINTCON1);
659 if (val & VIDINTCON1_INT_FRAME)
660 /* VSYNC interrupt */
661 writel(VIDINTCON1_INT_FRAME, fimd_ctx->regs + VIDINTCON1);
663 /* check the crtc is detached already from encoder */
664 if (fimd_ctx->pipe < 0)
667 drm_handle_vblank(fimd_ctx->drm_dev, fimd_ctx->pipe);
668 exynos_drm_crtc_finish_pageflip(fimd_ctx->drm_dev, fimd_ctx->pipe);
674 static int fimd_subdrv_probe(void *ctx, struct drm_device *drm_dev)
676 struct fimd_context *fimd_ctx = ctx;
677 DRM_DEBUG_KMS("%s\n", __FILE__);
680 * enable drm irq mode.
681 * - with irq_enabled = 1, we can use the vblank feature.
683 * P.S. note that we wouldn't use drm irq handler but
684 * just specific driver own one instead because
685 * drm framework supports only one irq handler.
687 drm_dev->irq_enabled = 1;
690 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
691 * by drm timer once a current process gives up ownership of
692 * vblank event.(after drm_vblank_put function is called)
694 drm_dev->vblank_disable_allowed = 1;
696 fimd_ctx->drm_dev = drm_dev;
701 static struct exynos_controller_ops fimd_controller_ops = {
702 .subdrv_probe = fimd_subdrv_probe,
703 .get_panel = fimd_get_panel,
704 .enable_vblank = fimd_enable_vblank,
705 .disable_vblank = fimd_disable_vblank,
707 .mode_set = fimd_win_mode_set,
708 .commit = fimd_commit,
710 .win_commit = fimd_win_commit,
711 .win_disable = fimd_win_disable,
714 static void fimd_clear_win(struct fimd_context *ctx, int win)
718 DRM_DEBUG_KMS("%s\n", __FILE__);
720 writel(0, ctx->regs + WINCON(win));
721 writel(0, ctx->regs + VIDOSD_A(win));
722 writel(0, ctx->regs + VIDOSD_B(win));
723 writel(0, ctx->regs + VIDOSD_C(win));
725 if (win == 1 || win == 2)
726 writel(0, ctx->regs + VIDOSD_D(win));
728 val = readl(ctx->regs + SHADOWCON);
729 val &= ~SHADOWCON_WINx_PROTECT(win);
730 writel(val, ctx->regs + SHADOWCON);
734 * Disables all windows for suspend, keeps track of which ones were enabled.
736 static void fimd_window_suspend(struct fimd_context *fimd_ctx)
738 struct fimd_win_data *win_data;
741 for(i = 0; i < WINDOWS_NR; i++)
743 win_data = &fimd_ctx->win_data[i];
744 win_data->win_suspended = win_data->enabled;
745 fimd_win_disable(fimd_ctx, i);
750 * Resumes the suspended windows.
752 static void fimd_window_resume(struct fimd_context *fimd_ctx)
754 struct fimd_win_data *win_data;
757 for(i = 0; i < WINDOWS_NR; i++)
759 win_data = &fimd_ctx->win_data[i];
760 if (win_data->win_suspended) {
761 fimd_win_commit(fimd_ctx, i);
762 win_data->win_suspended = false;
767 static int fimd_power_on(struct fimd_context *fimd_ctx, bool enable)
769 DRM_DEBUG_KMS("%s\n", __FILE__);
774 ret = clk_enable(fimd_ctx->bus_clk);
778 ret = clk_enable(fimd_ctx->lcd_clk);
780 clk_disable(fimd_ctx->bus_clk);
784 fimd_ctx->suspended = false;
786 /* if vblank was enabled status, enable it again. */
787 if (test_and_clear_bit(0, &fimd_ctx->irq_flags))
788 fimd_enable_vblank(fimd_ctx, fimd_ctx->pipe);
790 fimd_apply(fimd_ctx);
791 fimd_commit(fimd_ctx);
793 if (fimd_ctx->panel_type == DP_LCD)
794 writel(MIE_CLK_ENABLE, fimd_ctx->regs + DPCLKCON);
796 fimd_window_resume(fimd_ctx);
799 * We need to make sure that all windows are disabled before we
800 * suspend that connector. Otherwise we might try to scan from
801 * a destroyed buffer later.
803 fimd_window_suspend(fimd_ctx);
805 if (fimd_ctx->panel_type == DP_LCD)
806 writel(0, fimd_ctx->regs + DPCLKCON);
808 clk_disable(fimd_ctx->lcd_clk);
809 clk_disable(fimd_ctx->bus_clk);
811 fimd_ctx->suspended = true;
817 #ifdef CONFIG_EXYNOS_IOMMU
818 static int iommu_init(struct platform_device *pdev)
820 struct platform_device *pds;
822 pds = find_sysmmu_dt(pdev, "sysmmu");
824 printk(KERN_ERR "No sysmmu found\n");
828 platform_set_sysmmu(&pds->dev, &pdev->dev);
830 * Due to the ordering in Makefile, this should be called first
831 * (before exynos_drm_drv.c and exynos_mixer.c and actually create
832 * the common mapping instead of reusing it. Ensure this assumption
835 WARN_ON(exynos_drm_common_mapping);
836 exynos_drm_common_mapping = s5p_create_iommu_mapping(&pdev->dev,
837 0x20000000, SZ_256M, 4,
838 exynos_drm_common_mapping);
840 if (!exynos_drm_common_mapping) {
841 printk(KERN_ERR "IOMMU mapping not created\n");
848 static void iommu_deinit(struct platform_device *pdev)
850 s5p_destroy_iommu_mapping(&pdev->dev);
851 DRM_DEBUG("released the IOMMU mapping\n");
855 static int __devinit fimd_probe(struct platform_device *pdev)
857 struct device *dev = &pdev->dev;
858 struct fimd_context *fimd_ctx;
859 struct exynos_drm_fimd_pdata *pdata;
860 struct resource *res;
861 struct clk *clk_parent;
865 #ifdef CONFIG_EXYNOS_IOMMU
866 ret = iommu_init(pdev);
868 dev_err(dev, "failed to initialize IOMMU\n");
872 DRM_DEBUG_KMS("%s\n", __FILE__);
874 pdata = pdev->dev.platform_data;
876 dev_err(dev, "no platform data specified\n");
880 fimd_ctx = kzalloc(sizeof(*fimd_ctx), GFP_KERNEL);
884 fimd_ctx->panel_type = pdata->panel_type;
887 fimd_ctx->bus_clk = clk_get(dev, "fimd");
888 if (IS_ERR(fimd_ctx->bus_clk)) {
889 dev_err(dev, "failed to get bus clock\n");
890 ret = PTR_ERR(fimd_ctx->bus_clk);
894 fimd_ctx->lcd_clk = clk_get(dev, "sclk_fimd");
895 if (IS_ERR(fimd_ctx->lcd_clk)) {
896 dev_err(dev, "failed to get lcd clock\n");
897 ret = PTR_ERR(fimd_ctx->lcd_clk);
901 clk_parent = clk_get(NULL, "sclk_vpll");
902 if (IS_ERR(clk_parent)) {
903 ret = PTR_ERR(clk_parent);
907 if (clk_set_parent(fimd_ctx->lcd_clk, clk_parent)) {
908 ret = PTR_ERR(fimd_ctx->lcd_clk);
912 if (clk_set_rate(fimd_ctx->lcd_clk, pdata->clock_rate)) {
913 ret = PTR_ERR(fimd_ctx->lcd_clk);
919 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
921 dev_err(dev, "failed to find registers\n");
926 fimd_ctx->regs_res = request_mem_region(res->start, resource_size(res),
928 if (!fimd_ctx->regs_res) {
929 dev_err(dev, "failed to claim register region\n");
934 fimd_ctx->regs = ioremap(res->start, resource_size(res));
935 if (!fimd_ctx->regs) {
936 dev_err(dev, "failed to map registers\n");
938 goto err_req_region_io;
941 fimd_ctx->regs_mie = ioremap(MIE_BASE_ADDRESS, 0x400);
942 if (!fimd_ctx->regs_mie) {
943 dev_err(dev, "failed to map registers\n");
945 goto err_req_region_io_mie;
948 res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
950 dev_err(dev, "irq request failed.\n");
951 goto err_req_region_irq;
954 fimd_ctx->irq = res->start;
956 ret = request_irq(fimd_ctx->irq, fimd_irq_handler, 0, "drm_fimd",
959 dev_err(dev, "irq request failed.\n");
963 fimd_ctx->vidcon0 = pdata->vidcon0;
964 fimd_ctx->vidcon1 = pdata->vidcon1;
965 fimd_ctx->default_win = pdata->default_win;
966 fimd_ctx->panel = &pdata->panel;
968 mutex_init(&fimd_ctx->lock);
970 platform_set_drvdata(pdev, fimd_ctx);
972 fimd_power(fimd_ctx, DRM_MODE_DPMS_ON);
974 for (win = 0; win < WINDOWS_NR; win++)
975 fimd_clear_win(fimd_ctx, win);
977 if (fimd_ctx->panel_type == DP_LCD)
978 writel(MIE_CLK_ENABLE, fimd_ctx->regs + DPCLKCON);
980 exynos_display_attach_controller(EXYNOS_DRM_DISPLAY_TYPE_FIMD,
981 &fimd_controller_ops, fimd_ctx);
987 iounmap(fimd_ctx->regs_mie);
989 err_req_region_io_mie:
990 iounmap(fimd_ctx->regs);
993 release_resource(fimd_ctx->regs_res);
994 kfree(fimd_ctx->regs_res);
997 clk_disable(fimd_ctx->lcd_clk);
998 clk_put(fimd_ctx->lcd_clk);
1001 clk_disable(fimd_ctx->bus_clk);
1002 clk_put(fimd_ctx->bus_clk);
1005 #ifdef CONFIG_EXYNOS_IOMMU
1012 static int __devexit fimd_remove(struct platform_device *pdev)
1014 struct fimd_context *ctx = platform_get_drvdata(pdev);
1016 DRM_DEBUG_KMS("%s\n", __FILE__);
1021 clk_disable(ctx->lcd_clk);
1022 clk_disable(ctx->bus_clk);
1024 fimd_power(ctx, DRM_MODE_DPMS_OFF);
1027 clk_put(ctx->lcd_clk);
1028 clk_put(ctx->bus_clk);
1030 iounmap(ctx->regs_mie);
1032 release_resource(ctx->regs_res);
1033 kfree(ctx->regs_res);
1034 free_irq(ctx->irq, ctx);
1035 #ifdef CONFIG_EXYNOS_IOMMU
1043 static struct platform_device_id exynos_drm_driver_ids[] = {
1045 .name = "exynos4-fb",
1047 .name = "exynos5-fb",
1051 MODULE_DEVICE_TABLE(platform, exynos_drm_driver_ids);
1053 struct platform_driver fimd_driver = {
1054 .probe = fimd_probe,
1055 .remove = __devexit_p(fimd_remove),
1056 .id_table = exynos_drm_driver_ids,
1058 .name = "exynos-drm-fimd",
1059 .owner = THIS_MODULE,