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 				 struct drm_framebuffer *fb)
157 {
158 	unsigned long val;
159 
160 	val = readl(ctx->addr + DECON_WINCONx(win));
161 	val &= ~WINCONx_BPPMODE_MASK;
162 
163 	switch (fb->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", fb->bits_per_pixel);
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 (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_update_plane(struct exynos_drm_crtc *crtc,
223 			       struct exynos_drm_plane *plane)
224 {
225 	struct decon_context *ctx = crtc->ctx;
226 	struct drm_plane_state *state = plane->base.state;
227 	unsigned int win = plane->zpos;
228 	unsigned int bpp = state->fb->bits_per_pixel >> 3;
229 	unsigned int pitch = state->fb->pitches[0];
230 	u32 val;
231 
232 	if (ctx->suspended)
233 		return;
234 
235 	decon_shadow_protect_win(ctx, win, true);
236 
237 	val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y);
238 	writel(val, ctx->addr + DECON_VIDOSDxA(win));
239 
240 	val = COORDINATE_X(plane->crtc_x + plane->crtc_w - 1) |
241 		COORDINATE_Y(plane->crtc_y + plane->crtc_h - 1);
242 	writel(val, ctx->addr + DECON_VIDOSDxB(win));
243 
244 	val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
245 		VIDOSD_Wx_ALPHA_B_F(0x0);
246 	writel(val, ctx->addr + DECON_VIDOSDxC(win));
247 
248 	val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
249 		VIDOSD_Wx_ALPHA_B_F(0x0);
250 	writel(val, ctx->addr + DECON_VIDOSDxD(win));
251 
252 	writel(plane->dma_addr[0], ctx->addr + DECON_VIDW0xADD0B0(win));
253 
254 	val = plane->dma_addr[0] + pitch * plane->crtc_h;
255 	writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));
256 
257 	val = OFFSIZE(pitch - plane->crtc_w * bpp)
258 		| PAGEWIDTH(plane->crtc_w * bpp);
259 	writel(val, ctx->addr + DECON_VIDW0xADD2(win));
260 
261 	decon_win_set_pixfmt(ctx, win, state->fb);
262 
263 	/* window enable */
264 	val = readl(ctx->addr + DECON_WINCONx(win));
265 	val |= WINCONx_ENWIN_F;
266 	writel(val, ctx->addr + DECON_WINCONx(win));
267 
268 	decon_shadow_protect_win(ctx, win, false);
269 
270 	/* standalone update */
271 	val = readl(ctx->addr + DECON_UPDATE);
272 	val |= STANDALONE_UPDATE_F;
273 	writel(val, ctx->addr + DECON_UPDATE);
274 
275 	if (ctx->i80_if)
276 		atomic_set(&ctx->win_updated, 1);
277 }
278 
279 static void decon_disable_plane(struct exynos_drm_crtc *crtc,
280 				struct exynos_drm_plane *plane)
281 {
282 	struct decon_context *ctx = crtc->ctx;
283 	unsigned int win = plane->zpos;
284 	u32 val;
285 
286 	if (ctx->suspended)
287 		return;
288 
289 	decon_shadow_protect_win(ctx, win, true);
290 
291 	/* window disable */
292 	val = readl(ctx->addr + DECON_WINCONx(win));
293 	val &= ~WINCONx_ENWIN_F;
294 	writel(val, ctx->addr + DECON_WINCONx(win));
295 
296 	decon_shadow_protect_win(ctx, win, false);
297 
298 	/* standalone update */
299 	val = readl(ctx->addr + DECON_UPDATE);
300 	val |= STANDALONE_UPDATE_F;
301 	writel(val, ctx->addr + DECON_UPDATE);
302 }
303 
304 static void decon_swreset(struct decon_context *ctx)
305 {
306 	unsigned int tries;
307 
308 	writel(0, ctx->addr + DECON_VIDCON0);
309 	for (tries = 2000; tries; --tries) {
310 		if (~readl(ctx->addr + DECON_VIDCON0) & VIDCON0_STOP_STATUS)
311 			break;
312 		udelay(10);
313 	}
314 
315 	WARN(tries == 0, "failed to disable DECON\n");
316 
317 	writel(VIDCON0_SWRESET, ctx->addr + DECON_VIDCON0);
318 	for (tries = 2000; tries; --tries) {
319 		if (~readl(ctx->addr + DECON_VIDCON0) & VIDCON0_SWRESET)
320 			break;
321 		udelay(10);
322 	}
323 
324 	WARN(tries == 0, "failed to software reset DECON\n");
325 }
326 
327 static void decon_enable(struct exynos_drm_crtc *crtc)
328 {
329 	struct decon_context *ctx = crtc->ctx;
330 	int ret;
331 	int i;
332 
333 	if (!ctx->suspended)
334 		return;
335 
336 	ctx->suspended = false;
337 
338 	pm_runtime_get_sync(ctx->dev);
339 
340 	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
341 		ret = clk_prepare_enable(ctx->clks[i]);
342 		if (ret < 0)
343 			goto err;
344 	}
345 
346 	set_bit(BIT_CLKS_ENABLED, &ctx->enabled);
347 
348 	/* if vblank was enabled status, enable it again. */
349 	if (test_and_clear_bit(0, &ctx->irq_flags))
350 		decon_enable_vblank(ctx->crtc);
351 
352 	decon_commit(ctx->crtc);
353 
354 	return;
355 err:
356 	while (--i >= 0)
357 		clk_disable_unprepare(ctx->clks[i]);
358 
359 	ctx->suspended = true;
360 }
361 
362 static void decon_disable(struct exynos_drm_crtc *crtc)
363 {
364 	struct decon_context *ctx = crtc->ctx;
365 	int i;
366 
367 	if (ctx->suspended)
368 		return;
369 
370 	/*
371 	 * We need to make sure that all windows are disabled before we
372 	 * suspend that connector. Otherwise we might try to scan from
373 	 * a destroyed buffer later.
374 	 */
375 	for (i = 0; i < WINDOWS_NR; i++)
376 		decon_disable_plane(crtc, &ctx->planes[i]);
377 
378 	decon_swreset(ctx);
379 
380 	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++)
381 		clk_disable_unprepare(ctx->clks[i]);
382 
383 	clear_bit(BIT_CLKS_ENABLED, &ctx->enabled);
384 
385 	pm_runtime_put_sync(ctx->dev);
386 
387 	ctx->suspended = true;
388 }
389 
390 void decon_te_irq_handler(struct exynos_drm_crtc *crtc)
391 {
392 	struct decon_context *ctx = crtc->ctx;
393 	u32 val;
394 
395 	if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
396 		return;
397 
398 	if (atomic_add_unless(&ctx->win_updated, -1, 0)) {
399 		/* trigger */
400 		val = readl(ctx->addr + DECON_TRIGCON);
401 		val |= TRIGCON_SWTRIGCMD;
402 		writel(val, ctx->addr + DECON_TRIGCON);
403 	}
404 
405 	drm_crtc_handle_vblank(&ctx->crtc->base);
406 }
407 
408 static void decon_clear_channels(struct exynos_drm_crtc *crtc)
409 {
410 	struct decon_context *ctx = crtc->ctx;
411 	int win, i, ret;
412 	u32 val;
413 
414 	DRM_DEBUG_KMS("%s\n", __FILE__);
415 
416 	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
417 		ret = clk_prepare_enable(ctx->clks[i]);
418 		if (ret < 0)
419 			goto err;
420 	}
421 
422 	for (win = 0; win < WINDOWS_NR; win++) {
423 		/* shadow update disable */
424 		val = readl(ctx->addr + DECON_SHADOWCON);
425 		val |= SHADOWCON_Wx_PROTECT(win);
426 		writel(val, ctx->addr + DECON_SHADOWCON);
427 
428 		/* window disable */
429 		val = readl(ctx->addr + DECON_WINCONx(win));
430 		val &= ~WINCONx_ENWIN_F;
431 		writel(val, ctx->addr + DECON_WINCONx(win));
432 
433 		/* shadow update enable */
434 		val = readl(ctx->addr + DECON_SHADOWCON);
435 		val &= ~SHADOWCON_Wx_PROTECT(win);
436 		writel(val, ctx->addr + DECON_SHADOWCON);
437 
438 		/* standalone update */
439 		val = readl(ctx->addr + DECON_UPDATE);
440 		val |= STANDALONE_UPDATE_F;
441 		writel(val, ctx->addr + DECON_UPDATE);
442 	}
443 	/* TODO: wait for possible vsync */
444 	msleep(50);
445 
446 err:
447 	while (--i >= 0)
448 		clk_disable_unprepare(ctx->clks[i]);
449 }
450 
451 static struct exynos_drm_crtc_ops decon_crtc_ops = {
452 	.enable			= decon_enable,
453 	.disable		= decon_disable,
454 	.commit			= decon_commit,
455 	.enable_vblank		= decon_enable_vblank,
456 	.disable_vblank		= decon_disable_vblank,
457 	.commit			= decon_commit,
458 	.update_plane		= decon_update_plane,
459 	.disable_plane		= decon_disable_plane,
460 	.te_handler		= decon_te_irq_handler,
461 };
462 
463 static int decon_bind(struct device *dev, struct device *master, void *data)
464 {
465 	struct decon_context *ctx = dev_get_drvdata(dev);
466 	struct drm_device *drm_dev = data;
467 	struct exynos_drm_private *priv = drm_dev->dev_private;
468 	struct exynos_drm_plane *exynos_plane;
469 	enum drm_plane_type type;
470 	unsigned int zpos;
471 	int ret;
472 
473 	ctx->drm_dev = drm_dev;
474 	ctx->pipe = priv->pipe++;
475 
476 	for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
477 		type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
478 							DRM_PLANE_TYPE_OVERLAY;
479 		ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
480 				1 << ctx->pipe, type, zpos);
481 		if (ret)
482 			return ret;
483 	}
484 
485 	exynos_plane = &ctx->planes[ctx->default_win];
486 	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
487 					ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
488 					&decon_crtc_ops, ctx);
489 	if (IS_ERR(ctx->crtc)) {
490 		ret = PTR_ERR(ctx->crtc);
491 		goto err;
492 	}
493 
494 	decon_clear_channels(ctx->crtc);
495 
496 	ret = drm_iommu_attach_device(drm_dev, dev);
497 	if (ret)
498 		goto err;
499 
500 	return ret;
501 err:
502 	priv->pipe--;
503 	return ret;
504 }
505 
506 static void decon_unbind(struct device *dev, struct device *master, void *data)
507 {
508 	struct decon_context *ctx = dev_get_drvdata(dev);
509 
510 	decon_disable(ctx->crtc);
511 
512 	/* detach this sub driver from iommu mapping if supported. */
513 	drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
514 }
515 
516 static const struct component_ops decon_component_ops = {
517 	.bind	= decon_bind,
518 	.unbind = decon_unbind,
519 };
520 
521 static irqreturn_t decon_vsync_irq_handler(int irq, void *dev_id)
522 {
523 	struct decon_context *ctx = dev_id;
524 	u32 val;
525 
526 	if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
527 		goto out;
528 
529 	val = readl(ctx->addr + DECON_VIDINTCON1);
530 	if (val & VIDINTCON1_INTFRMPEND) {
531 		drm_crtc_handle_vblank(&ctx->crtc->base);
532 
533 		/* clear */
534 		writel(VIDINTCON1_INTFRMPEND, ctx->addr + DECON_VIDINTCON1);
535 	}
536 
537 out:
538 	return IRQ_HANDLED;
539 }
540 
541 static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id)
542 {
543 	struct decon_context *ctx = dev_id;
544 	u32 val;
545 
546 	if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
547 		goto out;
548 
549 	val = readl(ctx->addr + DECON_VIDINTCON1);
550 	if (val & VIDINTCON1_INTFRMDONEPEND) {
551 		exynos_drm_crtc_finish_pageflip(ctx->crtc);
552 
553 		/* clear */
554 		writel(VIDINTCON1_INTFRMDONEPEND,
555 				ctx->addr + DECON_VIDINTCON1);
556 	}
557 
558 out:
559 	return IRQ_HANDLED;
560 }
561 
562 static int exynos5433_decon_probe(struct platform_device *pdev)
563 {
564 	struct device *dev = &pdev->dev;
565 	struct decon_context *ctx;
566 	struct resource *res;
567 	int ret;
568 	int i;
569 
570 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
571 	if (!ctx)
572 		return -ENOMEM;
573 
574 	ctx->default_win = 0;
575 	ctx->suspended = true;
576 	ctx->dev = dev;
577 	if (of_get_child_by_name(dev->of_node, "i80-if-timings"))
578 		ctx->i80_if = true;
579 
580 	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
581 		struct clk *clk;
582 
583 		clk = devm_clk_get(ctx->dev, decon_clks_name[i]);
584 		if (IS_ERR(clk))
585 			return PTR_ERR(clk);
586 
587 		ctx->clks[i] = clk;
588 	}
589 
590 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
591 	if (!res) {
592 		dev_err(dev, "cannot find IO resource\n");
593 		return -ENXIO;
594 	}
595 
596 	ctx->addr = devm_ioremap_resource(dev, res);
597 	if (IS_ERR(ctx->addr)) {
598 		dev_err(dev, "ioremap failed\n");
599 		return PTR_ERR(ctx->addr);
600 	}
601 
602 	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
603 			ctx->i80_if ? "lcd_sys" : "vsync");
604 	if (!res) {
605 		dev_err(dev, "cannot find IRQ resource\n");
606 		return -ENXIO;
607 	}
608 
609 	ret = devm_request_irq(dev, res->start, ctx->i80_if ?
610 			decon_lcd_sys_irq_handler : decon_vsync_irq_handler, 0,
611 			"drm_decon", ctx);
612 	if (ret < 0) {
613 		dev_err(dev, "lcd_sys irq request failed\n");
614 		return ret;
615 	}
616 
617 	platform_set_drvdata(pdev, ctx);
618 
619 	pm_runtime_enable(dev);
620 
621 	ret = component_add(dev, &decon_component_ops);
622 	if (ret)
623 		goto err_disable_pm_runtime;
624 
625 	return 0;
626 
627 err_disable_pm_runtime:
628 	pm_runtime_disable(dev);
629 
630 	return ret;
631 }
632 
633 static int exynos5433_decon_remove(struct platform_device *pdev)
634 {
635 	pm_runtime_disable(&pdev->dev);
636 
637 	component_del(&pdev->dev, &decon_component_ops);
638 
639 	return 0;
640 }
641 
642 static const struct of_device_id exynos5433_decon_driver_dt_match[] = {
643 	{ .compatible = "samsung,exynos5433-decon" },
644 	{},
645 };
646 MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match);
647 
648 struct platform_driver exynos5433_decon_driver = {
649 	.probe		= exynos5433_decon_probe,
650 	.remove		= exynos5433_decon_remove,
651 	.driver		= {
652 		.name	= "exynos5433-decon",
653 		.of_match_table = exynos5433_decon_driver_dt_match,
654 	},
655 };
656