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