drm/exynos: fimd: Fix compilation warning
[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
785         DRM_DEBUG_KMS("%s\n", __FILE__);
786
787         if (enable) {
788                 int ret;
789
790                 ret = clk_enable(ctx->bus_clk);
791                 if (ret < 0)
792                         return ret;
793
794                 ret = clk_enable(ctx->lcd_clk);
795                 if  (ret < 0) {
796                         clk_disable(ctx->bus_clk);
797                         return ret;
798                 }
799
800                 ctx->suspended = false;
801
802                 /* if vblank was enabled status, enable it again. */
803                 if (test_and_clear_bit(0, &ctx->irq_flags))
804                         fimd_enable_vblank(dev);
805
806                 fimd_apply(dev);
807
808                 if (pdata->panel_type == DP_LCD)
809                         writel(MIE_CLK_ENABLE, ctx->regs + DPCLKCON);
810         } else {
811                 clk_disable(ctx->lcd_clk);
812                 clk_disable(ctx->bus_clk);
813
814                 ctx->suspended = true;
815
816                 if (pdata->panel_type == DP_LCD)
817                         writel(0, ctx->regs + DPCLKCON);
818         }
819
820         return 0;
821 }
822
823 #ifdef CONFIG_EXYNOS_IOMMU
824 static int iommu_init(struct platform_device *pdev)
825 {
826         struct platform_device *pds;
827
828         pds = find_sysmmu_dt(pdev, "sysmmu");
829         if (pds==NULL) {
830                 printk(KERN_ERR "No sysmmu found\n");
831                 return -1;
832         }
833
834         platform_set_sysmmu(&pds->dev, &pdev->dev);
835         exynos_drm_common_mapping = s5p_create_iommu_mapping(&pdev->dev,
836                                         0x20000000, SZ_256M, 4,
837                                         exynos_drm_common_mapping);
838
839         if (!exynos_drm_common_mapping) {
840                 printk(KERN_ERR "IOMMU mapping not created\n");
841                 return -1;
842         }
843
844         return 0;
845 }
846
847 static void iommu_deinit(struct platform_device *pdev)
848 {
849         s5p_destroy_iommu_mapping(&pdev->dev);
850         DRM_DEBUG("released the IOMMU mapping\n");
851
852         return;
853 }
854 #endif
855
856 static int __devinit fimd_probe(struct platform_device *pdev)
857 {
858         struct device *dev = &pdev->dev;
859         struct fimd_context *ctx;
860         struct exynos_drm_subdrv *subdrv;
861         struct exynos_drm_fimd_pdata *pdata;
862         struct exynos_drm_panel_info *panel;
863         struct resource *res;
864         struct clk *clk_parent;
865         int win,i;
866         int ret = -EINVAL;
867
868 #ifdef CONFIG_EXYNOS_IOMMU
869         ret = iommu_init(pdev);
870         if (ret < 0) {
871                 dev_err(dev, "failed to initialize IOMMU\n");
872                 return -ENODEV;
873         }
874 #endif
875         DRM_DEBUG_KMS("%s\n", __FILE__);
876
877         pdata = pdev->dev.platform_data;
878         if (!pdata) {
879                 dev_err(dev, "no platform data specified\n");
880                 return -EINVAL;
881         }
882
883         panel = pdata->panel;
884         if (!panel) {
885                 dev_err(dev, "panel is null.\n");
886                 return -EINVAL;
887         }
888
889         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
890         if (!ctx)
891                 return -ENOMEM;
892
893         ctx->bus_clk = clk_get(dev, "fimd");
894         if (IS_ERR(ctx->bus_clk)) {
895                 dev_err(dev, "failed to get bus clock\n");
896                 ret = PTR_ERR(ctx->bus_clk);
897                 goto err_clk_get;
898         }
899
900         ctx->lcd_clk = clk_get(dev, "sclk_fimd");
901         if (IS_ERR(ctx->lcd_clk)) {
902                 dev_err(dev, "failed to get lcd clock\n");
903                 ret = PTR_ERR(ctx->lcd_clk);
904                 goto err_bus_clk;
905         }
906
907         clk_parent = clk_get(NULL, "sclk_vpll");
908         if (IS_ERR(clk_parent)) {
909                 ret = PTR_ERR(clk_parent);
910                 goto err_clk;
911         }
912
913         if (clk_set_parent(ctx->lcd_clk, clk_parent)) {
914                 ret = PTR_ERR(ctx->lcd_clk);
915                 goto err_clk;
916         }
917
918         if (clk_set_rate(ctx->lcd_clk, pdata->clock_rate)) {
919                 ret = PTR_ERR(ctx->lcd_clk);
920                 goto err_clk;
921         }
922
923         clk_put(clk_parent);
924
925         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
926         if (!res) {
927                 dev_err(dev, "failed to find registers\n");
928                 ret = -ENOENT;
929                 goto err_clk;
930         }
931
932         ctx->regs_res = request_mem_region(res->start, resource_size(res),
933                                            dev_name(dev));
934         if (!ctx->regs_res) {
935                 dev_err(dev, "failed to claim register region\n");
936                 ret = -ENOENT;
937                 goto err_clk;
938         }
939
940         ctx->regs = ioremap(res->start, resource_size(res));
941         if (!ctx->regs) {
942                 dev_err(dev, "failed to map registers\n");
943                 ret = -ENXIO;
944                 goto err_req_region_io;
945         }
946
947         ctx->regs_mie = ioremap(MIE_BASE_ADDRESS, 0x400);
948         if (!ctx->regs_mie) {
949                 dev_err(dev, "failed to map registers\n");
950                 ret = -ENXIO;
951                 goto err_req_region_io_mie;
952         }
953
954         res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
955         if (!res) {
956                 dev_err(dev, "irq request failed.\n");
957                 goto err_req_region_irq;
958         }
959
960         ctx->irq = res->start;
961
962         ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx);
963         if (ret < 0) {
964                 dev_err(dev, "irq request failed.\n");
965                 goto err_req_irq;
966         }
967
968         ctx->vidcon0 = pdata->vidcon0;
969         ctx->vidcon1 = pdata->vidcon1;
970         ctx->default_win = pdata->default_win;
971         ctx->panel = panel;
972
973         subdrv = &ctx->subdrv;
974
975         subdrv->dev = dev;
976         subdrv->manager = &fimd_manager;
977         subdrv->probe = fimd_subdrv_probe;
978         subdrv->remove = fimd_subdrv_remove;
979
980         mutex_init(&ctx->lock);
981
982         platform_set_drvdata(pdev, ctx);
983
984         pm_runtime_enable(dev);
985         pm_runtime_get_sync(dev);
986
987         for (i = 0;i < MAX_NR_PANELS;i++) {
988                 if(panel[i].timing.xres == -1 && panel[i].timing.yres == -1)
989                         break;
990
991                 ctx->clkdiv[i] = fimd_calc_clkdiv(ctx, &panel[i].timing);
992                 panel[i].timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv[i];
993                 DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n for panel[%d]",
994                                 panel[i].timing.pixclock, ctx->clkdiv[i],i);
995         }
996
997         for (win = 0; win < WINDOWS_NR; win++)
998                 fimd_clear_win(ctx, win);
999
1000         if (pdata->panel_type == DP_LCD)
1001                 writel(MIE_CLK_ENABLE, ctx->regs + DPCLKCON);
1002
1003         exynos_drm_subdrv_register(subdrv);
1004
1005         return 0;
1006
1007 err_req_irq:
1008 err_req_region_irq:
1009         iounmap(ctx->regs_mie);
1010
1011 err_req_region_io_mie:
1012         iounmap(ctx->regs);
1013
1014 err_req_region_io:
1015         release_resource(ctx->regs_res);
1016         kfree(ctx->regs_res);
1017
1018 err_clk:
1019         clk_disable(ctx->lcd_clk);
1020         clk_put(ctx->lcd_clk);
1021
1022 err_bus_clk:
1023         clk_disable(ctx->bus_clk);
1024         clk_put(ctx->bus_clk);
1025
1026 err_clk_get:
1027 #ifdef CONFIG_EXYNOS_IOMMU
1028         iommu_deinit(pdev);
1029 #endif
1030         kfree(ctx);
1031         return ret;
1032 }
1033
1034 static int __devexit fimd_remove(struct platform_device *pdev)
1035 {
1036         struct device *dev = &pdev->dev;
1037         struct fimd_context *ctx = platform_get_drvdata(pdev);
1038
1039         DRM_DEBUG_KMS("%s\n", __FILE__);
1040
1041         exynos_drm_subdrv_unregister(&ctx->subdrv);
1042
1043         if (ctx->suspended)
1044                 goto out;
1045
1046         clk_disable(ctx->lcd_clk);
1047         clk_disable(ctx->bus_clk);
1048
1049         pm_runtime_set_suspended(dev);
1050         pm_runtime_put_sync(dev);
1051
1052 out:
1053         pm_runtime_disable(dev);
1054
1055         clk_put(ctx->lcd_clk);
1056         clk_put(ctx->bus_clk);
1057
1058         iounmap(ctx->regs_mie);
1059         iounmap(ctx->regs);
1060         release_resource(ctx->regs_res);
1061         kfree(ctx->regs_res);
1062         free_irq(ctx->irq, ctx);
1063 #ifdef CONFIG_EXYNOS_IOMMU
1064         iommu_deinit(pdev);
1065 #endif
1066         kfree(ctx);
1067
1068         return 0;
1069 }
1070
1071 #ifdef CONFIG_PM_SLEEP
1072 static int fimd_suspend(struct device *dev)
1073 {
1074         struct fimd_context *ctx = get_fimd_context(dev);
1075
1076         if (pm_runtime_suspended(dev))
1077                 return 0;
1078
1079         /*
1080          * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
1081          * called here, an error would be returned by that interface
1082          * because the usage_count of pm runtime is more than 1.
1083          */
1084         return fimd_power_on(ctx, false);
1085 }
1086
1087 static int fimd_resume(struct device *dev)
1088 {
1089         struct fimd_context *ctx = get_fimd_context(dev);
1090
1091         /*
1092          * if entered to sleep when lcd panel was on, the usage_count
1093          * of pm runtime would still be 1 so in this case, fimd driver
1094          * should be on directly not drawing on pm runtime interface.
1095          */
1096         if (!pm_runtime_suspended(dev))
1097                 return fimd_power_on(ctx, true);
1098
1099         return 0;
1100 }
1101 #endif
1102
1103 #ifdef CONFIG_PM_RUNTIME
1104 static int fimd_runtime_suspend(struct device *dev)
1105 {
1106         struct fimd_context *ctx = get_fimd_context(dev);
1107
1108         DRM_DEBUG_KMS("%s\n", __FILE__);
1109
1110         return fimd_power_on(ctx, false);
1111 }
1112
1113 static int fimd_runtime_resume(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, true);
1120 }
1121 #endif
1122
1123 static struct platform_device_id exynos_drm_driver_ids[] = {
1124         {
1125                 .name           = "exynos4-fb",
1126         }, {
1127                 .name           = "exynos5-fb",
1128         },
1129         {},
1130 };
1131 MODULE_DEVICE_TABLE(platform, exynos_drm_driver_ids);
1132
1133 static const struct dev_pm_ops fimd_pm_ops = {
1134         SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
1135         SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
1136 };
1137
1138 struct platform_driver fimd_driver = {
1139         .probe          = fimd_probe,
1140         .remove         = __devexit_p(fimd_remove),
1141         .id_table       = exynos_drm_driver_ids,
1142         .driver         = {
1143                 .name   = "exynos-drm-fimd",
1144                 .owner  = THIS_MODULE,
1145                 .pm     = &fimd_pm_ops,
1146         },
1147 };