xref: /linux/drivers/gpu/drm/exynos/exynos5433_drm_decon.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
1 /* drivers/gpu/drm/exynos5433_drm_decon.c
2  *
3  * Copyright (C) 2015 Samsung Electronics Co.Ltd
4  * Authors:
5  *	Joonyoung Shim <jy0922.shim@samsung.com>
6  *	Hyungwon Hwang <human.hwang@samsung.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundationr
11  */
12 
13 #include <linux/platform_device.h>
14 #include <linux/clk.h>
15 #include <linux/component.h>
16 #include <linux/of_gpio.h>
17 #include <linux/pm_runtime.h>
18 
19 #include <video/exynos5433_decon.h>
20 
21 #include "exynos_drm_drv.h"
22 #include "exynos_drm_crtc.h"
23 #include "exynos_drm_plane.h"
24 #include "exynos_drm_iommu.h"
25 
26 #define WINDOWS_NR	3
27 #define MIN_FB_WIDTH_FOR_16WORD_BURST	128
28 
29 struct decon_context {
30 	struct device			*dev;
31 	struct drm_device		*drm_dev;
32 	struct exynos_drm_crtc		*crtc;
33 	struct exynos_drm_plane		planes[WINDOWS_NR];
34 	void __iomem			*addr;
35 	struct clk			*clks[6];
36 	unsigned int			default_win;
37 	unsigned long			irq_flags;
38 	int				pipe;
39 	bool				suspended;
40 
41 #define BIT_CLKS_ENABLED		0
42 #define BIT_IRQS_ENABLED		1
43 	unsigned long			enabled;
44 	bool				i80_if;
45 	atomic_t			win_updated;
46 };
47 
48 static const char * const decon_clks_name[] = {
49 	"aclk_decon",
50 	"aclk_smmu_decon0x",
51 	"aclk_xiu_decon0x",
52 	"pclk_smmu_decon0x",
53 	"sclk_decon_vclk",
54 	"sclk_decon_eclk",
55 };
56 
57 static const uint32_t decon_formats[] = {
58 	DRM_FORMAT_XRGB1555,
59 	DRM_FORMAT_RGB565,
60 	DRM_FORMAT_XRGB8888,
61 	DRM_FORMAT_ARGB8888,
62 };
63 
64 static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
65 {
66 	struct decon_context *ctx = crtc->ctx;
67 	u32 val;
68 
69 	if (ctx->suspended)
70 		return -EPERM;
71 
72 	if (test_and_set_bit(0, &ctx->irq_flags)) {
73 		val = VIDINTCON0_INTEN;
74 		if (ctx->i80_if)
75 			val |= VIDINTCON0_FRAMEDONE;
76 		else
77 			val |= VIDINTCON0_INTFRMEN;
78 
79 		writel(val, ctx->addr + DECON_VIDINTCON0);
80 	}
81 
82 	return 0;
83 }
84 
85 static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
86 {
87 	struct decon_context *ctx = crtc->ctx;
88 
89 	if (ctx->suspended)
90 		return;
91 
92 	if (test_and_clear_bit(0, &ctx->irq_flags))
93 		writel(0, ctx->addr + DECON_VIDINTCON0);
94 }
95 
96 static void decon_setup_trigger(struct decon_context *ctx)
97 {
98 	u32 val = TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F |
99 			TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN;
100 	writel(val, ctx->addr + DECON_TRIGCON);
101 }
102 
103 static void decon_commit(struct exynos_drm_crtc *crtc)
104 {
105 	struct decon_context *ctx = crtc->ctx;
106 	struct drm_display_mode *mode = &crtc->base.mode;
107 	u32 val;
108 
109 	if (ctx->suspended)
110 		return;
111 
112 	/* enable clock gate */
113 	val = CMU_CLKGAGE_MODE_SFR_F | CMU_CLKGAGE_MODE_MEM_F;
114 	writel(val, ctx->addr + DECON_CMU);
115 
116 	/* lcd on and use command if */
117 	val = VIDOUT_LCD_ON;
118 	if (ctx->i80_if)
119 		val |= VIDOUT_COMMAND_IF;
120 	else
121 		val |= VIDOUT_RGB_IF;
122 	writel(val, ctx->addr + DECON_VIDOUTCON0);
123 
124 	val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
125 		VIDTCON2_HOZVAL(mode->hdisplay - 1);
126 	writel(val, ctx->addr + DECON_VIDTCON2);
127 
128 	if (!ctx->i80_if) {
129 		val = VIDTCON00_VBPD_F(
130 				mode->crtc_vtotal - mode->crtc_vsync_end) |
131 			VIDTCON00_VFPD_F(
132 				mode->crtc_vsync_start - mode->crtc_vdisplay);
133 		writel(val, ctx->addr + DECON_VIDTCON00);
134 
135 		val = VIDTCON01_VSPW_F(
136 				mode->crtc_vsync_end - mode->crtc_vsync_start);
137 		writel(val, ctx->addr + DECON_VIDTCON01);
138 
139 		val = VIDTCON10_HBPD_F(
140 				mode->crtc_htotal - mode->crtc_hsync_end) |
141 			VIDTCON10_HFPD_F(
142 				mode->crtc_hsync_start - mode->crtc_hdisplay);
143 		writel(val, ctx->addr + DECON_VIDTCON10);
144 
145 		val = VIDTCON11_HSPW_F(
146 				mode->crtc_hsync_end - mode->crtc_hsync_start);
147 		writel(val, ctx->addr + DECON_VIDTCON11);
148 	}
149 
150 	decon_setup_trigger(ctx);
151 
152 	/* enable output and display signal */
153 	val = VIDCON0_ENVID | VIDCON0_ENVID_F;
154 	writel(val, ctx->addr + DECON_VIDCON0);
155 }
156 
157 #define COORDINATE_X(x)		(((x) & 0xfff) << 12)
158 #define COORDINATE_Y(x)		((x) & 0xfff)
159 #define OFFSIZE(x)		(((x) & 0x3fff) << 14)
160 #define PAGEWIDTH(x)		((x) & 0x3fff)
161 
162 static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
163 				 struct drm_framebuffer *fb)
164 {
165 	unsigned long val;
166 
167 	val = readl(ctx->addr + DECON_WINCONx(win));
168 	val &= ~WINCONx_BPPMODE_MASK;
169 
170 	switch (fb->pixel_format) {
171 	case DRM_FORMAT_XRGB1555:
172 		val |= WINCONx_BPPMODE_16BPP_I1555;
173 		val |= WINCONx_HAWSWP_F;
174 		val |= WINCONx_BURSTLEN_16WORD;
175 		break;
176 	case DRM_FORMAT_RGB565:
177 		val |= WINCONx_BPPMODE_16BPP_565;
178 		val |= WINCONx_HAWSWP_F;
179 		val |= WINCONx_BURSTLEN_16WORD;
180 		break;
181 	case DRM_FORMAT_XRGB8888:
182 		val |= WINCONx_BPPMODE_24BPP_888;
183 		val |= WINCONx_WSWP_F;
184 		val |= WINCONx_BURSTLEN_16WORD;
185 		break;
186 	case DRM_FORMAT_ARGB8888:
187 		val |= WINCONx_BPPMODE_32BPP_A8888;
188 		val |= WINCONx_WSWP_F | WINCONx_BLD_PIX_F | WINCONx_ALPHA_SEL_F;
189 		val |= WINCONx_BURSTLEN_16WORD;
190 		break;
191 	default:
192 		DRM_ERROR("Proper pixel format is not set\n");
193 		return;
194 	}
195 
196 	DRM_DEBUG_KMS("bpp = %u\n", fb->bits_per_pixel);
197 
198 	/*
199 	 * In case of exynos, setting dma-burst to 16Word causes permanent
200 	 * tearing for very small buffers, e.g. cursor buffer. Burst Mode
201 	 * switching which is based on plane size is not recommended as
202 	 * plane size varies a lot towards the end of the screen and rapid
203 	 * movement causes unstable DMA which results into iommu crash/tear.
204 	 */
205 
206 	if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
207 		val &= ~WINCONx_BURSTLEN_MASK;
208 		val |= WINCONx_BURSTLEN_8WORD;
209 	}
210 
211 	writel(val, ctx->addr + DECON_WINCONx(win));
212 }
213 
214 static void decon_shadow_protect_win(struct decon_context *ctx, int win,
215 					bool protect)
216 {
217 	u32 val;
218 
219 	val = readl(ctx->addr + DECON_SHADOWCON);
220 
221 	if (protect)
222 		val |= SHADOWCON_Wx_PROTECT(win);
223 	else
224 		val &= ~SHADOWCON_Wx_PROTECT(win);
225 
226 	writel(val, ctx->addr + DECON_SHADOWCON);
227 }
228 
229 static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
230 					struct exynos_drm_plane *plane)
231 {
232 	struct decon_context *ctx = crtc->ctx;
233 
234 	if (ctx->suspended)
235 		return;
236 
237 	decon_shadow_protect_win(ctx, plane->zpos, true);
238 }
239 
240 static void decon_update_plane(struct exynos_drm_crtc *crtc,
241 			       struct exynos_drm_plane *plane)
242 {
243 	struct decon_context *ctx = crtc->ctx;
244 	struct drm_plane_state *state = plane->base.state;
245 	unsigned int win = plane->zpos;
246 	unsigned int bpp = state->fb->bits_per_pixel >> 3;
247 	unsigned int pitch = state->fb->pitches[0];
248 	u32 val;
249 
250 	if (ctx->suspended)
251 		return;
252 
253 	val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y);
254 	writel(val, ctx->addr + DECON_VIDOSDxA(win));
255 
256 	val = COORDINATE_X(plane->crtc_x + plane->crtc_w - 1) |
257 		COORDINATE_Y(plane->crtc_y + plane->crtc_h - 1);
258 	writel(val, ctx->addr + DECON_VIDOSDxB(win));
259 
260 	val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
261 		VIDOSD_Wx_ALPHA_B_F(0x0);
262 	writel(val, ctx->addr + DECON_VIDOSDxC(win));
263 
264 	val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
265 		VIDOSD_Wx_ALPHA_B_F(0x0);
266 	writel(val, ctx->addr + DECON_VIDOSDxD(win));
267 
268 	writel(plane->dma_addr[0], ctx->addr + DECON_VIDW0xADD0B0(win));
269 
270 	val = plane->dma_addr[0] + pitch * plane->crtc_h;
271 	writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));
272 
273 	val = OFFSIZE(pitch - plane->crtc_w * bpp)
274 		| PAGEWIDTH(plane->crtc_w * bpp);
275 	writel(val, ctx->addr + DECON_VIDW0xADD2(win));
276 
277 	decon_win_set_pixfmt(ctx, win, state->fb);
278 
279 	/* window enable */
280 	val = readl(ctx->addr + DECON_WINCONx(win));
281 	val |= WINCONx_ENWIN_F;
282 	writel(val, ctx->addr + DECON_WINCONx(win));
283 
284 	/* standalone update */
285 	val = readl(ctx->addr + DECON_UPDATE);
286 	val |= STANDALONE_UPDATE_F;
287 	writel(val, ctx->addr + DECON_UPDATE);
288 }
289 
290 static void decon_disable_plane(struct exynos_drm_crtc *crtc,
291 				struct exynos_drm_plane *plane)
292 {
293 	struct decon_context *ctx = crtc->ctx;
294 	unsigned int win = plane->zpos;
295 	u32 val;
296 
297 	if (ctx->suspended)
298 		return;
299 
300 	decon_shadow_protect_win(ctx, win, true);
301 
302 	/* window disable */
303 	val = readl(ctx->addr + DECON_WINCONx(win));
304 	val &= ~WINCONx_ENWIN_F;
305 	writel(val, ctx->addr + DECON_WINCONx(win));
306 
307 	decon_shadow_protect_win(ctx, win, false);
308 
309 	/* standalone update */
310 	val = readl(ctx->addr + DECON_UPDATE);
311 	val |= STANDALONE_UPDATE_F;
312 	writel(val, ctx->addr + DECON_UPDATE);
313 }
314 
315 static void decon_atomic_flush(struct exynos_drm_crtc *crtc,
316 				struct exynos_drm_plane *plane)
317 {
318 	struct decon_context *ctx = crtc->ctx;
319 
320 	if (ctx->suspended)
321 		return;
322 
323 	decon_shadow_protect_win(ctx, plane->zpos, false);
324 
325 	if (ctx->i80_if)
326 		atomic_set(&ctx->win_updated, 1);
327 }
328 
329 static void decon_swreset(struct decon_context *ctx)
330 {
331 	unsigned int tries;
332 
333 	writel(0, ctx->addr + DECON_VIDCON0);
334 	for (tries = 2000; tries; --tries) {
335 		if (~readl(ctx->addr + DECON_VIDCON0) & VIDCON0_STOP_STATUS)
336 			break;
337 		udelay(10);
338 	}
339 
340 	WARN(tries == 0, "failed to disable DECON\n");
341 
342 	writel(VIDCON0_SWRESET, ctx->addr + DECON_VIDCON0);
343 	for (tries = 2000; tries; --tries) {
344 		if (~readl(ctx->addr + DECON_VIDCON0) & VIDCON0_SWRESET)
345 			break;
346 		udelay(10);
347 	}
348 
349 	WARN(tries == 0, "failed to software reset DECON\n");
350 }
351 
352 static void decon_enable(struct exynos_drm_crtc *crtc)
353 {
354 	struct decon_context *ctx = crtc->ctx;
355 	int ret;
356 	int i;
357 
358 	if (!ctx->suspended)
359 		return;
360 
361 	ctx->suspended = false;
362 
363 	pm_runtime_get_sync(ctx->dev);
364 
365 	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
366 		ret = clk_prepare_enable(ctx->clks[i]);
367 		if (ret < 0)
368 			goto err;
369 	}
370 
371 	set_bit(BIT_CLKS_ENABLED, &ctx->enabled);
372 
373 	/* if vblank was enabled status, enable it again. */
374 	if (test_and_clear_bit(0, &ctx->irq_flags))
375 		decon_enable_vblank(ctx->crtc);
376 
377 	decon_commit(ctx->crtc);
378 
379 	return;
380 err:
381 	while (--i >= 0)
382 		clk_disable_unprepare(ctx->clks[i]);
383 
384 	ctx->suspended = true;
385 }
386 
387 static void decon_disable(struct exynos_drm_crtc *crtc)
388 {
389 	struct decon_context *ctx = crtc->ctx;
390 	int i;
391 
392 	if (ctx->suspended)
393 		return;
394 
395 	/*
396 	 * We need to make sure that all windows are disabled before we
397 	 * suspend that connector. Otherwise we might try to scan from
398 	 * a destroyed buffer later.
399 	 */
400 	for (i = 0; i < WINDOWS_NR; i++)
401 		decon_disable_plane(crtc, &ctx->planes[i]);
402 
403 	decon_swreset(ctx);
404 
405 	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++)
406 		clk_disable_unprepare(ctx->clks[i]);
407 
408 	clear_bit(BIT_CLKS_ENABLED, &ctx->enabled);
409 
410 	pm_runtime_put_sync(ctx->dev);
411 
412 	ctx->suspended = true;
413 }
414 
415 void decon_te_irq_handler(struct exynos_drm_crtc *crtc)
416 {
417 	struct decon_context *ctx = crtc->ctx;
418 	u32 val;
419 
420 	if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
421 		return;
422 
423 	if (atomic_add_unless(&ctx->win_updated, -1, 0)) {
424 		/* trigger */
425 		val = readl(ctx->addr + DECON_TRIGCON);
426 		val |= TRIGCON_SWTRIGCMD;
427 		writel(val, ctx->addr + DECON_TRIGCON);
428 	}
429 
430 	drm_crtc_handle_vblank(&ctx->crtc->base);
431 }
432 
433 static void decon_clear_channels(struct exynos_drm_crtc *crtc)
434 {
435 	struct decon_context *ctx = crtc->ctx;
436 	int win, i, ret;
437 	u32 val;
438 
439 	DRM_DEBUG_KMS("%s\n", __FILE__);
440 
441 	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
442 		ret = clk_prepare_enable(ctx->clks[i]);
443 		if (ret < 0)
444 			goto err;
445 	}
446 
447 	for (win = 0; win < WINDOWS_NR; win++) {
448 		/* shadow update disable */
449 		val = readl(ctx->addr + DECON_SHADOWCON);
450 		val |= SHADOWCON_Wx_PROTECT(win);
451 		writel(val, ctx->addr + DECON_SHADOWCON);
452 
453 		/* window disable */
454 		val = readl(ctx->addr + DECON_WINCONx(win));
455 		val &= ~WINCONx_ENWIN_F;
456 		writel(val, ctx->addr + DECON_WINCONx(win));
457 
458 		/* shadow update enable */
459 		val = readl(ctx->addr + DECON_SHADOWCON);
460 		val &= ~SHADOWCON_Wx_PROTECT(win);
461 		writel(val, ctx->addr + DECON_SHADOWCON);
462 
463 		/* standalone update */
464 		val = readl(ctx->addr + DECON_UPDATE);
465 		val |= STANDALONE_UPDATE_F;
466 		writel(val, ctx->addr + DECON_UPDATE);
467 	}
468 	/* TODO: wait for possible vsync */
469 	msleep(50);
470 
471 err:
472 	while (--i >= 0)
473 		clk_disable_unprepare(ctx->clks[i]);
474 }
475 
476 static struct exynos_drm_crtc_ops decon_crtc_ops = {
477 	.enable			= decon_enable,
478 	.disable		= decon_disable,
479 	.commit			= decon_commit,
480 	.enable_vblank		= decon_enable_vblank,
481 	.disable_vblank		= decon_disable_vblank,
482 	.commit			= decon_commit,
483 	.atomic_begin		= decon_atomic_begin,
484 	.update_plane		= decon_update_plane,
485 	.disable_plane		= decon_disable_plane,
486 	.atomic_flush		= decon_atomic_flush,
487 	.te_handler		= decon_te_irq_handler,
488 };
489 
490 static int decon_bind(struct device *dev, struct device *master, void *data)
491 {
492 	struct decon_context *ctx = dev_get_drvdata(dev);
493 	struct drm_device *drm_dev = data;
494 	struct exynos_drm_private *priv = drm_dev->dev_private;
495 	struct exynos_drm_plane *exynos_plane;
496 	enum drm_plane_type type;
497 	unsigned int zpos;
498 	int ret;
499 
500 	ctx->drm_dev = drm_dev;
501 	ctx->pipe = priv->pipe++;
502 
503 	for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
504 		type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
505 							DRM_PLANE_TYPE_OVERLAY;
506 		ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
507 				1 << ctx->pipe, type, decon_formats,
508 				ARRAY_SIZE(decon_formats), zpos);
509 		if (ret)
510 			return ret;
511 	}
512 
513 	exynos_plane = &ctx->planes[ctx->default_win];
514 	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
515 					ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
516 					&decon_crtc_ops, ctx);
517 	if (IS_ERR(ctx->crtc)) {
518 		ret = PTR_ERR(ctx->crtc);
519 		goto err;
520 	}
521 
522 	decon_clear_channels(ctx->crtc);
523 
524 	ret = drm_iommu_attach_device(drm_dev, dev);
525 	if (ret)
526 		goto err;
527 
528 	return ret;
529 err:
530 	priv->pipe--;
531 	return ret;
532 }
533 
534 static void decon_unbind(struct device *dev, struct device *master, void *data)
535 {
536 	struct decon_context *ctx = dev_get_drvdata(dev);
537 
538 	decon_disable(ctx->crtc);
539 
540 	/* detach this sub driver from iommu mapping if supported. */
541 	drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
542 }
543 
544 static const struct component_ops decon_component_ops = {
545 	.bind	= decon_bind,
546 	.unbind = decon_unbind,
547 };
548 
549 static irqreturn_t decon_vsync_irq_handler(int irq, void *dev_id)
550 {
551 	struct decon_context *ctx = dev_id;
552 	u32 val;
553 
554 	if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
555 		goto out;
556 
557 	val = readl(ctx->addr + DECON_VIDINTCON1);
558 	if (val & VIDINTCON1_INTFRMPEND) {
559 		drm_crtc_handle_vblank(&ctx->crtc->base);
560 
561 		/* clear */
562 		writel(VIDINTCON1_INTFRMPEND, ctx->addr + DECON_VIDINTCON1);
563 	}
564 
565 out:
566 	return IRQ_HANDLED;
567 }
568 
569 static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id)
570 {
571 	struct decon_context *ctx = dev_id;
572 	u32 val;
573 	int win;
574 
575 	if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
576 		goto out;
577 
578 	val = readl(ctx->addr + DECON_VIDINTCON1);
579 	if (val & VIDINTCON1_INTFRMDONEPEND) {
580 		for (win = 0 ; win < WINDOWS_NR ; win++) {
581 			struct exynos_drm_plane *plane = &ctx->planes[win];
582 
583 			if (!plane->pending_fb)
584 				continue;
585 
586 			exynos_drm_crtc_finish_update(ctx->crtc, plane);
587 		}
588 
589 		/* clear */
590 		writel(VIDINTCON1_INTFRMDONEPEND,
591 				ctx->addr + DECON_VIDINTCON1);
592 	}
593 
594 out:
595 	return IRQ_HANDLED;
596 }
597 
598 static int exynos5433_decon_probe(struct platform_device *pdev)
599 {
600 	struct device *dev = &pdev->dev;
601 	struct decon_context *ctx;
602 	struct resource *res;
603 	int ret;
604 	int i;
605 
606 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
607 	if (!ctx)
608 		return -ENOMEM;
609 
610 	ctx->default_win = 0;
611 	ctx->suspended = true;
612 	ctx->dev = dev;
613 	if (of_get_child_by_name(dev->of_node, "i80-if-timings"))
614 		ctx->i80_if = true;
615 
616 	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
617 		struct clk *clk;
618 
619 		clk = devm_clk_get(ctx->dev, decon_clks_name[i]);
620 		if (IS_ERR(clk))
621 			return PTR_ERR(clk);
622 
623 		ctx->clks[i] = clk;
624 	}
625 
626 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
627 	if (!res) {
628 		dev_err(dev, "cannot find IO resource\n");
629 		return -ENXIO;
630 	}
631 
632 	ctx->addr = devm_ioremap_resource(dev, res);
633 	if (IS_ERR(ctx->addr)) {
634 		dev_err(dev, "ioremap failed\n");
635 		return PTR_ERR(ctx->addr);
636 	}
637 
638 	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
639 			ctx->i80_if ? "lcd_sys" : "vsync");
640 	if (!res) {
641 		dev_err(dev, "cannot find IRQ resource\n");
642 		return -ENXIO;
643 	}
644 
645 	ret = devm_request_irq(dev, res->start, ctx->i80_if ?
646 			decon_lcd_sys_irq_handler : decon_vsync_irq_handler, 0,
647 			"drm_decon", ctx);
648 	if (ret < 0) {
649 		dev_err(dev, "lcd_sys irq request failed\n");
650 		return ret;
651 	}
652 
653 	platform_set_drvdata(pdev, ctx);
654 
655 	pm_runtime_enable(dev);
656 
657 	ret = component_add(dev, &decon_component_ops);
658 	if (ret)
659 		goto err_disable_pm_runtime;
660 
661 	return 0;
662 
663 err_disable_pm_runtime:
664 	pm_runtime_disable(dev);
665 
666 	return ret;
667 }
668 
669 static int exynos5433_decon_remove(struct platform_device *pdev)
670 {
671 	pm_runtime_disable(&pdev->dev);
672 
673 	component_del(&pdev->dev, &decon_component_ops);
674 
675 	return 0;
676 }
677 
678 static const struct of_device_id exynos5433_decon_driver_dt_match[] = {
679 	{ .compatible = "samsung,exynos5433-decon" },
680 	{},
681 };
682 MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match);
683 
684 struct platform_driver exynos5433_decon_driver = {
685 	.probe		= exynos5433_decon_probe,
686 	.remove		= exynos5433_decon_remove,
687 	.driver		= {
688 		.name	= "exynos5433-decon",
689 		.of_match_table = exynos5433_decon_driver_dt_match,
690 	},
691 };
692