]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/exynos/exynos_drm_fimd.c
gpu: ipu-v3: Kconfig: Remove SOC_IMX6SL from IMX_IPUV3_CORE Kconfig
[karo-tx-linux.git] / drivers / gpu / drm / exynos / exynos_drm_fimd.c
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 <drm/drmP.h>
15
16 #include <linux/kernel.h>
17 #include <linux/platform_device.h>
18 #include <linux/clk.h>
19 #include <linux/of.h>
20 #include <linux/of_device.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/component.h>
23 #include <linux/mfd/syscon.h>
24 #include <linux/regmap.h>
25
26 #include <video/of_display_timing.h>
27 #include <video/of_videomode.h>
28 #include <video/samsung_fimd.h>
29 #include <drm/exynos_drm.h>
30
31 #include "exynos_drm_drv.h"
32 #include "exynos_drm_fbdev.h"
33 #include "exynos_drm_crtc.h"
34 #include "exynos_drm_iommu.h"
35
36 /*
37  * FIMD stands for Fully Interactive Mobile Display and
38  * as a display controller, it transfers contents drawn on memory
39  * to a LCD Panel through Display Interfaces such as RGB or
40  * CPU Interface.
41  */
42
43 #define FIMD_DEFAULT_FRAMERATE 60
44 #define MIN_FB_WIDTH_FOR_16WORD_BURST 128
45
46 /* position control register for hardware window 0, 2 ~ 4.*/
47 #define VIDOSD_A(win)           (VIDOSD_BASE + 0x00 + (win) * 16)
48 #define VIDOSD_B(win)           (VIDOSD_BASE + 0x04 + (win) * 16)
49 /*
50  * size control register for hardware windows 0 and alpha control register
51  * for hardware windows 1 ~ 4
52  */
53 #define VIDOSD_C(win)           (VIDOSD_BASE + 0x08 + (win) * 16)
54 /* size control register for hardware windows 1 ~ 2. */
55 #define VIDOSD_D(win)           (VIDOSD_BASE + 0x0C + (win) * 16)
56
57 #define VIDWx_BUF_START(win, buf)       (VIDW_BUF_START(buf) + (win) * 8)
58 #define VIDWx_BUF_END(win, buf)         (VIDW_BUF_END(buf) + (win) * 8)
59 #define VIDWx_BUF_SIZE(win, buf)        (VIDW_BUF_SIZE(buf) + (win) * 4)
60
61 /* color key control register for hardware window 1 ~ 4. */
62 #define WKEYCON0_BASE(x)                ((WKEYCON0 + 0x140) + ((x - 1) * 8))
63 /* color key value register for hardware window 1 ~ 4. */
64 #define WKEYCON1_BASE(x)                ((WKEYCON1 + 0x140) + ((x - 1) * 8))
65
66 /* I80 / RGB trigger control register */
67 #define TRIGCON                         0x1A4
68 #define TRGMODE_I80_RGB_ENABLE_I80      (1 << 0)
69 #define SWTRGCMD_I80_RGB_ENABLE         (1 << 1)
70
71 /* display mode change control register except exynos4 */
72 #define VIDOUT_CON                      0x000
73 #define VIDOUT_CON_F_I80_LDI0           (0x2 << 8)
74
75 /* I80 interface control for main LDI register */
76 #define I80IFCONFAx(x)                  (0x1B0 + (x) * 4)
77 #define I80IFCONFBx(x)                  (0x1B8 + (x) * 4)
78 #define LCD_CS_SETUP(x)                 ((x) << 16)
79 #define LCD_WR_SETUP(x)                 ((x) << 12)
80 #define LCD_WR_ACTIVE(x)                ((x) << 8)
81 #define LCD_WR_HOLD(x)                  ((x) << 4)
82 #define I80IFEN_ENABLE                  (1 << 0)
83
84 /* FIMD has totally five hardware windows. */
85 #define WINDOWS_NR      5
86
87 #define get_fimd_manager(mgr)   platform_get_drvdata(to_platform_device(dev))
88
89 struct fimd_driver_data {
90         unsigned int timing_base;
91         unsigned int lcdblk_offset;
92         unsigned int lcdblk_vt_shift;
93         unsigned int lcdblk_bypass_shift;
94
95         unsigned int has_shadowcon:1;
96         unsigned int has_clksel:1;
97         unsigned int has_limited_fmt:1;
98         unsigned int has_vidoutcon:1;
99 };
100
101 static struct fimd_driver_data s3c64xx_fimd_driver_data = {
102         .timing_base = 0x0,
103         .has_clksel = 1,
104         .has_limited_fmt = 1,
105 };
106
107 static struct fimd_driver_data exynos4_fimd_driver_data = {
108         .timing_base = 0x0,
109         .lcdblk_offset = 0x210,
110         .lcdblk_vt_shift = 10,
111         .lcdblk_bypass_shift = 1,
112         .has_shadowcon = 1,
113 };
114
115 static struct fimd_driver_data exynos5_fimd_driver_data = {
116         .timing_base = 0x20000,
117         .lcdblk_offset = 0x214,
118         .lcdblk_vt_shift = 24,
119         .lcdblk_bypass_shift = 15,
120         .has_shadowcon = 1,
121         .has_vidoutcon = 1,
122 };
123
124 struct fimd_win_data {
125         unsigned int            offset_x;
126         unsigned int            offset_y;
127         unsigned int            ovl_width;
128         unsigned int            ovl_height;
129         unsigned int            fb_width;
130         unsigned int            fb_height;
131         unsigned int            bpp;
132         unsigned int            pixel_format;
133         dma_addr_t              dma_addr;
134         unsigned int            buf_offsize;
135         unsigned int            line_size;      /* bytes */
136         bool                    enabled;
137         bool                    resume;
138 };
139
140 struct fimd_context {
141         struct device                   *dev;
142         struct drm_device               *drm_dev;
143         struct clk                      *bus_clk;
144         struct clk                      *lcd_clk;
145         void __iomem                    *regs;
146         struct regmap                   *sysreg;
147         struct drm_display_mode         mode;
148         struct fimd_win_data            win_data[WINDOWS_NR];
149         unsigned int                    default_win;
150         unsigned long                   irq_flags;
151         u32                             vidcon0;
152         u32                             vidcon1;
153         u32                             vidout_con;
154         u32                             i80ifcon;
155         bool                            i80_if;
156         bool                            suspended;
157         int                             pipe;
158         wait_queue_head_t               wait_vsync_queue;
159         atomic_t                        wait_vsync_event;
160         atomic_t                        win_updated;
161         atomic_t                        triggering;
162
163         struct exynos_drm_panel_info panel;
164         struct fimd_driver_data *driver_data;
165         struct exynos_drm_display *display;
166 };
167
168 static const struct of_device_id fimd_driver_dt_match[] = {
169         { .compatible = "samsung,s3c6400-fimd",
170           .data = &s3c64xx_fimd_driver_data },
171         { .compatible = "samsung,exynos4210-fimd",
172           .data = &exynos4_fimd_driver_data },
173         { .compatible = "samsung,exynos5250-fimd",
174           .data = &exynos5_fimd_driver_data },
175         {},
176 };
177 MODULE_DEVICE_TABLE(of, fimd_driver_dt_match);
178
179 static inline struct fimd_driver_data *drm_fimd_get_driver_data(
180         struct platform_device *pdev)
181 {
182         const struct of_device_id *of_id =
183                         of_match_device(fimd_driver_dt_match, &pdev->dev);
184
185         return (struct fimd_driver_data *)of_id->data;
186 }
187
188 static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
189 {
190         struct fimd_context *ctx = mgr->ctx;
191
192         if (ctx->suspended)
193                 return;
194
195         atomic_set(&ctx->wait_vsync_event, 1);
196
197         /*
198          * wait for FIMD to signal VSYNC interrupt or return after
199          * timeout which is set to 50ms (refresh rate of 20).
200          */
201         if (!wait_event_timeout(ctx->wait_vsync_queue,
202                                 !atomic_read(&ctx->wait_vsync_event),
203                                 HZ/20))
204                 DRM_DEBUG_KMS("vblank wait timed out.\n");
205 }
206
207
208 static void fimd_clear_channel(struct exynos_drm_manager *mgr)
209 {
210         struct fimd_context *ctx = mgr->ctx;
211         int win, ch_enabled = 0;
212
213         DRM_DEBUG_KMS("%s\n", __FILE__);
214
215         /* Check if any channel is enabled. */
216         for (win = 0; win < WINDOWS_NR; win++) {
217                 u32 val = readl(ctx->regs + SHADOWCON);
218                 if (val & SHADOWCON_CHx_ENABLE(win)) {
219                         val &= ~SHADOWCON_CHx_ENABLE(win);
220                         writel(val, ctx->regs + SHADOWCON);
221                         ch_enabled = 1;
222                 }
223         }
224
225         /* Wait for vsync, as disable channel takes effect at next vsync */
226         if (ch_enabled)
227                 fimd_wait_for_vblank(mgr);
228 }
229
230 static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
231                         struct drm_device *drm_dev)
232 {
233         struct fimd_context *ctx = mgr->ctx;
234         struct exynos_drm_private *priv;
235         priv = drm_dev->dev_private;
236
237         mgr->drm_dev = ctx->drm_dev = drm_dev;
238         mgr->pipe = ctx->pipe = priv->pipe++;
239
240         /*
241          * enable drm irq mode.
242          * - with irq_enabled = true, we can use the vblank feature.
243          *
244          * P.S. note that we wouldn't use drm irq handler but
245          *      just specific driver own one instead because
246          *      drm framework supports only one irq handler.
247          */
248         drm_dev->irq_enabled = true;
249
250         /*
251          * with vblank_disable_allowed = true, vblank interrupt will be disabled
252          * by drm timer once a current process gives up ownership of
253          * vblank event.(after drm_vblank_put function is called)
254          */
255         drm_dev->vblank_disable_allowed = true;
256
257         /* attach this sub driver to iommu mapping if supported. */
258         if (is_drm_iommu_supported(ctx->drm_dev)) {
259                 /*
260                  * If any channel is already active, iommu will throw
261                  * a PAGE FAULT when enabled. So clear any channel if enabled.
262                  */
263                 fimd_clear_channel(mgr);
264                 drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
265         }
266
267         return 0;
268 }
269
270 static void fimd_mgr_remove(struct exynos_drm_manager *mgr)
271 {
272         struct fimd_context *ctx = mgr->ctx;
273
274         /* detach this sub driver from iommu mapping if supported. */
275         if (is_drm_iommu_supported(ctx->drm_dev))
276                 drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
277 }
278
279 static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
280                 const struct drm_display_mode *mode)
281 {
282         unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
283         u32 clkdiv;
284
285         if (ctx->i80_if) {
286                 /*
287                  * The frame done interrupt should be occurred prior to the
288                  * next TE signal.
289                  */
290                 ideal_clk *= 2;
291         }
292
293         /* Find the clock divider value that gets us closest to ideal_clk */
294         clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->lcd_clk), ideal_clk);
295
296         return (clkdiv < 0x100) ? clkdiv : 0xff;
297 }
298
299 static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
300                 const struct drm_display_mode *mode,
301                 struct drm_display_mode *adjusted_mode)
302 {
303         if (adjusted_mode->vrefresh == 0)
304                 adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
305
306         return true;
307 }
308
309 static void fimd_mode_set(struct exynos_drm_manager *mgr,
310                 const struct drm_display_mode *in_mode)
311 {
312         struct fimd_context *ctx = mgr->ctx;
313
314         drm_mode_copy(&ctx->mode, in_mode);
315 }
316
317 static void fimd_commit(struct exynos_drm_manager *mgr)
318 {
319         struct fimd_context *ctx = mgr->ctx;
320         struct drm_display_mode *mode = &ctx->mode;
321         struct fimd_driver_data *driver_data = ctx->driver_data;
322         void *timing_base = ctx->regs + driver_data->timing_base;
323         u32 val, clkdiv;
324
325         if (ctx->suspended)
326                 return;
327
328         /* nothing to do if we haven't set the mode yet */
329         if (mode->htotal == 0 || mode->vtotal == 0)
330                 return;
331
332         if (ctx->i80_if) {
333                 val = ctx->i80ifcon | I80IFEN_ENABLE;
334                 writel(val, timing_base + I80IFCONFAx(0));
335
336                 /* disable auto frame rate */
337                 writel(0, timing_base + I80IFCONFBx(0));
338
339                 /* set video type selection to I80 interface */
340                 if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
341                                         driver_data->lcdblk_offset,
342                                         0x3 << driver_data->lcdblk_vt_shift,
343                                         0x1 << driver_data->lcdblk_vt_shift)) {
344                         DRM_ERROR("Failed to update sysreg for I80 i/f.\n");
345                         return;
346                 }
347         } else {
348                 int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
349                 u32 vidcon1;
350
351                 /* setup polarity values */
352                 vidcon1 = ctx->vidcon1;
353                 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
354                         vidcon1 |= VIDCON1_INV_VSYNC;
355                 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
356                         vidcon1 |= VIDCON1_INV_HSYNC;
357                 writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
358
359                 /* setup vertical timing values. */
360                 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
361                 vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
362                 vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
363
364                 val = VIDTCON0_VBPD(vbpd - 1) |
365                         VIDTCON0_VFPD(vfpd - 1) |
366                         VIDTCON0_VSPW(vsync_len - 1);
367                 writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
368
369                 /* setup horizontal timing values.  */
370                 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
371                 hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
372                 hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
373
374                 val = VIDTCON1_HBPD(hbpd - 1) |
375                         VIDTCON1_HFPD(hfpd - 1) |
376                         VIDTCON1_HSPW(hsync_len - 1);
377                 writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
378         }
379
380         if (driver_data->has_vidoutcon)
381                 writel(ctx->vidout_con, timing_base + VIDOUT_CON);
382
383         /* set bypass selection */
384         if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
385                                 driver_data->lcdblk_offset,
386                                 0x1 << driver_data->lcdblk_bypass_shift,
387                                 0x1 << driver_data->lcdblk_bypass_shift)) {
388                 DRM_ERROR("Failed to update sysreg for bypass setting.\n");
389                 return;
390         }
391
392         /* setup horizontal and vertical display size. */
393         val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
394                VIDTCON2_HOZVAL(mode->hdisplay - 1) |
395                VIDTCON2_LINEVAL_E(mode->vdisplay - 1) |
396                VIDTCON2_HOZVAL_E(mode->hdisplay - 1);
397         writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
398
399         /*
400          * fields of register with prefix '_F' would be updated
401          * at vsync(same as dma start)
402          */
403         val = ctx->vidcon0;
404         val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
405
406         if (ctx->driver_data->has_clksel)
407                 val |= VIDCON0_CLKSEL_LCD;
408
409         clkdiv = fimd_calc_clkdiv(ctx, mode);
410         if (clkdiv > 1)
411                 val |= VIDCON0_CLKVAL_F(clkdiv - 1) | VIDCON0_CLKDIR;
412
413         writel(val, ctx->regs + VIDCON0);
414 }
415
416 static int fimd_enable_vblank(struct exynos_drm_manager *mgr)
417 {
418         struct fimd_context *ctx = mgr->ctx;
419         u32 val;
420
421         if (ctx->suspended)
422                 return -EPERM;
423
424         if (!test_and_set_bit(0, &ctx->irq_flags)) {
425                 val = readl(ctx->regs + VIDINTCON0);
426
427                 val |= VIDINTCON0_INT_ENABLE;
428                 val |= VIDINTCON0_INT_FRAME;
429
430                 val &= ~VIDINTCON0_FRAMESEL0_MASK;
431                 val |= VIDINTCON0_FRAMESEL0_VSYNC;
432                 val &= ~VIDINTCON0_FRAMESEL1_MASK;
433                 val |= VIDINTCON0_FRAMESEL1_NONE;
434
435                 writel(val, ctx->regs + VIDINTCON0);
436         }
437
438         return 0;
439 }
440
441 static void fimd_disable_vblank(struct exynos_drm_manager *mgr)
442 {
443         struct fimd_context *ctx = mgr->ctx;
444         u32 val;
445
446         if (ctx->suspended)
447                 return;
448
449         if (test_and_clear_bit(0, &ctx->irq_flags)) {
450                 val = readl(ctx->regs + VIDINTCON0);
451
452                 val &= ~VIDINTCON0_INT_FRAME;
453                 val &= ~VIDINTCON0_INT_ENABLE;
454
455                 writel(val, ctx->regs + VIDINTCON0);
456         }
457 }
458
459 static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
460                         struct exynos_drm_overlay *overlay)
461 {
462         struct fimd_context *ctx = mgr->ctx;
463         struct fimd_win_data *win_data;
464         int win;
465         unsigned long offset;
466
467         if (!overlay) {
468                 DRM_ERROR("overlay is NULL\n");
469                 return;
470         }
471
472         win = overlay->zpos;
473         if (win == DEFAULT_ZPOS)
474                 win = ctx->default_win;
475
476         if (win < 0 || win >= WINDOWS_NR)
477                 return;
478
479         offset = overlay->fb_x * (overlay->bpp >> 3);
480         offset += overlay->fb_y * overlay->pitch;
481
482         DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
483
484         win_data = &ctx->win_data[win];
485
486         win_data->offset_x = overlay->crtc_x;
487         win_data->offset_y = overlay->crtc_y;
488         win_data->ovl_width = overlay->crtc_width;
489         win_data->ovl_height = overlay->crtc_height;
490         win_data->fb_width = overlay->fb_width;
491         win_data->fb_height = overlay->fb_height;
492         win_data->dma_addr = overlay->dma_addr[0] + offset;
493         win_data->bpp = overlay->bpp;
494         win_data->pixel_format = overlay->pixel_format;
495         win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
496                                 (overlay->bpp >> 3);
497         win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
498
499         DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
500                         win_data->offset_x, win_data->offset_y);
501         DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
502                         win_data->ovl_width, win_data->ovl_height);
503         DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
504         DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
505                         overlay->fb_width, overlay->crtc_width);
506 }
507
508 static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
509 {
510         struct fimd_win_data *win_data = &ctx->win_data[win];
511         unsigned long val;
512
513         val = WINCONx_ENWIN;
514
515         /*
516          * In case of s3c64xx, window 0 doesn't support alpha channel.
517          * So the request format is ARGB8888 then change it to XRGB8888.
518          */
519         if (ctx->driver_data->has_limited_fmt && !win) {
520                 if (win_data->pixel_format == DRM_FORMAT_ARGB8888)
521                         win_data->pixel_format = DRM_FORMAT_XRGB8888;
522         }
523
524         switch (win_data->pixel_format) {
525         case DRM_FORMAT_C8:
526                 val |= WINCON0_BPPMODE_8BPP_PALETTE;
527                 val |= WINCONx_BURSTLEN_8WORD;
528                 val |= WINCONx_BYTSWP;
529                 break;
530         case DRM_FORMAT_XRGB1555:
531                 val |= WINCON0_BPPMODE_16BPP_1555;
532                 val |= WINCONx_HAWSWP;
533                 val |= WINCONx_BURSTLEN_16WORD;
534                 break;
535         case DRM_FORMAT_RGB565:
536                 val |= WINCON0_BPPMODE_16BPP_565;
537                 val |= WINCONx_HAWSWP;
538                 val |= WINCONx_BURSTLEN_16WORD;
539                 break;
540         case DRM_FORMAT_XRGB8888:
541                 val |= WINCON0_BPPMODE_24BPP_888;
542                 val |= WINCONx_WSWP;
543                 val |= WINCONx_BURSTLEN_16WORD;
544                 break;
545         case DRM_FORMAT_ARGB8888:
546                 val |= WINCON1_BPPMODE_25BPP_A1888
547                         | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
548                 val |= WINCONx_WSWP;
549                 val |= WINCONx_BURSTLEN_16WORD;
550                 break;
551         default:
552                 DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
553
554                 val |= WINCON0_BPPMODE_24BPP_888;
555                 val |= WINCONx_WSWP;
556                 val |= WINCONx_BURSTLEN_16WORD;
557                 break;
558         }
559
560         DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
561
562         /*
563          * In case of exynos, setting dma-burst to 16Word causes permanent
564          * tearing for very small buffers, e.g. cursor buffer. Burst Mode
565          * switching which is based on overlay size is not recommended as
566          * overlay size varies alot towards the end of the screen and rapid
567          * movement causes unstable DMA which results into iommu crash/tear.
568          */
569
570         if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
571                 val &= ~WINCONx_BURSTLEN_MASK;
572                 val |= WINCONx_BURSTLEN_4WORD;
573         }
574
575         writel(val, ctx->regs + WINCON(win));
576 }
577
578 static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win)
579 {
580         unsigned int keycon0 = 0, keycon1 = 0;
581
582         keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
583                         WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
584
585         keycon1 = WxKEYCON1_COLVAL(0xffffffff);
586
587         writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
588         writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
589 }
590
591 /**
592  * shadow_protect_win() - disable updating values from shadow registers at vsync
593  *
594  * @win: window to protect registers for
595  * @protect: 1 to protect (disable updates)
596  */
597 static void fimd_shadow_protect_win(struct fimd_context *ctx,
598                                                         int win, bool protect)
599 {
600         u32 reg, bits, val;
601
602         if (ctx->driver_data->has_shadowcon) {
603                 reg = SHADOWCON;
604                 bits = SHADOWCON_WINx_PROTECT(win);
605         } else {
606                 reg = PRTCON;
607                 bits = PRTCON_PROTECT;
608         }
609
610         val = readl(ctx->regs + reg);
611         if (protect)
612                 val |= bits;
613         else
614                 val &= ~bits;
615         writel(val, ctx->regs + reg);
616 }
617
618 static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
619 {
620         struct fimd_context *ctx = mgr->ctx;
621         struct fimd_win_data *win_data;
622         int win = zpos;
623         unsigned long val, alpha, size;
624         unsigned int last_x;
625         unsigned int last_y;
626
627         if (ctx->suspended)
628                 return;
629
630         if (win == DEFAULT_ZPOS)
631                 win = ctx->default_win;
632
633         if (win < 0 || win >= WINDOWS_NR)
634                 return;
635
636         win_data = &ctx->win_data[win];
637
638         /* If suspended, enable this on resume */
639         if (ctx->suspended) {
640                 win_data->resume = true;
641                 return;
642         }
643
644         /*
645          * SHADOWCON/PRTCON register is used for enabling timing.
646          *
647          * for example, once only width value of a register is set,
648          * if the dma is started then fimd hardware could malfunction so
649          * with protect window setting, the register fields with prefix '_F'
650          * wouldn't be updated at vsync also but updated once unprotect window
651          * is set.
652          */
653
654         /* protect windows */
655         fimd_shadow_protect_win(ctx, win, true);
656
657         /* buffer start address */
658         val = (unsigned long)win_data->dma_addr;
659         writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
660
661         /* buffer end address */
662         size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
663         val = (unsigned long)(win_data->dma_addr + size);
664         writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
665
666         DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
667                         (unsigned long)win_data->dma_addr, val, size);
668         DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
669                         win_data->ovl_width, win_data->ovl_height);
670
671         /* buffer size */
672         val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
673                 VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) |
674                 VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) |
675                 VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size);
676         writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
677
678         /* OSD position */
679         val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
680                 VIDOSDxA_TOPLEFT_Y(win_data->offset_y) |
681                 VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) |
682                 VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y);
683         writel(val, ctx->regs + VIDOSD_A(win));
684
685         last_x = win_data->offset_x + win_data->ovl_width;
686         if (last_x)
687                 last_x--;
688         last_y = win_data->offset_y + win_data->ovl_height;
689         if (last_y)
690                 last_y--;
691
692         val = VIDOSDxB_BOTRIGHT_X(last_x) | VIDOSDxB_BOTRIGHT_Y(last_y) |
693                 VIDOSDxB_BOTRIGHT_X_E(last_x) | VIDOSDxB_BOTRIGHT_Y_E(last_y);
694
695         writel(val, ctx->regs + VIDOSD_B(win));
696
697         DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
698                         win_data->offset_x, win_data->offset_y, last_x, last_y);
699
700         /* hardware window 0 doesn't support alpha channel. */
701         if (win != 0) {
702                 /* OSD alpha */
703                 alpha = VIDISD14C_ALPHA1_R(0xf) |
704                         VIDISD14C_ALPHA1_G(0xf) |
705                         VIDISD14C_ALPHA1_B(0xf);
706
707                 writel(alpha, ctx->regs + VIDOSD_C(win));
708         }
709
710         /* OSD size */
711         if (win != 3 && win != 4) {
712                 u32 offset = VIDOSD_D(win);
713                 if (win == 0)
714                         offset = VIDOSD_C(win);
715                 val = win_data->ovl_width * win_data->ovl_height;
716                 writel(val, ctx->regs + offset);
717
718                 DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
719         }
720
721         fimd_win_set_pixfmt(ctx, win);
722
723         /* hardware window 0 doesn't support color key. */
724         if (win != 0)
725                 fimd_win_set_colkey(ctx, win);
726
727         /* wincon */
728         val = readl(ctx->regs + WINCON(win));
729         val |= WINCONx_ENWIN;
730         writel(val, ctx->regs + WINCON(win));
731
732         /* Enable DMA channel and unprotect windows */
733         fimd_shadow_protect_win(ctx, win, false);
734
735         if (ctx->driver_data->has_shadowcon) {
736                 val = readl(ctx->regs + SHADOWCON);
737                 val |= SHADOWCON_CHx_ENABLE(win);
738                 writel(val, ctx->regs + SHADOWCON);
739         }
740
741         win_data->enabled = true;
742
743         if (ctx->i80_if)
744                 atomic_set(&ctx->win_updated, 1);
745 }
746
747 static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
748 {
749         struct fimd_context *ctx = mgr->ctx;
750         struct fimd_win_data *win_data;
751         int win = zpos;
752         u32 val;
753
754         if (win == DEFAULT_ZPOS)
755                 win = ctx->default_win;
756
757         if (win < 0 || win >= WINDOWS_NR)
758                 return;
759
760         win_data = &ctx->win_data[win];
761
762         if (ctx->suspended) {
763                 /* do not resume this window*/
764                 win_data->resume = false;
765                 return;
766         }
767
768         /* protect windows */
769         fimd_shadow_protect_win(ctx, win, true);
770
771         /* wincon */
772         val = readl(ctx->regs + WINCON(win));
773         val &= ~WINCONx_ENWIN;
774         writel(val, ctx->regs + WINCON(win));
775
776         /* unprotect windows */
777         if (ctx->driver_data->has_shadowcon) {
778                 val = readl(ctx->regs + SHADOWCON);
779                 val &= ~SHADOWCON_CHx_ENABLE(win);
780                 writel(val, ctx->regs + SHADOWCON);
781         }
782
783         fimd_shadow_protect_win(ctx, win, false);
784
785         win_data->enabled = false;
786 }
787
788 static void fimd_window_suspend(struct exynos_drm_manager *mgr)
789 {
790         struct fimd_context *ctx = mgr->ctx;
791         struct fimd_win_data *win_data;
792         int i;
793
794         for (i = 0; i < WINDOWS_NR; i++) {
795                 win_data = &ctx->win_data[i];
796                 win_data->resume = win_data->enabled;
797                 if (win_data->enabled)
798                         fimd_win_disable(mgr, i);
799         }
800         fimd_wait_for_vblank(mgr);
801 }
802
803 static void fimd_window_resume(struct exynos_drm_manager *mgr)
804 {
805         struct fimd_context *ctx = mgr->ctx;
806         struct fimd_win_data *win_data;
807         int i;
808
809         for (i = 0; i < WINDOWS_NR; i++) {
810                 win_data = &ctx->win_data[i];
811                 win_data->enabled = win_data->resume;
812                 win_data->resume = false;
813         }
814 }
815
816 static void fimd_apply(struct exynos_drm_manager *mgr)
817 {
818         struct fimd_context *ctx = mgr->ctx;
819         struct fimd_win_data *win_data;
820         int i;
821
822         for (i = 0; i < WINDOWS_NR; i++) {
823                 win_data = &ctx->win_data[i];
824                 if (win_data->enabled)
825                         fimd_win_commit(mgr, i);
826                 else
827                         fimd_win_disable(mgr, i);
828         }
829
830         fimd_commit(mgr);
831 }
832
833 static int fimd_poweron(struct exynos_drm_manager *mgr)
834 {
835         struct fimd_context *ctx = mgr->ctx;
836         int ret;
837
838         if (!ctx->suspended)
839                 return 0;
840
841         ctx->suspended = false;
842
843         pm_runtime_get_sync(ctx->dev);
844
845         ret = clk_prepare_enable(ctx->bus_clk);
846         if (ret < 0) {
847                 DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
848                 goto bus_clk_err;
849         }
850
851         ret = clk_prepare_enable(ctx->lcd_clk);
852         if  (ret < 0) {
853                 DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
854                 goto lcd_clk_err;
855         }
856
857         /* if vblank was enabled status, enable it again. */
858         if (test_and_clear_bit(0, &ctx->irq_flags)) {
859                 ret = fimd_enable_vblank(mgr);
860                 if (ret) {
861                         DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
862                         goto enable_vblank_err;
863                 }
864         }
865
866         fimd_window_resume(mgr);
867
868         fimd_apply(mgr);
869
870         return 0;
871
872 enable_vblank_err:
873         clk_disable_unprepare(ctx->lcd_clk);
874 lcd_clk_err:
875         clk_disable_unprepare(ctx->bus_clk);
876 bus_clk_err:
877         ctx->suspended = true;
878         return ret;
879 }
880
881 static int fimd_poweroff(struct exynos_drm_manager *mgr)
882 {
883         struct fimd_context *ctx = mgr->ctx;
884
885         if (ctx->suspended)
886                 return 0;
887
888         /*
889          * We need to make sure that all windows are disabled before we
890          * suspend that connector. Otherwise we might try to scan from
891          * a destroyed buffer later.
892          */
893         fimd_window_suspend(mgr);
894
895         clk_disable_unprepare(ctx->lcd_clk);
896         clk_disable_unprepare(ctx->bus_clk);
897
898         pm_runtime_put_sync(ctx->dev);
899
900         ctx->suspended = true;
901         return 0;
902 }
903
904 static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
905 {
906         DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
907
908         switch (mode) {
909         case DRM_MODE_DPMS_ON:
910                 fimd_poweron(mgr);
911                 break;
912         case DRM_MODE_DPMS_STANDBY:
913         case DRM_MODE_DPMS_SUSPEND:
914         case DRM_MODE_DPMS_OFF:
915                 fimd_poweroff(mgr);
916                 break;
917         default:
918                 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
919                 break;
920         }
921 }
922
923 static void fimd_trigger(struct device *dev)
924 {
925         struct exynos_drm_manager *mgr = get_fimd_manager(dev);
926         struct fimd_context *ctx = mgr->ctx;
927         struct fimd_driver_data *driver_data = ctx->driver_data;
928         void *timing_base = ctx->regs + driver_data->timing_base;
929         u32 reg;
930
931         atomic_set(&ctx->triggering, 1);
932
933         reg = readl(ctx->regs + VIDINTCON0);
934         reg |= (VIDINTCON0_INT_ENABLE | VIDINTCON0_INT_I80IFDONE |
935                                                 VIDINTCON0_INT_SYSMAINCON);
936         writel(reg, ctx->regs + VIDINTCON0);
937
938         reg = readl(timing_base + TRIGCON);
939         reg |= (TRGMODE_I80_RGB_ENABLE_I80 | SWTRGCMD_I80_RGB_ENABLE);
940         writel(reg, timing_base + TRIGCON);
941 }
942
943 static void fimd_te_handler(struct exynos_drm_manager *mgr)
944 {
945         struct fimd_context *ctx = mgr->ctx;
946
947         /* Checks the crtc is detached already from encoder */
948         if (ctx->pipe < 0 || !ctx->drm_dev)
949                 return;
950
951          /*
952          * Skips to trigger if in triggering state, because multiple triggering
953          * requests can cause panel reset.
954          */
955         if (atomic_read(&ctx->triggering))
956                 return;
957
958         /*
959          * If there is a page flip request, triggers and handles the page flip
960          * event so that current fb can be updated into panel GRAM.
961          */
962         if (atomic_add_unless(&ctx->win_updated, -1, 0))
963                 fimd_trigger(ctx->dev);
964
965         /* Wakes up vsync event queue */
966         if (atomic_read(&ctx->wait_vsync_event)) {
967                 atomic_set(&ctx->wait_vsync_event, 0);
968                 wake_up(&ctx->wait_vsync_queue);
969
970                 if (!atomic_read(&ctx->triggering))
971                         drm_handle_vblank(ctx->drm_dev, ctx->pipe);
972         }
973 }
974
975 static struct exynos_drm_manager_ops fimd_manager_ops = {
976         .dpms = fimd_dpms,
977         .mode_fixup = fimd_mode_fixup,
978         .mode_set = fimd_mode_set,
979         .commit = fimd_commit,
980         .enable_vblank = fimd_enable_vblank,
981         .disable_vblank = fimd_disable_vblank,
982         .wait_for_vblank = fimd_wait_for_vblank,
983         .win_mode_set = fimd_win_mode_set,
984         .win_commit = fimd_win_commit,
985         .win_disable = fimd_win_disable,
986         .te_handler = fimd_te_handler,
987 };
988
989 static struct exynos_drm_manager fimd_manager = {
990         .type = EXYNOS_DISPLAY_TYPE_LCD,
991         .ops = &fimd_manager_ops,
992 };
993
994 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
995 {
996         struct fimd_context *ctx = (struct fimd_context *)dev_id;
997         u32 val, clear_bit;
998
999         val = readl(ctx->regs + VIDINTCON1);
1000
1001         clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME;
1002         if (val & clear_bit)
1003                 writel(clear_bit, ctx->regs + VIDINTCON1);
1004
1005         /* check the crtc is detached already from encoder */
1006         if (ctx->pipe < 0 || !ctx->drm_dev)
1007                 goto out;
1008
1009         if (ctx->i80_if) {
1010                 /* unset I80 frame done interrupt */
1011                 val = readl(ctx->regs + VIDINTCON0);
1012                 val &= ~(VIDINTCON0_INT_I80IFDONE | VIDINTCON0_INT_SYSMAINCON);
1013                 writel(val, ctx->regs + VIDINTCON0);
1014
1015                 /* exit triggering mode */
1016                 atomic_set(&ctx->triggering, 0);
1017
1018                 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
1019                 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
1020         } else {
1021                 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
1022                 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
1023
1024                 /* set wait vsync event to zero and wake up queue. */
1025                 if (atomic_read(&ctx->wait_vsync_event)) {
1026                         atomic_set(&ctx->wait_vsync_event, 0);
1027                         wake_up(&ctx->wait_vsync_queue);
1028                 }
1029         }
1030
1031 out:
1032         return IRQ_HANDLED;
1033 }
1034
1035 static int fimd_bind(struct device *dev, struct device *master, void *data)
1036 {
1037         struct fimd_context *ctx = fimd_manager.ctx;
1038         struct drm_device *drm_dev = data;
1039
1040         fimd_mgr_initialize(&fimd_manager, drm_dev);
1041         exynos_drm_crtc_create(&fimd_manager);
1042         if (ctx->display)
1043                 exynos_drm_create_enc_conn(drm_dev, ctx->display);
1044
1045         return 0;
1046
1047 }
1048
1049 static void fimd_unbind(struct device *dev, struct device *master,
1050                         void *data)
1051 {
1052         struct exynos_drm_manager *mgr = dev_get_drvdata(dev);
1053         struct fimd_context *ctx = fimd_manager.ctx;
1054         struct drm_crtc *crtc = mgr->crtc;
1055
1056         fimd_dpms(mgr, DRM_MODE_DPMS_OFF);
1057
1058         if (ctx->display)
1059                 exynos_dpi_remove(dev);
1060
1061         fimd_mgr_remove(mgr);
1062
1063         crtc->funcs->destroy(crtc);
1064 }
1065
1066 static const struct component_ops fimd_component_ops = {
1067         .bind   = fimd_bind,
1068         .unbind = fimd_unbind,
1069 };
1070
1071 static int fimd_probe(struct platform_device *pdev)
1072 {
1073         struct device *dev = &pdev->dev;
1074         struct fimd_context *ctx;
1075         struct device_node *i80_if_timings;
1076         struct resource *res;
1077         int ret = -EINVAL;
1078
1079         ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
1080                                         fimd_manager.type);
1081         if (ret)
1082                 return ret;
1083
1084         if (!dev->of_node) {
1085                 ret = -ENODEV;
1086                 goto err_del_component;
1087         }
1088
1089         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1090         if (!ctx) {
1091                 ret = -ENOMEM;
1092                 goto err_del_component;
1093         }
1094
1095         ctx->dev = dev;
1096         ctx->suspended = true;
1097         ctx->driver_data = drm_fimd_get_driver_data(pdev);
1098
1099         if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
1100                 ctx->vidcon1 |= VIDCON1_INV_VDEN;
1101         if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
1102                 ctx->vidcon1 |= VIDCON1_INV_VCLK;
1103
1104         i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
1105         if (i80_if_timings) {
1106                 u32 val;
1107
1108                 ctx->i80_if = true;
1109
1110                 if (ctx->driver_data->has_vidoutcon)
1111                         ctx->vidout_con |= VIDOUT_CON_F_I80_LDI0;
1112                 else
1113                         ctx->vidcon0 |= VIDCON0_VIDOUT_I80_LDI0;
1114                 /*
1115                  * The user manual describes that this "DSI_EN" bit is required
1116                  * to enable I80 24-bit data interface.
1117                  */
1118                 ctx->vidcon0 |= VIDCON0_DSI_EN;
1119
1120                 if (of_property_read_u32(i80_if_timings, "cs-setup", &val))
1121                         val = 0;
1122                 ctx->i80ifcon = LCD_CS_SETUP(val);
1123                 if (of_property_read_u32(i80_if_timings, "wr-setup", &val))
1124                         val = 0;
1125                 ctx->i80ifcon |= LCD_WR_SETUP(val);
1126                 if (of_property_read_u32(i80_if_timings, "wr-active", &val))
1127                         val = 1;
1128                 ctx->i80ifcon |= LCD_WR_ACTIVE(val);
1129                 if (of_property_read_u32(i80_if_timings, "wr-hold", &val))
1130                         val = 0;
1131                 ctx->i80ifcon |= LCD_WR_HOLD(val);
1132         }
1133         of_node_put(i80_if_timings);
1134
1135         ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1136                                                         "samsung,sysreg");
1137         if (IS_ERR(ctx->sysreg)) {
1138                 dev_warn(dev, "failed to get system register.\n");
1139                 ctx->sysreg = NULL;
1140         }
1141
1142         ctx->bus_clk = devm_clk_get(dev, "fimd");
1143         if (IS_ERR(ctx->bus_clk)) {
1144                 dev_err(dev, "failed to get bus clock\n");
1145                 ret = PTR_ERR(ctx->bus_clk);
1146                 goto err_del_component;
1147         }
1148
1149         ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
1150         if (IS_ERR(ctx->lcd_clk)) {
1151                 dev_err(dev, "failed to get lcd clock\n");
1152                 ret = PTR_ERR(ctx->lcd_clk);
1153                 goto err_del_component;
1154         }
1155
1156         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1157
1158         ctx->regs = devm_ioremap_resource(dev, res);
1159         if (IS_ERR(ctx->regs)) {
1160                 ret = PTR_ERR(ctx->regs);
1161                 goto err_del_component;
1162         }
1163
1164         res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1165                                            ctx->i80_if ? "lcd_sys" : "vsync");
1166         if (!res) {
1167                 dev_err(dev, "irq request failed.\n");
1168                 ret = -ENXIO;
1169                 goto err_del_component;
1170         }
1171
1172         ret = devm_request_irq(dev, res->start, fimd_irq_handler,
1173                                                         0, "drm_fimd", ctx);
1174         if (ret) {
1175                 dev_err(dev, "irq request failed.\n");
1176                 goto err_del_component;
1177         }
1178
1179         init_waitqueue_head(&ctx->wait_vsync_queue);
1180         atomic_set(&ctx->wait_vsync_event, 0);
1181
1182         platform_set_drvdata(pdev, &fimd_manager);
1183
1184         fimd_manager.ctx = ctx;
1185
1186         ctx->display = exynos_dpi_probe(dev);
1187         if (IS_ERR(ctx->display))
1188                 return PTR_ERR(ctx->display);
1189
1190         pm_runtime_enable(&pdev->dev);
1191
1192         ret = component_add(&pdev->dev, &fimd_component_ops);
1193         if (ret)
1194                 goto err_disable_pm_runtime;
1195
1196         return ret;
1197
1198 err_disable_pm_runtime:
1199         pm_runtime_disable(&pdev->dev);
1200
1201 err_del_component:
1202         exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1203         return ret;
1204 }
1205
1206 static int fimd_remove(struct platform_device *pdev)
1207 {
1208         pm_runtime_disable(&pdev->dev);
1209
1210         component_del(&pdev->dev, &fimd_component_ops);
1211         exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1212
1213         return 0;
1214 }
1215
1216 struct platform_driver fimd_driver = {
1217         .probe          = fimd_probe,
1218         .remove         = fimd_remove,
1219         .driver         = {
1220                 .name   = "exynos4-fb",
1221                 .owner  = THIS_MODULE,
1222                 .of_match_table = fimd_driver_dt_match,
1223         },
1224 };