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