Revert "drm/exynos: Implements proper disable of LCD clock"
[cascardo/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 "drmP.h"
15
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/clk.h>
20 #include <linux/pm_runtime.h>
21
22 #include <drm/exynos_drm.h>
23 #include <plat/regs-fb-v4.h>
24
25 #include "exynos_drm_drv.h"
26 #include "exynos_drm_crtc.h"
27 #include "exynos_drm_fbdev.h"
28
29 /*
30  * FIMD is stand for Fully Interactive Mobile Display and
31  * as a display controller, it transfers contents drawn on memory
32  * to a LCD Panel through Display Interfaces such as RGB or
33  * CPU Interface.
34  */
35
36 /* position control register for hardware window 0, 2 ~ 4.*/
37 #define VIDOSD_A(win)           (VIDOSD_BASE + 0x00 + (win) * 16)
38 #define VIDOSD_B(win)           (VIDOSD_BASE + 0x04 + (win) * 16)
39 /* size control register for hardware window 0. */
40 #define VIDOSD_C_SIZE_W0        (VIDOSD_BASE + 0x08)
41 /* alpha control register for hardware window 1 ~ 4. */
42 #define VIDOSD_C(win)           (VIDOSD_BASE + 0x18 + (win) * 16)
43 /* size control register for hardware window 1 ~ 4. */
44 #define VIDOSD_D(win)           (VIDOSD_BASE + 0x0C + (win) * 16)
45
46 #define VIDWx_BUF_START(win, buf)       (VIDW_BUF_START(buf) + (win) * 8)
47 #define VIDWx_BUF_END(win, buf)         (VIDW_BUF_END(buf) + (win) * 8)
48 #define VIDWx_BUF_SIZE(win, buf)        (VIDW_BUF_SIZE(buf) + (win) * 4)
49
50 /* color key control register for hardware window 1 ~ 4. */
51 #define WKEYCON0_BASE(x)                ((WKEYCON0 + 0x140) + (x * 8))
52 /* color key value register for hardware window 1 ~ 4. */
53 #define WKEYCON1_BASE(x)                ((WKEYCON1 + 0x140) + (x * 8))
54
55 /* FIMD has totally five hardware windows. */
56 #define WINDOWS_NR      5
57
58 #define get_fimd_context(dev)   platform_get_drvdata(to_platform_device(dev))
59
60 struct fimd_win_data {
61         unsigned int            offset_x;
62         unsigned int            offset_y;
63         unsigned int            ovl_width;
64         unsigned int            ovl_height;
65         unsigned int            fb_width;
66         unsigned int            fb_height;
67         unsigned int            fb_pitch;
68         unsigned int            bpp;
69         dma_addr_t              dma_addr;
70         void __iomem            *vaddr;
71         unsigned int            buf_offsize;
72         unsigned int            line_size;      /* bytes */
73         bool                    enabled;
74 };
75
76 struct fimd_context {
77         struct exynos_drm_subdrv        subdrv;
78         int                             irq;
79         struct drm_crtc                 *crtc;
80         struct clk                      *bus_clk;
81         struct clk                      *lcd_clk;
82         struct resource                 *regs_res;
83         void __iomem                    *regs;
84         void __iomem                    *regs_mie;
85         struct fimd_win_data            win_data[WINDOWS_NR];
86         unsigned int                    clkdiv[MAX_NR_PANELS];
87         unsigned int                    default_win;
88         unsigned long                   irq_flags;
89         u32                             vidcon0;
90         u32                             vidcon1;
91         int                             idx;
92         bool                            suspended;
93         struct mutex                    lock;
94
95         struct exynos_drm_panel_info *panel;
96 };
97
98 static bool fimd_display_is_connected(struct device *dev)
99 {
100         DRM_DEBUG_KMS("%s\n", __FILE__);
101
102         /* TODO. */
103
104         return true;
105 }
106
107 static void *fimd_get_panel(struct device *dev)
108 {
109         struct fimd_context *ctx = get_fimd_context(dev);
110
111         DRM_DEBUG_KMS("%s\n", __FILE__);
112
113         return ctx->panel;
114 }
115
116 static int fimd_check_timing(struct device *dev, void *timing)
117 {
118         struct fimd_context *ctx = get_fimd_context(dev);
119         struct fb_videomode *check_timing = timing;
120         int i;
121
122         DRM_DEBUG_KMS("%s\n", __FILE__);
123
124         for (i = 0;i< MAX_NR_PANELS;i++) {
125                 if (ctx->panel[i].timing.xres == -1 &&
126                          ctx->panel[i].timing.yres == -1)
127                          break;
128
129                 if (ctx->panel[i].timing.xres == check_timing->xres &&
130                          ctx->panel[i].timing.yres == check_timing->yres &&
131                         ctx->panel[i].timing.refresh == check_timing->refresh
132                         )
133                         return 0;
134         }
135
136         return -EINVAL;
137 }
138
139 static int fimd_power_on(struct fimd_context *ctx, bool enable);
140
141 static int fimd_display_power_on(struct device *dev, int mode)
142 {
143         struct fimd_context *ctx = get_fimd_context(dev);
144         bool enable;
145
146         DRM_DEBUG_KMS("%s\n", __FILE__);
147
148         switch (mode) {
149         case DRM_MODE_DPMS_ON:
150         case DRM_MODE_DPMS_STANDBY:
151                 enable = true;
152                 break;
153         case DRM_MODE_DPMS_SUSPEND:
154         case DRM_MODE_DPMS_OFF:
155                 enable = false;
156                 break;
157         default:
158                 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
159                 return -EINVAL;
160         }
161
162         fimd_power_on(ctx, enable);
163
164         return 0;
165 }
166
167 static struct exynos_drm_display_ops fimd_display_ops = {
168         .type = EXYNOS_DISPLAY_TYPE_LCD,
169         .is_connected = fimd_display_is_connected,
170         .get_panel = fimd_get_panel,
171         .check_timing = fimd_check_timing,
172         .power_on = fimd_display_power_on,
173 };
174
175 static void fimd_apply(struct device *subdrv_dev)
176 {
177         struct fimd_context *ctx = get_fimd_context(subdrv_dev);
178         struct exynos_drm_manager *mgr = ctx->subdrv.manager;
179         struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
180         struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
181         struct fimd_win_data *win_data;
182         int i;
183
184         DRM_DEBUG_KMS("%s\n", __FILE__);
185
186         for (i = 0; i < WINDOWS_NR; i++) {
187                 win_data = &ctx->win_data[i];
188                 if (win_data->enabled && (ovl_ops && ovl_ops->commit))
189                         ovl_ops->commit(subdrv_dev, i);
190         }
191
192         if (mgr_ops && mgr_ops->commit)
193                 mgr_ops->commit(subdrv_dev);
194 }
195
196 static void fimd_commit(struct device *dev)
197 {
198         struct fimd_context *ctx = get_fimd_context(dev);
199         struct exynos_drm_panel_info *panel = &ctx->panel[ctx->idx];
200         struct fb_videomode *timing = &panel->timing;
201         u32 val;
202
203         if (ctx->suspended)
204                 return;
205
206         DRM_DEBUG_KMS("%s\n", __FILE__);
207
208         /* setup polarity values from machine code. */
209         writel(ctx->vidcon1, ctx->regs + VIDCON1);
210
211         /* setup vertical timing values. */
212         val = VIDTCON0_VBPD(timing->upper_margin - 1) |
213                VIDTCON0_VFPD(timing->lower_margin - 1) |
214                VIDTCON0_VSPW(timing->vsync_len - 1);
215         writel(val, ctx->regs + VIDTCON0);
216
217         /* setup horizontal timing values.  */
218         val = VIDTCON1_HBPD(timing->left_margin - 1) |
219                VIDTCON1_HFPD(timing->right_margin - 1) |
220                VIDTCON1_HSPW(timing->hsync_len - 1);
221         writel(val, ctx->regs + VIDTCON1);
222
223         /* setup horizontal and vertical display size. */
224         val = VIDTCON2_LINEVAL(timing->yres - 1) |
225                VIDTCON2_HOZVAL(timing->xres - 1);
226         writel(val, ctx->regs + VIDTCON2);
227
228         /* setup clock source, clock divider, enable dma. */
229         val = ctx->vidcon0;
230         val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
231
232         if (ctx->clkdiv[ctx->idx] > 1)
233                 val |= VIDCON0_CLKVAL_F(ctx->clkdiv[ctx->idx] - 1) | VIDCON0_CLKDIR;
234         else
235                 val &= ~VIDCON0_CLKDIR; /* 1:1 clock */
236
237         /*
238          * fields of register with prefix '_F' would be updated
239          * at vsync(same as dma start)
240          */
241         val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
242         writel(val, ctx->regs + VIDCON0);
243 }
244
245 static int fimd_enable_vblank(struct device *dev)
246 {
247         struct fimd_context *ctx = get_fimd_context(dev);
248         u32 val;
249
250         DRM_DEBUG_KMS("%s\n", __FILE__);
251
252         if (ctx->suspended)
253                 return -EPERM;
254
255         if (!test_and_set_bit(0, &ctx->irq_flags)) {
256                 val = readl(ctx->regs + VIDINTCON0);
257
258                 val |= VIDINTCON0_INT_ENABLE;
259                 val |= VIDINTCON0_INT_FRAME;
260
261                 val &= ~VIDINTCON0_FRAMESEL0_MASK;
262                 val |= VIDINTCON0_FRAMESEL0_VSYNC;
263                 val &= ~VIDINTCON0_FRAMESEL1_MASK;
264                 val |= VIDINTCON0_FRAMESEL1_NONE;
265
266                 writel(val, ctx->regs + VIDINTCON0);
267         }
268
269         return 0;
270 }
271
272 static void fimd_disable_vblank(struct device *dev)
273 {
274         struct fimd_context *ctx = get_fimd_context(dev);
275         u32 val;
276
277         DRM_DEBUG_KMS("%s\n", __FILE__);
278
279         if (ctx->suspended)
280                 return;
281
282         if (test_and_clear_bit(0, &ctx->irq_flags)) {
283                 val = readl(ctx->regs + VIDINTCON0);
284
285                 val &= ~VIDINTCON0_INT_FRAME;
286                 val &= ~VIDINTCON0_INT_ENABLE;
287
288                 writel(val, ctx->regs + VIDINTCON0);
289         }
290 }
291
292 static struct exynos_drm_manager_ops fimd_manager_ops = {
293         .apply = fimd_apply,
294         .commit = fimd_commit,
295         .enable_vblank = fimd_enable_vblank,
296         .disable_vblank = fimd_disable_vblank,
297 };
298
299 static void fimd_win_mode_set(struct device *dev,
300                               struct exynos_drm_overlay *overlay)
301 {
302         struct fimd_context *ctx = get_fimd_context(dev);
303         struct fimd_win_data *win_data;
304         int win;
305         unsigned long offset;
306
307         DRM_DEBUG_KMS("%s\n", __FILE__);
308
309         if (!overlay) {
310                 dev_err(dev, "overlay is NULL\n");
311                 return;
312         }
313
314         win = overlay->zpos;
315         if (win == DEFAULT_ZPOS)
316                 win = ctx->default_win;
317
318         if (win < 0 || win > WINDOWS_NR)
319                 return;
320
321         if(win == ctx->default_win) {
322                 for(ctx->idx = 0;ctx->idx < MAX_NR_PANELS;ctx->idx++) {
323                         if (ctx->panel[ctx->idx].timing.xres == -1 &&
324                                 ctx->panel[ctx->idx].timing.yres == -1) {
325                                         DRM_ERROR("Invalid panel parameters");
326                                         ctx->idx = 0; /* Reset to first panel index*/
327                                         break;
328                                 }
329                         if (ctx->panel[ctx->idx].timing.xres == overlay->fb_width &&
330                                 ctx->panel[ctx->idx].timing.yres == overlay->fb_height)
331                                         break;
332                 }
333         }
334
335         offset = overlay->fb_x * (overlay->bpp >> 3);
336         offset += overlay->fb_y * overlay->fb_pitch;
337
338         DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n",
339                 offset, overlay->fb_pitch);
340
341         win_data = &ctx->win_data[win];
342
343         win_data->offset_x = overlay->crtc_x;
344         win_data->offset_y = overlay->crtc_y;
345         win_data->ovl_width = overlay->crtc_width;
346         win_data->ovl_height = overlay->crtc_height;
347         win_data->fb_width = overlay->fb_width;
348         win_data->fb_height = overlay->fb_height;
349         win_data->fb_pitch = overlay->fb_pitch;
350         win_data->dma_addr = overlay->dma_addr[0] + offset;
351         win_data->vaddr = overlay->vaddr[0] + offset;
352         win_data->bpp = overlay->bpp;
353         win_data->buf_offsize = overlay->fb_pitch -
354                 (overlay->fb_width * (overlay->bpp >> 3));
355         win_data->line_size = overlay->fb_width * (overlay->bpp >> 3);
356
357         DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
358                         win_data->offset_x, win_data->offset_y);
359         DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
360                         win_data->ovl_width, win_data->ovl_height);
361         DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
362                         (unsigned long)win_data->dma_addr,
363                         (unsigned long)win_data->vaddr);
364         DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
365                         overlay->fb_width, overlay->crtc_width);
366 }
367
368 static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
369 {
370         struct fimd_context *ctx = get_fimd_context(dev);
371         struct fimd_win_data *win_data = &ctx->win_data[win];
372         unsigned long val;
373         unsigned long bytes;
374
375         DRM_DEBUG_KMS("%s\n", __FILE__);
376
377         val = WINCONx_ENWIN;
378
379         switch (win_data->bpp) {
380         case 1:
381                 val |= WINCON0_BPPMODE_1BPP;
382                 val |= WINCONx_BITSWP;
383                 bytes = win_data->fb_width >> 3;
384                 break;
385         case 2:
386                 val |= WINCON0_BPPMODE_2BPP;
387                 val |= WINCONx_BITSWP;
388                 bytes = win_data->fb_width >> 2;
389                 break;
390         case 4:
391                 val |= WINCON0_BPPMODE_4BPP;
392                 val |= WINCONx_BITSWP;
393                 bytes = win_data->fb_width >> 1;
394                 break;
395         case 8:
396                 val |= WINCON0_BPPMODE_8BPP_PALETTE;
397                 val |= WINCONx_BYTSWP;
398                 bytes = win_data->fb_width;
399                 break;
400         case 16:
401                 val |= WINCON0_BPPMODE_16BPP_565;
402                 val |= WINCONx_HAWSWP;
403                 bytes = win_data->fb_width << 1;
404                 break;
405         case 24:
406                 val |= WINCON0_BPPMODE_24BPP_888;
407                 val |= WINCONx_WSWP;
408                 bytes = win_data->fb_width * 3;
409                 break;
410         case 32:
411                 val |= WINCON1_BPPMODE_28BPP_A4888
412                         | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
413                 val |= WINCONx_WSWP;
414                 bytes = win_data->fb_width << 2;
415                 break;
416         default:
417                 DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
418                 bytes = win_data->fb_width * 3;
419                 val |= WINCON0_BPPMODE_24BPP_888;
420                 val |= WINCONx_WSWP;
421                 break;
422         }
423
424         /*
425          * Adjust the burst size based on the number of bytes to be read.
426          * Each WORD of the BURST is 8 bytes long. There are 3 BURST sizes
427          * supported by fimd.
428          * WINCONx_BURSTLEN_4WORD = 32 bytes
429          * WINCONx_BURSTLEN_8WORD = 64 bytes
430          * WINCONx_BURSTLEN_16WORD = 128 bytes
431          */
432         if (win_data->fb_width <= 64)
433                 val |= WINCONx_BURSTLEN_4WORD;
434         else
435                 val |= WINCONx_BURSTLEN_16WORD;
436
437         DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
438
439         writel(val, ctx->regs + WINCON(win));
440 }
441
442 static void fimd_win_set_colkey(struct device *dev, unsigned int win)
443 {
444         struct fimd_context *ctx = get_fimd_context(dev);
445         unsigned int keycon0 = 0, keycon1 = 0;
446
447         DRM_DEBUG_KMS("%s\n", __FILE__);
448
449         keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
450                         WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
451
452         keycon1 = WxKEYCON1_COLVAL(0xffffffff);
453
454         writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
455         writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
456 }
457
458 static void mie_set_6bit_dithering(struct fimd_context *ctx)
459 {
460         struct fb_videomode *timing = &ctx->panel->timing;
461         unsigned long val;
462         int i;
463
464         writel(MIE_HRESOL(timing->xres) | MIE_VRESOL(timing->yres) |
465                                 MIE_MODE_UI, ctx->regs_mie + MIE_CTRL1);
466
467         writel(MIE_WINHADDR0(0) | MIE_WINHADDR1(timing->xres),
468                                                 ctx->regs_mie + MIE_WINHADDR);
469         writel(MIE_WINVADDR0(0) | MIE_WINVADDR1(timing->yres),
470                                                 ctx->regs_mie + MIE_WINVADDR);
471
472         val = (timing->xres + timing->left_margin +
473                         timing->right_margin + timing->hsync_len) *
474               (timing->yres + timing->upper_margin +
475                         timing->lower_margin + timing->vsync_len) /
476                                                         (MIE_PWMCLKVAL + 1);
477         writel(PWMCLKCNT(val), ctx->regs_mie + MIE_PWMCLKCNT);
478
479         writel((MIE_VBPD(timing->upper_margin)) |
480                 MIE_VFPD(timing->lower_margin) |
481                 MIE_VSPW(timing->vsync_len), ctx->regs_mie + MIE_PWMVIDTCON1);
482
483         writel(MIE_HBPD(timing->left_margin) |
484                 MIE_HFPD(timing->right_margin) |
485                 MIE_HSPW(timing->hsync_len), ctx->regs_mie + MIE_PWMVIDTCON2);
486
487         writel(MIE_DITHCON_EN | MIE_RGB6MODE,
488                                         ctx->regs_mie + MIE_AUXCON);
489
490         /* Bypass MIE image brightness enhancement */
491         for (i = 0; i <= 0x30; i += 4) {
492                 writel(0, ctx->regs_mie + 0x100 + i);
493                 writel(0, ctx->regs_mie + 0x200 + i);
494         }
495 }
496
497 static void fimd_win_commit(struct device *dev, int zpos)
498 {
499         struct fimd_context *ctx = get_fimd_context(dev);
500         struct fimd_win_data *win_data;
501         int win = zpos;
502         unsigned long val, alpha, size;
503
504         DRM_DEBUG_KMS("%s\n", __FILE__);
505
506         if (ctx->suspended)
507                 return;
508
509         if (win == DEFAULT_ZPOS)
510                 win = ctx->default_win;
511
512         if (win < 0 || win > WINDOWS_NR)
513                 return;
514
515         win_data = &ctx->win_data[win];
516
517         /*
518          * SHADOWCON register is used for enabling timing.
519          *
520          * for example, once only width value of a register is set,
521          * if the dma is started then fimd hardware could malfunction so
522          * with protect window setting, the register fields with prefix '_F'
523          * wouldn't be updated at vsync also but updated once unprotect window
524          * is set.
525          */
526
527         /* protect windows */
528         val = readl(ctx->regs + SHADOWCON);
529         val |= SHADOWCON_WINx_PROTECT(win);
530         writel(val, ctx->regs + SHADOWCON);
531
532         /* buffer start address */
533         val = (unsigned long)win_data->dma_addr;
534         writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
535
536         /* buffer end address */
537         size = win_data->fb_height * win_data->fb_pitch;
538         val = (unsigned long)(win_data->dma_addr + size);
539         writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
540
541         DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
542                         (unsigned long)win_data->dma_addr, val, size);
543         DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
544                         win_data->ovl_width, win_data->ovl_height);
545
546         /* buffer size */
547         val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
548                 VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size);
549         writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
550
551         /* OSD position */
552         val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
553                 VIDOSDxA_TOPLEFT_Y(win_data->offset_y);
554         writel(val, ctx->regs + VIDOSD_A(win));
555
556         val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x +
557                                         win_data->ovl_width - 1) |
558                 VIDOSDxB_BOTRIGHT_Y(win_data->offset_y +
559                                         win_data->ovl_height - 1);
560         writel(val, ctx->regs + VIDOSD_B(win));
561
562         DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
563                         win_data->offset_x, win_data->offset_y,
564                         win_data->offset_x + win_data->ovl_width - 1,
565                         win_data->offset_y + win_data->ovl_height - 1);
566
567         /* hardware window 0 doesn't support alpha channel. */
568         if (win != 0) {
569                 /* OSD alpha */
570                 alpha = VIDISD14C_ALPHA1_R(0xf) |
571                         VIDISD14C_ALPHA1_G(0xf) |
572                         VIDISD14C_ALPHA1_B(0xf);
573
574                 writel(alpha, ctx->regs + VIDOSD_C(win));
575         }
576
577         /* OSD size */
578         if (win != 3 && win != 4) {
579                 u32 offset = VIDOSD_D(win);
580                 if (win == 0)
581                         offset = VIDOSD_C_SIZE_W0;
582                 val = win_data->ovl_width * win_data->ovl_height;
583                 writel(val, ctx->regs + offset);
584
585                 DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
586         }
587
588         fimd_win_set_pixfmt(dev, win);
589
590         /* hardware window 0 doesn't support color key. */
591         if (win != 0)
592                 fimd_win_set_colkey(dev, win);
593
594         /* wincon */
595         val = readl(ctx->regs + WINCON(win));
596         val |= WINCONx_ENWIN;
597         writel(val, ctx->regs + WINCON(win));
598
599         mie_set_6bit_dithering(ctx);
600
601         /* Enable DMA channel and unprotect windows */
602         val = readl(ctx->regs + SHADOWCON);
603         val |= SHADOWCON_CHx_ENABLE(win);
604         val &= ~SHADOWCON_WINx_PROTECT(win);
605         writel(val, ctx->regs + SHADOWCON);
606
607         win_data->enabled = true;
608 }
609
610 static void fimd_win_disable(struct device *dev, int zpos)
611 {
612         struct fimd_context *ctx = get_fimd_context(dev);
613         struct fimd_win_data *win_data;
614         int win = zpos;
615         u32 val;
616
617         DRM_DEBUG_KMS("%s\n", __FILE__);
618         if (ctx->suspended)
619                 return;
620
621         if (win == DEFAULT_ZPOS)
622                 win = ctx->default_win;
623
624         if (win < 0 || win > WINDOWS_NR)
625                 return;
626
627         win_data = &ctx->win_data[win];
628
629         /* protect windows */
630         val = readl(ctx->regs + SHADOWCON);
631         val |= SHADOWCON_WINx_PROTECT(win);
632         writel(val, ctx->regs + SHADOWCON);
633
634         /* wincon */
635         val = readl(ctx->regs + WINCON(win));
636         val &= ~WINCONx_ENWIN;
637         writel(val, ctx->regs + WINCON(win));
638
639         /* unprotect windows */
640         val = readl(ctx->regs + SHADOWCON);
641         val &= ~SHADOWCON_CHx_ENABLE(win);
642         val &= ~SHADOWCON_WINx_PROTECT(win);
643         writel(val, ctx->regs + SHADOWCON);
644
645         win_data->enabled = false;
646 }
647
648 static struct exynos_drm_overlay_ops fimd_overlay_ops = {
649         .mode_set = fimd_win_mode_set,
650         .commit = fimd_win_commit,
651         .disable = fimd_win_disable,
652 };
653
654 static struct exynos_drm_manager fimd_manager = {
655         .pipe           = -1,
656         .ops            = &fimd_manager_ops,
657         .overlay_ops    = &fimd_overlay_ops,
658         .display_ops    = &fimd_display_ops,
659 };
660
661 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
662 {
663         struct fimd_context *ctx = (struct fimd_context *)dev_id;
664         struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
665         struct drm_device *drm_dev = subdrv->drm_dev;
666         struct exynos_drm_manager *manager = subdrv->manager;
667         u32 val;
668
669         val = readl(ctx->regs + VIDINTCON1);
670
671         if (val & VIDINTCON1_INT_FRAME)
672                 /* VSYNC interrupt */
673                 writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
674
675         /* check the crtc is detached already from encoder */
676         if (manager->pipe < 0)
677                 goto out;
678
679         drm_handle_vblank(drm_dev, manager->pipe);
680         exynos_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
681
682 out:
683         return IRQ_HANDLED;
684 }
685
686 static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
687 {
688         DRM_DEBUG_KMS("%s\n", __FILE__);
689
690         /*
691          * enable drm irq mode.
692          * - with irq_enabled = 1, we can use the vblank feature.
693          *
694          * P.S. note that we wouldn't use drm irq handler but
695          *      just specific driver own one instead because
696          *      drm framework supports only one irq handler.
697          */
698         drm_dev->irq_enabled = 1;
699
700         /*
701          * with vblank_disable_allowed = 1, vblank interrupt will be disabled
702          * by drm timer once a current process gives up ownership of
703          * vblank event.(after drm_vblank_put function is called)
704          */
705         drm_dev->vblank_disable_allowed = 1;
706
707         return 0;
708 }
709
710 static void fimd_subdrv_remove(struct drm_device *drm_dev)
711 {
712         DRM_DEBUG_KMS("%s\n", __FILE__);
713
714         /* TODO. */
715 }
716
717 static int fimd_calc_clkdiv(struct fimd_context *ctx,
718                             struct fb_videomode *timing)
719 {
720         unsigned long clk = clk_get_rate(ctx->lcd_clk);
721         u32 retrace;
722         u32 clkdiv;
723         u32 best_framerate = 0;
724         u32 framerate;
725
726         DRM_DEBUG_KMS("%s\n", __FILE__);
727
728         retrace = timing->left_margin + timing->hsync_len +
729                                 timing->right_margin + timing->xres;
730         retrace *= timing->upper_margin + timing->vsync_len +
731                                 timing->lower_margin + timing->yres;
732
733         /* default framerate is 60Hz */
734         if (!timing->refresh)
735                 timing->refresh = 60;
736
737         clk /= retrace;
738
739         for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
740                 int tmp;
741
742                 /* get best framerate */
743                 framerate = clk / clkdiv;
744                 tmp = timing->refresh - framerate;
745                 if (tmp < 0) {
746                         best_framerate = framerate;
747                         continue;
748                 } else {
749                         if (!best_framerate)
750                                 best_framerate = framerate;
751                         else if (tmp < (best_framerate - framerate))
752                                 best_framerate = framerate;
753                         break;
754                 }
755         }
756
757         return clkdiv;
758 }
759
760 static void fimd_clear_win(struct fimd_context *ctx, int win)
761 {
762         u32 val;
763
764         DRM_DEBUG_KMS("%s\n", __FILE__);
765
766         writel(0, ctx->regs + WINCON(win));
767         writel(0, ctx->regs + VIDOSD_A(win));
768         writel(0, ctx->regs + VIDOSD_B(win));
769         writel(0, ctx->regs + VIDOSD_C(win));
770
771         if (win == 1 || win == 2)
772                 writel(0, ctx->regs + VIDOSD_D(win));
773
774         val = readl(ctx->regs + SHADOWCON);
775         val &= ~SHADOWCON_WINx_PROTECT(win);
776         writel(val, ctx->regs + SHADOWCON);
777 }
778
779 static int fimd_power_on(struct fimd_context *ctx, bool enable)
780 {
781         struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
782         struct device *dev = subdrv->dev;
783         struct exynos_drm_fimd_pdata *pdata = dev->platform_data;
784         int i;
785
786         DRM_DEBUG_KMS("%s\n", __FILE__);
787
788         if (enable) {
789                 int ret;
790
791                 ret = clk_enable(ctx->bus_clk);
792                 if (ret < 0)
793                         return ret;
794
795                 ret = clk_enable(ctx->lcd_clk);
796                 if  (ret < 0) {
797                         clk_disable(ctx->bus_clk);
798                         return ret;
799                 }
800
801                 ctx->suspended = false;
802
803                 /* if vblank was enabled status, enable it again. */
804                 if (test_and_clear_bit(0, &ctx->irq_flags))
805                         fimd_enable_vblank(dev);
806
807                 fimd_apply(dev);
808
809                 if (pdata->panel_type == DP_LCD)
810                         writel(MIE_CLK_ENABLE, ctx->regs + DPCLKCON);
811         } else {
812                 /*
813                  * We need to make sure that all windows are disabled before we
814                  * suspend that connector. Otherwise we might try to scan from
815                  * a destroyed buffer later.
816                  */
817                 for (i = 0; i < WINDOWS_NR; i++)
818                         fimd_win_disable(dev, i);
819
820                 clk_disable(ctx->lcd_clk);
821                 clk_disable(ctx->bus_clk);
822
823                 ctx->suspended = true;
824
825                 if (pdata->panel_type == DP_LCD)
826                         writel(0, ctx->regs + DPCLKCON);
827         }
828
829         return 0;
830 }
831
832 #ifdef CONFIG_EXYNOS_IOMMU
833 static int iommu_init(struct platform_device *pdev)
834 {
835         struct platform_device *pds;
836
837         pds = find_sysmmu_dt(pdev, "sysmmu");
838         if (pds==NULL) {
839                 printk(KERN_ERR "No sysmmu found\n");
840                 return -1;
841         }
842
843         platform_set_sysmmu(&pds->dev, &pdev->dev);
844         exynos_drm_common_mapping = s5p_create_iommu_mapping(&pdev->dev,
845                                         0x20000000, SZ_256M, 4,
846                                         exynos_drm_common_mapping);
847
848         if (!exynos_drm_common_mapping) {
849                 printk(KERN_ERR "IOMMU mapping not created\n");
850                 return -1;
851         }
852
853         return 0;
854 }
855
856 static void iommu_deinit(struct platform_device *pdev)
857 {
858         s5p_destroy_iommu_mapping(&pdev->dev);
859         DRM_DEBUG("released the IOMMU mapping\n");
860
861         return;
862 }
863 #endif
864
865 static int __devinit fimd_probe(struct platform_device *pdev)
866 {
867         struct device *dev = &pdev->dev;
868         struct fimd_context *ctx;
869         struct exynos_drm_subdrv *subdrv;
870         struct exynos_drm_fimd_pdata *pdata;
871         struct exynos_drm_panel_info *panel;
872         struct resource *res;
873         struct clk *clk_parent;
874         int win,i;
875         int ret = -EINVAL;
876
877 #ifdef CONFIG_EXYNOS_IOMMU
878         ret = iommu_init(pdev);
879         if (ret < 0) {
880                 dev_err(dev, "failed to initialize IOMMU\n");
881                 return -ENODEV;
882         }
883 #endif
884         DRM_DEBUG_KMS("%s\n", __FILE__);
885
886         pdata = pdev->dev.platform_data;
887         if (!pdata) {
888                 dev_err(dev, "no platform data specified\n");
889                 return -EINVAL;
890         }
891
892         panel = pdata->panel;
893         if (!panel) {
894                 dev_err(dev, "panel is null.\n");
895                 return -EINVAL;
896         }
897
898         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
899         if (!ctx)
900                 return -ENOMEM;
901
902         ctx->bus_clk = clk_get(dev, "fimd");
903         if (IS_ERR(ctx->bus_clk)) {
904                 dev_err(dev, "failed to get bus clock\n");
905                 ret = PTR_ERR(ctx->bus_clk);
906                 goto err_clk_get;
907         }
908
909         ctx->lcd_clk = clk_get(dev, "sclk_fimd");
910         if (IS_ERR(ctx->lcd_clk)) {
911                 dev_err(dev, "failed to get lcd clock\n");
912                 ret = PTR_ERR(ctx->lcd_clk);
913                 goto err_bus_clk;
914         }
915
916         clk_parent = clk_get(NULL, "sclk_vpll");
917         if (IS_ERR(clk_parent)) {
918                 ret = PTR_ERR(clk_parent);
919                 goto err_clk;
920         }
921
922         if (clk_set_parent(ctx->lcd_clk, clk_parent)) {
923                 ret = PTR_ERR(ctx->lcd_clk);
924                 goto err_clk;
925         }
926
927         if (clk_set_rate(ctx->lcd_clk, pdata->clock_rate)) {
928                 ret = PTR_ERR(ctx->lcd_clk);
929                 goto err_clk;
930         }
931
932         clk_put(clk_parent);
933
934         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
935         if (!res) {
936                 dev_err(dev, "failed to find registers\n");
937                 ret = -ENOENT;
938                 goto err_clk;
939         }
940
941         ctx->regs_res = request_mem_region(res->start, resource_size(res),
942                                            dev_name(dev));
943         if (!ctx->regs_res) {
944                 dev_err(dev, "failed to claim register region\n");
945                 ret = -ENOENT;
946                 goto err_clk;
947         }
948
949         ctx->regs = ioremap(res->start, resource_size(res));
950         if (!ctx->regs) {
951                 dev_err(dev, "failed to map registers\n");
952                 ret = -ENXIO;
953                 goto err_req_region_io;
954         }
955
956         ctx->regs_mie = ioremap(MIE_BASE_ADDRESS, 0x400);
957         if (!ctx->regs_mie) {
958                 dev_err(dev, "failed to map registers\n");
959                 ret = -ENXIO;
960                 goto err_req_region_io_mie;
961         }
962
963         res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
964         if (!res) {
965                 dev_err(dev, "irq request failed.\n");
966                 goto err_req_region_irq;
967         }
968
969         ctx->irq = res->start;
970
971         ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx);
972         if (ret < 0) {
973                 dev_err(dev, "irq request failed.\n");
974                 goto err_req_irq;
975         }
976
977         ctx->vidcon0 = pdata->vidcon0;
978         ctx->vidcon1 = pdata->vidcon1;
979         ctx->default_win = pdata->default_win;
980         ctx->panel = panel;
981
982         subdrv = &ctx->subdrv;
983
984         subdrv->dev = dev;
985         subdrv->manager = &fimd_manager;
986         subdrv->probe = fimd_subdrv_probe;
987         subdrv->remove = fimd_subdrv_remove;
988
989         mutex_init(&ctx->lock);
990
991         platform_set_drvdata(pdev, ctx);
992
993         pm_runtime_enable(dev);
994         pm_runtime_get_sync(dev);
995
996         for (i = 0;i < MAX_NR_PANELS;i++) {
997                 if(panel[i].timing.xres == -1 && panel[i].timing.yres == -1)
998                         break;
999
1000                 ctx->clkdiv[i] = fimd_calc_clkdiv(ctx, &panel[i].timing);
1001                 panel[i].timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv[i];
1002                 DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n for panel[%d]",
1003                                 panel[i].timing.pixclock, ctx->clkdiv[i],i);
1004         }
1005
1006         for (win = 0; win < WINDOWS_NR; win++)
1007                 fimd_clear_win(ctx, win);
1008
1009         if (pdata->panel_type == DP_LCD)
1010                 writel(MIE_CLK_ENABLE, ctx->regs + DPCLKCON);
1011
1012         exynos_drm_subdrv_register(subdrv);
1013
1014         return 0;
1015
1016 err_req_irq:
1017 err_req_region_irq:
1018         iounmap(ctx->regs_mie);
1019
1020 err_req_region_io_mie:
1021         iounmap(ctx->regs);
1022
1023 err_req_region_io:
1024         release_resource(ctx->regs_res);
1025         kfree(ctx->regs_res);
1026
1027 err_clk:
1028         clk_disable(ctx->lcd_clk);
1029         clk_put(ctx->lcd_clk);
1030
1031 err_bus_clk:
1032         clk_disable(ctx->bus_clk);
1033         clk_put(ctx->bus_clk);
1034
1035 err_clk_get:
1036 #ifdef CONFIG_EXYNOS_IOMMU
1037         iommu_deinit(pdev);
1038 #endif
1039         kfree(ctx);
1040         return ret;
1041 }
1042
1043 static int __devexit fimd_remove(struct platform_device *pdev)
1044 {
1045         struct device *dev = &pdev->dev;
1046         struct fimd_context *ctx = platform_get_drvdata(pdev);
1047
1048         DRM_DEBUG_KMS("%s\n", __FILE__);
1049
1050         exynos_drm_subdrv_unregister(&ctx->subdrv);
1051
1052         if (ctx->suspended)
1053                 goto out;
1054
1055         clk_disable(ctx->lcd_clk);
1056         clk_disable(ctx->bus_clk);
1057
1058         pm_runtime_set_suspended(dev);
1059         pm_runtime_put_sync(dev);
1060
1061 out:
1062         pm_runtime_disable(dev);
1063
1064         clk_put(ctx->lcd_clk);
1065         clk_put(ctx->bus_clk);
1066
1067         iounmap(ctx->regs_mie);
1068         iounmap(ctx->regs);
1069         release_resource(ctx->regs_res);
1070         kfree(ctx->regs_res);
1071         free_irq(ctx->irq, ctx);
1072 #ifdef CONFIG_EXYNOS_IOMMU
1073         iommu_deinit(pdev);
1074 #endif
1075         kfree(ctx);
1076
1077         return 0;
1078 }
1079
1080 #ifdef CONFIG_PM_SLEEP
1081 static int fimd_suspend(struct device *dev)
1082 {
1083         struct fimd_context *ctx = get_fimd_context(dev);
1084
1085         if (pm_runtime_suspended(dev))
1086                 return 0;
1087
1088         /*
1089          * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
1090          * called here, an error would be returned by that interface
1091          * because the usage_count of pm runtime is more than 1.
1092          */
1093         return fimd_power_on(ctx, false);
1094 }
1095
1096 static int fimd_resume(struct device *dev)
1097 {
1098         struct fimd_context *ctx = get_fimd_context(dev);
1099
1100         /*
1101          * if entered to sleep when lcd panel was on, the usage_count
1102          * of pm runtime would still be 1 so in this case, fimd driver
1103          * should be on directly not drawing on pm runtime interface.
1104          */
1105         if (!pm_runtime_suspended(dev))
1106                 return fimd_power_on(ctx, true);
1107
1108         return 0;
1109 }
1110 #endif
1111
1112 #ifdef CONFIG_PM_RUNTIME
1113 static int fimd_runtime_suspend(struct device *dev)
1114 {
1115         struct fimd_context *ctx = get_fimd_context(dev);
1116
1117         DRM_DEBUG_KMS("%s\n", __FILE__);
1118
1119         return fimd_power_on(ctx, false);
1120 }
1121
1122 static int fimd_runtime_resume(struct device *dev)
1123 {
1124         struct fimd_context *ctx = get_fimd_context(dev);
1125
1126         DRM_DEBUG_KMS("%s\n", __FILE__);
1127
1128         return fimd_power_on(ctx, true);
1129 }
1130 #endif
1131
1132 static struct platform_device_id exynos_drm_driver_ids[] = {
1133         {
1134                 .name           = "exynos4-fb",
1135         }, {
1136                 .name           = "exynos5-fb",
1137         },
1138         {},
1139 };
1140 MODULE_DEVICE_TABLE(platform, exynos_drm_driver_ids);
1141
1142 static const struct dev_pm_ops fimd_pm_ops = {
1143         SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
1144         SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
1145 };
1146
1147 struct platform_driver fimd_driver = {
1148         .probe          = fimd_probe,
1149         .remove         = __devexit_p(fimd_remove),
1150         .id_table       = exynos_drm_driver_ids,
1151         .driver         = {
1152                 .name   = "exynos-drm-fimd",
1153                 .owner  = THIS_MODULE,
1154                 .pm     = &fimd_pm_ops,
1155         },
1156 };