xref: /linux/drivers/gpu/drm/exynos/exynos_drm_fimd.c (revision b43ab901d671e3e3cad425ea5e9a3c74e266dcdd)
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_fbdev.h"
27 #include "exynos_drm_crtc.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		bpp;
68 	dma_addr_t		dma_addr;
69 	void __iomem		*vaddr;
70 	unsigned int		buf_offsize;
71 	unsigned int		line_size;	/* bytes */
72 	bool			enabled;
73 };
74 
75 struct fimd_context {
76 	struct exynos_drm_subdrv	subdrv;
77 	int				irq;
78 	struct drm_crtc			*crtc;
79 	struct clk			*bus_clk;
80 	struct clk			*lcd_clk;
81 	struct resource			*regs_res;
82 	void __iomem			*regs;
83 	struct fimd_win_data		win_data[WINDOWS_NR];
84 	unsigned int			clkdiv;
85 	unsigned int			default_win;
86 	unsigned long			irq_flags;
87 	u32				vidcon0;
88 	u32				vidcon1;
89 	bool				suspended;
90 	struct mutex			lock;
91 
92 	struct fb_videomode		*timing;
93 };
94 
95 static bool fimd_display_is_connected(struct device *dev)
96 {
97 	DRM_DEBUG_KMS("%s\n", __FILE__);
98 
99 	/* TODO. */
100 
101 	return true;
102 }
103 
104 static void *fimd_get_timing(struct device *dev)
105 {
106 	struct fimd_context *ctx = get_fimd_context(dev);
107 
108 	DRM_DEBUG_KMS("%s\n", __FILE__);
109 
110 	return ctx->timing;
111 }
112 
113 static int fimd_check_timing(struct device *dev, void *timing)
114 {
115 	DRM_DEBUG_KMS("%s\n", __FILE__);
116 
117 	/* TODO. */
118 
119 	return 0;
120 }
121 
122 static int fimd_display_power_on(struct device *dev, int mode)
123 {
124 	DRM_DEBUG_KMS("%s\n", __FILE__);
125 
126 	/* TODO */
127 
128 	return 0;
129 }
130 
131 static struct exynos_drm_display_ops fimd_display_ops = {
132 	.type = EXYNOS_DISPLAY_TYPE_LCD,
133 	.is_connected = fimd_display_is_connected,
134 	.get_timing = fimd_get_timing,
135 	.check_timing = fimd_check_timing,
136 	.power_on = fimd_display_power_on,
137 };
138 
139 static void fimd_dpms(struct device *subdrv_dev, int mode)
140 {
141 	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
142 
143 	DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
144 
145 	mutex_lock(&ctx->lock);
146 
147 	switch (mode) {
148 	case DRM_MODE_DPMS_ON:
149 		/*
150 		 * enable fimd hardware only if suspended status.
151 		 *
152 		 * P.S. fimd_dpms function would be called at booting time so
153 		 * clk_enable could be called double time.
154 		 */
155 		if (ctx->suspended)
156 			pm_runtime_get_sync(subdrv_dev);
157 		break;
158 	case DRM_MODE_DPMS_STANDBY:
159 	case DRM_MODE_DPMS_SUSPEND:
160 	case DRM_MODE_DPMS_OFF:
161 		pm_runtime_put_sync(subdrv_dev);
162 		break;
163 	default:
164 		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
165 		break;
166 	}
167 
168 	mutex_unlock(&ctx->lock);
169 }
170 
171 static void fimd_apply(struct device *subdrv_dev)
172 {
173 	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
174 	struct exynos_drm_manager *mgr = &ctx->subdrv.manager;
175 	struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
176 	struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
177 	struct fimd_win_data *win_data;
178 	int i;
179 
180 	DRM_DEBUG_KMS("%s\n", __FILE__);
181 
182 	for (i = 0; i < WINDOWS_NR; i++) {
183 		win_data = &ctx->win_data[i];
184 		if (win_data->enabled && (ovl_ops && ovl_ops->commit))
185 			ovl_ops->commit(subdrv_dev, i);
186 	}
187 
188 	if (mgr_ops && mgr_ops->commit)
189 		mgr_ops->commit(subdrv_dev);
190 }
191 
192 static void fimd_commit(struct device *dev)
193 {
194 	struct fimd_context *ctx = get_fimd_context(dev);
195 	struct fb_videomode *timing = ctx->timing;
196 	u32 val;
197 
198 	if (ctx->suspended)
199 		return;
200 
201 	DRM_DEBUG_KMS("%s\n", __FILE__);
202 
203 	/* setup polarity values from machine code. */
204 	writel(ctx->vidcon1, ctx->regs + VIDCON1);
205 
206 	/* setup vertical timing values. */
207 	val = VIDTCON0_VBPD(timing->upper_margin - 1) |
208 	       VIDTCON0_VFPD(timing->lower_margin - 1) |
209 	       VIDTCON0_VSPW(timing->vsync_len - 1);
210 	writel(val, ctx->regs + VIDTCON0);
211 
212 	/* setup horizontal timing values.  */
213 	val = VIDTCON1_HBPD(timing->left_margin - 1) |
214 	       VIDTCON1_HFPD(timing->right_margin - 1) |
215 	       VIDTCON1_HSPW(timing->hsync_len - 1);
216 	writel(val, ctx->regs + VIDTCON1);
217 
218 	/* setup horizontal and vertical display size. */
219 	val = VIDTCON2_LINEVAL(timing->yres - 1) |
220 	       VIDTCON2_HOZVAL(timing->xres - 1);
221 	writel(val, ctx->regs + VIDTCON2);
222 
223 	/* setup clock source, clock divider, enable dma. */
224 	val = ctx->vidcon0;
225 	val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
226 
227 	if (ctx->clkdiv > 1)
228 		val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
229 	else
230 		val &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
231 
232 	/*
233 	 * fields of register with prefix '_F' would be updated
234 	 * at vsync(same as dma start)
235 	 */
236 	val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
237 	writel(val, ctx->regs + VIDCON0);
238 }
239 
240 static int fimd_enable_vblank(struct device *dev)
241 {
242 	struct fimd_context *ctx = get_fimd_context(dev);
243 	u32 val;
244 
245 	DRM_DEBUG_KMS("%s\n", __FILE__);
246 
247 	if (ctx->suspended)
248 		return -EPERM;
249 
250 	if (!test_and_set_bit(0, &ctx->irq_flags)) {
251 		val = readl(ctx->regs + VIDINTCON0);
252 
253 		val |= VIDINTCON0_INT_ENABLE;
254 		val |= VIDINTCON0_INT_FRAME;
255 
256 		val &= ~VIDINTCON0_FRAMESEL0_MASK;
257 		val |= VIDINTCON0_FRAMESEL0_VSYNC;
258 		val &= ~VIDINTCON0_FRAMESEL1_MASK;
259 		val |= VIDINTCON0_FRAMESEL1_NONE;
260 
261 		writel(val, ctx->regs + VIDINTCON0);
262 	}
263 
264 	return 0;
265 }
266 
267 static void fimd_disable_vblank(struct device *dev)
268 {
269 	struct fimd_context *ctx = get_fimd_context(dev);
270 	u32 val;
271 
272 	DRM_DEBUG_KMS("%s\n", __FILE__);
273 
274 	if (ctx->suspended)
275 		return;
276 
277 	if (test_and_clear_bit(0, &ctx->irq_flags)) {
278 		val = readl(ctx->regs + VIDINTCON0);
279 
280 		val &= ~VIDINTCON0_INT_FRAME;
281 		val &= ~VIDINTCON0_INT_ENABLE;
282 
283 		writel(val, ctx->regs + VIDINTCON0);
284 	}
285 }
286 
287 static struct exynos_drm_manager_ops fimd_manager_ops = {
288 	.dpms = fimd_dpms,
289 	.apply = fimd_apply,
290 	.commit = fimd_commit,
291 	.enable_vblank = fimd_enable_vblank,
292 	.disable_vblank = fimd_disable_vblank,
293 };
294 
295 static void fimd_win_mode_set(struct device *dev,
296 			      struct exynos_drm_overlay *overlay)
297 {
298 	struct fimd_context *ctx = get_fimd_context(dev);
299 	struct fimd_win_data *win_data;
300 	int win;
301 	unsigned long offset;
302 
303 	DRM_DEBUG_KMS("%s\n", __FILE__);
304 
305 	if (!overlay) {
306 		dev_err(dev, "overlay is NULL\n");
307 		return;
308 	}
309 
310 	win = overlay->zpos;
311 	if (win == DEFAULT_ZPOS)
312 		win = ctx->default_win;
313 
314 	if (win < 0 || win > WINDOWS_NR)
315 		return;
316 
317 	offset = overlay->fb_x * (overlay->bpp >> 3);
318 	offset += overlay->fb_y * overlay->pitch;
319 
320 	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
321 
322 	win_data = &ctx->win_data[win];
323 
324 	win_data->offset_x = overlay->crtc_x;
325 	win_data->offset_y = overlay->crtc_y;
326 	win_data->ovl_width = overlay->crtc_width;
327 	win_data->ovl_height = overlay->crtc_height;
328 	win_data->fb_width = overlay->fb_width;
329 	win_data->fb_height = overlay->fb_height;
330 	win_data->dma_addr = overlay->dma_addr[0] + offset;
331 	win_data->vaddr = overlay->vaddr[0] + offset;
332 	win_data->bpp = overlay->bpp;
333 	win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
334 				(overlay->bpp >> 3);
335 	win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
336 
337 	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
338 			win_data->offset_x, win_data->offset_y);
339 	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
340 			win_data->ovl_width, win_data->ovl_height);
341 	DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
342 			(unsigned long)win_data->dma_addr,
343 			(unsigned long)win_data->vaddr);
344 	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
345 			overlay->fb_width, overlay->crtc_width);
346 }
347 
348 static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
349 {
350 	struct fimd_context *ctx = get_fimd_context(dev);
351 	struct fimd_win_data *win_data = &ctx->win_data[win];
352 	unsigned long val;
353 
354 	DRM_DEBUG_KMS("%s\n", __FILE__);
355 
356 	val = WINCONx_ENWIN;
357 
358 	switch (win_data->bpp) {
359 	case 1:
360 		val |= WINCON0_BPPMODE_1BPP;
361 		val |= WINCONx_BITSWP;
362 		val |= WINCONx_BURSTLEN_4WORD;
363 		break;
364 	case 2:
365 		val |= WINCON0_BPPMODE_2BPP;
366 		val |= WINCONx_BITSWP;
367 		val |= WINCONx_BURSTLEN_8WORD;
368 		break;
369 	case 4:
370 		val |= WINCON0_BPPMODE_4BPP;
371 		val |= WINCONx_BITSWP;
372 		val |= WINCONx_BURSTLEN_8WORD;
373 		break;
374 	case 8:
375 		val |= WINCON0_BPPMODE_8BPP_PALETTE;
376 		val |= WINCONx_BURSTLEN_8WORD;
377 		val |= WINCONx_BYTSWP;
378 		break;
379 	case 16:
380 		val |= WINCON0_BPPMODE_16BPP_565;
381 		val |= WINCONx_HAWSWP;
382 		val |= WINCONx_BURSTLEN_16WORD;
383 		break;
384 	case 24:
385 		val |= WINCON0_BPPMODE_24BPP_888;
386 		val |= WINCONx_WSWP;
387 		val |= WINCONx_BURSTLEN_16WORD;
388 		break;
389 	case 32:
390 		val |= WINCON1_BPPMODE_28BPP_A4888
391 			| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
392 		val |= WINCONx_WSWP;
393 		val |= WINCONx_BURSTLEN_16WORD;
394 		break;
395 	default:
396 		DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
397 
398 		val |= WINCON0_BPPMODE_24BPP_888;
399 		val |= WINCONx_WSWP;
400 		val |= WINCONx_BURSTLEN_16WORD;
401 		break;
402 	}
403 
404 	DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
405 
406 	writel(val, ctx->regs + WINCON(win));
407 }
408 
409 static void fimd_win_set_colkey(struct device *dev, unsigned int win)
410 {
411 	struct fimd_context *ctx = get_fimd_context(dev);
412 	unsigned int keycon0 = 0, keycon1 = 0;
413 
414 	DRM_DEBUG_KMS("%s\n", __FILE__);
415 
416 	keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
417 			WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
418 
419 	keycon1 = WxKEYCON1_COLVAL(0xffffffff);
420 
421 	writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
422 	writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
423 }
424 
425 static void fimd_win_commit(struct device *dev, int zpos)
426 {
427 	struct fimd_context *ctx = get_fimd_context(dev);
428 	struct fimd_win_data *win_data;
429 	int win = zpos;
430 	unsigned long val, alpha, size;
431 
432 	DRM_DEBUG_KMS("%s\n", __FILE__);
433 
434 	if (ctx->suspended)
435 		return;
436 
437 	if (win == DEFAULT_ZPOS)
438 		win = ctx->default_win;
439 
440 	if (win < 0 || win > WINDOWS_NR)
441 		return;
442 
443 	win_data = &ctx->win_data[win];
444 
445 	/*
446 	 * SHADOWCON register is used for enabling timing.
447 	 *
448 	 * for example, once only width value of a register is set,
449 	 * if the dma is started then fimd hardware could malfunction so
450 	 * with protect window setting, the register fields with prefix '_F'
451 	 * wouldn't be updated at vsync also but updated once unprotect window
452 	 * is set.
453 	 */
454 
455 	/* protect windows */
456 	val = readl(ctx->regs + SHADOWCON);
457 	val |= SHADOWCON_WINx_PROTECT(win);
458 	writel(val, ctx->regs + SHADOWCON);
459 
460 	/* buffer start address */
461 	val = (unsigned long)win_data->dma_addr;
462 	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
463 
464 	/* buffer end address */
465 	size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
466 	val = (unsigned long)(win_data->dma_addr + size);
467 	writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
468 
469 	DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
470 			(unsigned long)win_data->dma_addr, val, size);
471 	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
472 			win_data->ovl_width, win_data->ovl_height);
473 
474 	/* buffer size */
475 	val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
476 		VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size);
477 	writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
478 
479 	/* OSD position */
480 	val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
481 		VIDOSDxA_TOPLEFT_Y(win_data->offset_y);
482 	writel(val, ctx->regs + VIDOSD_A(win));
483 
484 	val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x +
485 					win_data->ovl_width - 1) |
486 		VIDOSDxB_BOTRIGHT_Y(win_data->offset_y +
487 					win_data->ovl_height - 1);
488 	writel(val, ctx->regs + VIDOSD_B(win));
489 
490 	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
491 			win_data->offset_x, win_data->offset_y,
492 			win_data->offset_x + win_data->ovl_width - 1,
493 			win_data->offset_y + win_data->ovl_height - 1);
494 
495 	/* hardware window 0 doesn't support alpha channel. */
496 	if (win != 0) {
497 		/* OSD alpha */
498 		alpha = VIDISD14C_ALPHA1_R(0xf) |
499 			VIDISD14C_ALPHA1_G(0xf) |
500 			VIDISD14C_ALPHA1_B(0xf);
501 
502 		writel(alpha, ctx->regs + VIDOSD_C(win));
503 	}
504 
505 	/* OSD size */
506 	if (win != 3 && win != 4) {
507 		u32 offset = VIDOSD_D(win);
508 		if (win == 0)
509 			offset = VIDOSD_C_SIZE_W0;
510 		val = win_data->ovl_width * win_data->ovl_height;
511 		writel(val, ctx->regs + offset);
512 
513 		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
514 	}
515 
516 	fimd_win_set_pixfmt(dev, win);
517 
518 	/* hardware window 0 doesn't support color key. */
519 	if (win != 0)
520 		fimd_win_set_colkey(dev, win);
521 
522 	/* wincon */
523 	val = readl(ctx->regs + WINCON(win));
524 	val |= WINCONx_ENWIN;
525 	writel(val, ctx->regs + WINCON(win));
526 
527 	/* Enable DMA channel and unprotect windows */
528 	val = readl(ctx->regs + SHADOWCON);
529 	val |= SHADOWCON_CHx_ENABLE(win);
530 	val &= ~SHADOWCON_WINx_PROTECT(win);
531 	writel(val, ctx->regs + SHADOWCON);
532 
533 	win_data->enabled = true;
534 }
535 
536 static void fimd_win_disable(struct device *dev, int zpos)
537 {
538 	struct fimd_context *ctx = get_fimd_context(dev);
539 	struct fimd_win_data *win_data;
540 	int win = zpos;
541 	u32 val;
542 
543 	DRM_DEBUG_KMS("%s\n", __FILE__);
544 
545 	if (win == DEFAULT_ZPOS)
546 		win = ctx->default_win;
547 
548 	if (win < 0 || win > WINDOWS_NR)
549 		return;
550 
551 	win_data = &ctx->win_data[win];
552 
553 	/* protect windows */
554 	val = readl(ctx->regs + SHADOWCON);
555 	val |= SHADOWCON_WINx_PROTECT(win);
556 	writel(val, ctx->regs + SHADOWCON);
557 
558 	/* wincon */
559 	val = readl(ctx->regs + WINCON(win));
560 	val &= ~WINCONx_ENWIN;
561 	writel(val, ctx->regs + WINCON(win));
562 
563 	/* unprotect windows */
564 	val = readl(ctx->regs + SHADOWCON);
565 	val &= ~SHADOWCON_CHx_ENABLE(win);
566 	val &= ~SHADOWCON_WINx_PROTECT(win);
567 	writel(val, ctx->regs + SHADOWCON);
568 
569 	win_data->enabled = false;
570 }
571 
572 static struct exynos_drm_overlay_ops fimd_overlay_ops = {
573 	.mode_set = fimd_win_mode_set,
574 	.commit = fimd_win_commit,
575 	.disable = fimd_win_disable,
576 };
577 
578 static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
579 {
580 	struct exynos_drm_private *dev_priv = drm_dev->dev_private;
581 	struct drm_pending_vblank_event *e, *t;
582 	struct timeval now;
583 	unsigned long flags;
584 	bool is_checked = false;
585 
586 	spin_lock_irqsave(&drm_dev->event_lock, flags);
587 
588 	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
589 			base.link) {
590 		/* if event's pipe isn't same as crtc then ignore it. */
591 		if (crtc != e->pipe)
592 			continue;
593 
594 		is_checked = true;
595 
596 		do_gettimeofday(&now);
597 		e->event.sequence = 0;
598 		e->event.tv_sec = now.tv_sec;
599 		e->event.tv_usec = now.tv_usec;
600 
601 		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
602 		wake_up_interruptible(&e->base.file_priv->event_wait);
603 	}
604 
605 	if (is_checked) {
606 		drm_vblank_put(drm_dev, crtc);
607 
608 		/*
609 		 * don't off vblank if vblank_disable_allowed is 1,
610 		 * because vblank would be off by timer handler.
611 		 */
612 		if (!drm_dev->vblank_disable_allowed)
613 			drm_vblank_off(drm_dev, crtc);
614 	}
615 
616 	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
617 }
618 
619 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
620 {
621 	struct fimd_context *ctx = (struct fimd_context *)dev_id;
622 	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
623 	struct drm_device *drm_dev = subdrv->drm_dev;
624 	struct exynos_drm_manager *manager = &subdrv->manager;
625 	u32 val;
626 
627 	val = readl(ctx->regs + VIDINTCON1);
628 
629 	if (val & VIDINTCON1_INT_FRAME)
630 		/* VSYNC interrupt */
631 		writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
632 
633 	/* check the crtc is detached already from encoder */
634 	if (manager->pipe < 0)
635 		goto out;
636 
637 	drm_handle_vblank(drm_dev, manager->pipe);
638 	fimd_finish_pageflip(drm_dev, manager->pipe);
639 
640 out:
641 	return IRQ_HANDLED;
642 }
643 
644 static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
645 {
646 	DRM_DEBUG_KMS("%s\n", __FILE__);
647 
648 	/*
649 	 * enable drm irq mode.
650 	 * - with irq_enabled = 1, we can use the vblank feature.
651 	 *
652 	 * P.S. note that we wouldn't use drm irq handler but
653 	 *	just specific driver own one instead because
654 	 *	drm framework supports only one irq handler.
655 	 */
656 	drm_dev->irq_enabled = 1;
657 
658 	/*
659 	 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
660 	 * by drm timer once a current process gives up ownership of
661 	 * vblank event.(after drm_vblank_put function is called)
662 	 */
663 	drm_dev->vblank_disable_allowed = 1;
664 
665 	return 0;
666 }
667 
668 static void fimd_subdrv_remove(struct drm_device *drm_dev)
669 {
670 	DRM_DEBUG_KMS("%s\n", __FILE__);
671 
672 	/* TODO. */
673 }
674 
675 static int fimd_calc_clkdiv(struct fimd_context *ctx,
676 			    struct fb_videomode *timing)
677 {
678 	unsigned long clk = clk_get_rate(ctx->lcd_clk);
679 	u32 retrace;
680 	u32 clkdiv;
681 	u32 best_framerate = 0;
682 	u32 framerate;
683 
684 	DRM_DEBUG_KMS("%s\n", __FILE__);
685 
686 	retrace = timing->left_margin + timing->hsync_len +
687 				timing->right_margin + timing->xres;
688 	retrace *= timing->upper_margin + timing->vsync_len +
689 				timing->lower_margin + timing->yres;
690 
691 	/* default framerate is 60Hz */
692 	if (!timing->refresh)
693 		timing->refresh = 60;
694 
695 	clk /= retrace;
696 
697 	for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
698 		int tmp;
699 
700 		/* get best framerate */
701 		framerate = clk / clkdiv;
702 		tmp = timing->refresh - framerate;
703 		if (tmp < 0) {
704 			best_framerate = framerate;
705 			continue;
706 		} else {
707 			if (!best_framerate)
708 				best_framerate = framerate;
709 			else if (tmp < (best_framerate - framerate))
710 				best_framerate = framerate;
711 			break;
712 		}
713 	}
714 
715 	return clkdiv;
716 }
717 
718 static void fimd_clear_win(struct fimd_context *ctx, int win)
719 {
720 	u32 val;
721 
722 	DRM_DEBUG_KMS("%s\n", __FILE__);
723 
724 	writel(0, ctx->regs + WINCON(win));
725 	writel(0, ctx->regs + VIDOSD_A(win));
726 	writel(0, ctx->regs + VIDOSD_B(win));
727 	writel(0, ctx->regs + VIDOSD_C(win));
728 
729 	if (win == 1 || win == 2)
730 		writel(0, ctx->regs + VIDOSD_D(win));
731 
732 	val = readl(ctx->regs + SHADOWCON);
733 	val &= ~SHADOWCON_WINx_PROTECT(win);
734 	writel(val, ctx->regs + SHADOWCON);
735 }
736 
737 static int __devinit fimd_probe(struct platform_device *pdev)
738 {
739 	struct device *dev = &pdev->dev;
740 	struct fimd_context *ctx;
741 	struct exynos_drm_subdrv *subdrv;
742 	struct exynos_drm_fimd_pdata *pdata;
743 	struct fb_videomode *timing;
744 	struct resource *res;
745 	int win;
746 	int ret = -EINVAL;
747 
748 	DRM_DEBUG_KMS("%s\n", __FILE__);
749 
750 	pdata = pdev->dev.platform_data;
751 	if (!pdata) {
752 		dev_err(dev, "no platform data specified\n");
753 		return -EINVAL;
754 	}
755 
756 	timing = &pdata->timing;
757 	if (!timing) {
758 		dev_err(dev, "timing is null.\n");
759 		return -EINVAL;
760 	}
761 
762 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
763 	if (!ctx)
764 		return -ENOMEM;
765 
766 	ctx->bus_clk = clk_get(dev, "fimd");
767 	if (IS_ERR(ctx->bus_clk)) {
768 		dev_err(dev, "failed to get bus clock\n");
769 		ret = PTR_ERR(ctx->bus_clk);
770 		goto err_clk_get;
771 	}
772 
773 	clk_enable(ctx->bus_clk);
774 
775 	ctx->lcd_clk = clk_get(dev, "sclk_fimd");
776 	if (IS_ERR(ctx->lcd_clk)) {
777 		dev_err(dev, "failed to get lcd clock\n");
778 		ret = PTR_ERR(ctx->lcd_clk);
779 		goto err_bus_clk;
780 	}
781 
782 	clk_enable(ctx->lcd_clk);
783 
784 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
785 	if (!res) {
786 		dev_err(dev, "failed to find registers\n");
787 		ret = -ENOENT;
788 		goto err_clk;
789 	}
790 
791 	ctx->regs_res = request_mem_region(res->start, resource_size(res),
792 					   dev_name(dev));
793 	if (!ctx->regs_res) {
794 		dev_err(dev, "failed to claim register region\n");
795 		ret = -ENOENT;
796 		goto err_clk;
797 	}
798 
799 	ctx->regs = ioremap(res->start, resource_size(res));
800 	if (!ctx->regs) {
801 		dev_err(dev, "failed to map registers\n");
802 		ret = -ENXIO;
803 		goto err_req_region_io;
804 	}
805 
806 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
807 	if (!res) {
808 		dev_err(dev, "irq request failed.\n");
809 		goto err_req_region_irq;
810 	}
811 
812 	ctx->irq = res->start;
813 
814 	ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx);
815 	if (ret < 0) {
816 		dev_err(dev, "irq request failed.\n");
817 		goto err_req_irq;
818 	}
819 
820 	ctx->clkdiv = fimd_calc_clkdiv(ctx, timing);
821 	ctx->vidcon0 = pdata->vidcon0;
822 	ctx->vidcon1 = pdata->vidcon1;
823 	ctx->default_win = pdata->default_win;
824 	ctx->timing = timing;
825 
826 	timing->pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
827 
828 	DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
829 			timing->pixclock, ctx->clkdiv);
830 
831 	subdrv = &ctx->subdrv;
832 
833 	subdrv->probe = fimd_subdrv_probe;
834 	subdrv->remove = fimd_subdrv_remove;
835 	subdrv->manager.pipe = -1;
836 	subdrv->manager.ops = &fimd_manager_ops;
837 	subdrv->manager.overlay_ops = &fimd_overlay_ops;
838 	subdrv->manager.display_ops = &fimd_display_ops;
839 	subdrv->manager.dev = dev;
840 
841 	mutex_init(&ctx->lock);
842 
843 	platform_set_drvdata(pdev, ctx);
844 
845 	pm_runtime_set_active(dev);
846 	pm_runtime_enable(dev);
847 	pm_runtime_get_sync(dev);
848 
849 	for (win = 0; win < WINDOWS_NR; win++)
850 		fimd_clear_win(ctx, win);
851 
852 	exynos_drm_subdrv_register(subdrv);
853 
854 	return 0;
855 
856 err_req_irq:
857 err_req_region_irq:
858 	iounmap(ctx->regs);
859 
860 err_req_region_io:
861 	release_resource(ctx->regs_res);
862 	kfree(ctx->regs_res);
863 
864 err_clk:
865 	clk_disable(ctx->lcd_clk);
866 	clk_put(ctx->lcd_clk);
867 
868 err_bus_clk:
869 	clk_disable(ctx->bus_clk);
870 	clk_put(ctx->bus_clk);
871 
872 err_clk_get:
873 	kfree(ctx);
874 	return ret;
875 }
876 
877 static int __devexit fimd_remove(struct platform_device *pdev)
878 {
879 	struct device *dev = &pdev->dev;
880 	struct fimd_context *ctx = platform_get_drvdata(pdev);
881 
882 	DRM_DEBUG_KMS("%s\n", __FILE__);
883 
884 	exynos_drm_subdrv_unregister(&ctx->subdrv);
885 
886 	if (ctx->suspended)
887 		goto out;
888 
889 	clk_disable(ctx->lcd_clk);
890 	clk_disable(ctx->bus_clk);
891 
892 	pm_runtime_set_suspended(dev);
893 	pm_runtime_put_sync(dev);
894 
895 out:
896 	pm_runtime_disable(dev);
897 
898 	clk_put(ctx->lcd_clk);
899 	clk_put(ctx->bus_clk);
900 
901 	iounmap(ctx->regs);
902 	release_resource(ctx->regs_res);
903 	kfree(ctx->regs_res);
904 	free_irq(ctx->irq, ctx);
905 
906 	kfree(ctx);
907 
908 	return 0;
909 }
910 
911 #ifdef CONFIG_PM_SLEEP
912 static int fimd_suspend(struct device *dev)
913 {
914 	int ret;
915 
916 	if (pm_runtime_suspended(dev))
917 		return 0;
918 
919 	ret = pm_runtime_suspend(dev);
920 	if (ret < 0)
921 		return ret;
922 
923 	return 0;
924 }
925 
926 static int fimd_resume(struct device *dev)
927 {
928 	int ret;
929 
930 	ret = pm_runtime_resume(dev);
931 	if (ret < 0) {
932 		DRM_ERROR("failed to resume runtime pm.\n");
933 		return ret;
934 	}
935 
936 	pm_runtime_disable(dev);
937 
938 	ret = pm_runtime_set_active(dev);
939 	if (ret < 0) {
940 		DRM_ERROR("failed to active runtime pm.\n");
941 		pm_runtime_enable(dev);
942 		pm_runtime_suspend(dev);
943 		return ret;
944 	}
945 
946 	pm_runtime_enable(dev);
947 
948 	return 0;
949 }
950 #endif
951 
952 #ifdef CONFIG_PM_RUNTIME
953 static int fimd_runtime_suspend(struct device *dev)
954 {
955 	struct fimd_context *ctx = get_fimd_context(dev);
956 
957 	DRM_DEBUG_KMS("%s\n", __FILE__);
958 
959 	clk_disable(ctx->lcd_clk);
960 	clk_disable(ctx->bus_clk);
961 
962 	ctx->suspended = true;
963 	return 0;
964 }
965 
966 static int fimd_runtime_resume(struct device *dev)
967 {
968 	struct fimd_context *ctx = get_fimd_context(dev);
969 	int ret;
970 
971 	DRM_DEBUG_KMS("%s\n", __FILE__);
972 
973 	ret = clk_enable(ctx->bus_clk);
974 	if (ret < 0)
975 		return ret;
976 
977 	ret = clk_enable(ctx->lcd_clk);
978 	if  (ret < 0) {
979 		clk_disable(ctx->bus_clk);
980 		return ret;
981 	}
982 
983 	ctx->suspended = false;
984 
985 	/* if vblank was enabled status, enable it again. */
986 	if (test_and_clear_bit(0, &ctx->irq_flags))
987 		fimd_enable_vblank(dev);
988 
989 	fimd_apply(dev);
990 
991 	return 0;
992 }
993 #endif
994 
995 static const struct dev_pm_ops fimd_pm_ops = {
996 	SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
997 	SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
998 };
999 
1000 static struct platform_driver fimd_driver = {
1001 	.probe		= fimd_probe,
1002 	.remove		= __devexit_p(fimd_remove),
1003 	.driver		= {
1004 		.name	= "exynos4-fb",
1005 		.owner	= THIS_MODULE,
1006 		.pm	= &fimd_pm_ops,
1007 	},
1008 };
1009 
1010 static int __init fimd_init(void)
1011 {
1012 	return platform_driver_register(&fimd_driver);
1013 }
1014 
1015 static void __exit fimd_exit(void)
1016 {
1017 	platform_driver_unregister(&fimd_driver);
1018 }
1019 
1020 module_init(fimd_init);
1021 module_exit(fimd_exit);
1022 
1023 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
1024 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
1025 MODULE_DESCRIPTION("Samsung DRM FIMD Driver");
1026 MODULE_LICENSE("GPL");
1027