aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/exynos/Makefile2
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_core.c119
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c33
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h47
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c10
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c17
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c300
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.h11
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c62
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.h24
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c51
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c120
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_mic.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_scaler.c44
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c4
-rw-r--r--drivers/gpu/drm/exynos/regs-gsc.h1
24 files changed, 324 insertions, 548 deletions
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 3b323f1e0475..2ad146bbf4f5 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -4,7 +4,7 @@
4# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. 4# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
5 5
6exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fb.o \ 6exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fb.o \
7 exynos_drm_gem.o exynos_drm_core.o exynos_drm_plane.o 7 exynos_drm_gem.o exynos_drm_plane.o
8 8
9exynosdrm-$(CONFIG_DRM_FBDEV_EMULATION) += exynos_drm_fbdev.o 9exynosdrm-$(CONFIG_DRM_FBDEV_EMULATION) += exynos_drm_fbdev.o
10exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o 10exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 82c95c34447f..94529aa82339 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -265,7 +265,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
265 unsigned long val; 265 unsigned long val;
266 266
267 val = readl(ctx->addr + DECON_WINCONx(win)); 267 val = readl(ctx->addr + DECON_WINCONx(win));
268 val &= ~WINCONx_BPPMODE_MASK; 268 val &= WINCONx_ENWIN_F;
269 269
270 switch (fb->format->format) { 270 switch (fb->format->format) {
271 case DRM_FORMAT_XRGB1555: 271 case DRM_FORMAT_XRGB1555:
@@ -356,8 +356,8 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
356 writel(val, ctx->addr + DECON_VIDOSDxB(win)); 356 writel(val, ctx->addr + DECON_VIDOSDxB(win));
357 } 357 }
358 358
359 val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) | 359 val = VIDOSD_Wx_ALPHA_R_F(0xff) | VIDOSD_Wx_ALPHA_G_F(0xff) |
360 VIDOSD_Wx_ALPHA_B_F(0x0); 360 VIDOSD_Wx_ALPHA_B_F(0xff);
361 writel(val, ctx->addr + DECON_VIDOSDxC(win)); 361 writel(val, ctx->addr + DECON_VIDOSDxC(win));
362 362
363 val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) | 363 val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
@@ -673,6 +673,8 @@ err:
673static const struct dev_pm_ops exynos5433_decon_pm_ops = { 673static const struct dev_pm_ops exynos5433_decon_pm_ops = {
674 SET_RUNTIME_PM_OPS(exynos5433_decon_suspend, exynos5433_decon_resume, 674 SET_RUNTIME_PM_OPS(exynos5433_decon_suspend, exynos5433_decon_resume,
675 NULL) 675 NULL)
676 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
677 pm_runtime_force_resume)
676}; 678};
677 679
678static const struct of_device_id exynos5433_decon_driver_dt_match[] = { 680static const struct of_device_id exynos5433_decon_driver_dt_match[] = {
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 3931d5e33fe0..88cbd000eb09 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -832,6 +832,8 @@ static int exynos7_decon_resume(struct device *dev)
832static const struct dev_pm_ops exynos7_decon_pm_ops = { 832static const struct dev_pm_ops exynos7_decon_pm_ops = {
833 SET_RUNTIME_PM_OPS(exynos7_decon_suspend, exynos7_decon_resume, 833 SET_RUNTIME_PM_OPS(exynos7_decon_suspend, exynos7_decon_resume,
834 NULL) 834 NULL)
835 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
836 pm_runtime_force_resume)
835}; 837};
836 838
837struct platform_driver decon_driver = { 839struct platform_driver decon_driver = {
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index af7ab1ceb50f..c8449ae4f4fe 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -16,6 +16,7 @@
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/of_graph.h> 17#include <linux/of_graph.h>
18#include <linux/component.h> 18#include <linux/component.h>
19#include <linux/pm_runtime.h>
19#include <video/of_display_timing.h> 20#include <video/of_display_timing.h>
20#include <video/of_videomode.h> 21#include <video/of_videomode.h>
21#include <video/videomode.h> 22#include <video/videomode.h>
@@ -278,6 +279,8 @@ static int exynos_dp_resume(struct device *dev)
278 279
279static const struct dev_pm_ops exynos_dp_pm_ops = { 280static const struct dev_pm_ops exynos_dp_pm_ops = {
280 SET_RUNTIME_PM_OPS(exynos_dp_suspend, exynos_dp_resume, NULL) 281 SET_RUNTIME_PM_OPS(exynos_dp_suspend, exynos_dp_resume, NULL)
282 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
283 pm_runtime_force_resume)
281}; 284};
282 285
283static const struct of_device_id exynos_dp_match[] = { 286static const struct of_device_id exynos_dp_match[] = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
deleted file mode 100644
index b0c0621fcdf7..000000000000
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ /dev/null
@@ -1,119 +0,0 @@
1/* exynos_drm_core.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * Author:
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
7 * Seung-Woo Kim <sw0312.kim@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#include <drm/drmP.h>
16
17#include "exynos_drm_drv.h"
18#include "exynos_drm_crtc.h"
19
20static LIST_HEAD(exynos_drm_subdrv_list);
21
22int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
23{
24 if (!subdrv)
25 return -EINVAL;
26
27 list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
28
29 return 0;
30}
31
32int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
33{
34 if (!subdrv)
35 return -EINVAL;
36
37 list_del(&subdrv->list);
38
39 return 0;
40}
41
42int exynos_drm_device_subdrv_probe(struct drm_device *dev)
43{
44 struct exynos_drm_subdrv *subdrv, *n;
45 int err;
46
47 if (!dev)
48 return -EINVAL;
49
50 list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
51 if (subdrv->probe) {
52 subdrv->drm_dev = dev;
53
54 /*
55 * this probe callback would be called by sub driver
56 * after setting of all resources to this sub driver,
57 * such as clock, irq and register map are done.
58 */
59 err = subdrv->probe(dev, subdrv->dev);
60 if (err) {
61 DRM_DEBUG("exynos drm subdrv probe failed.\n");
62 list_del(&subdrv->list);
63 continue;
64 }
65 }
66 }
67
68 return 0;
69}
70
71int exynos_drm_device_subdrv_remove(struct drm_device *dev)
72{
73 struct exynos_drm_subdrv *subdrv;
74
75 if (!dev) {
76 WARN(1, "Unexpected drm device unregister!\n");
77 return -EINVAL;
78 }
79
80 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
81 if (subdrv->remove)
82 subdrv->remove(dev, subdrv->dev);
83 }
84
85 return 0;
86}
87
88int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
89{
90 struct exynos_drm_subdrv *subdrv;
91 int ret;
92
93 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
94 if (subdrv->open) {
95 ret = subdrv->open(dev, subdrv->dev, file);
96 if (ret)
97 goto err;
98 }
99 }
100
101 return 0;
102
103err:
104 list_for_each_entry_continue_reverse(subdrv, &exynos_drm_subdrv_list, list) {
105 if (subdrv->close)
106 subdrv->close(dev, subdrv->dev, file);
107 }
108 return ret;
109}
110
111void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
112{
113 struct exynos_drm_subdrv *subdrv;
114
115 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
116 if (subdrv->close)
117 subdrv->close(dev, subdrv->dev, file);
118 }
119}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index a81b4a5e24a7..b599f74692e5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -55,8 +55,7 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
55 return -ENOMEM; 55 return -ENOMEM;
56 56
57 file->driver_priv = file_priv; 57 file->driver_priv = file_priv;
58 58 ret = g2d_open(dev, file);
59 ret = exynos_drm_subdrv_open(dev, file);
60 if (ret) 59 if (ret)
61 goto err_file_priv_free; 60 goto err_file_priv_free;
62 61
@@ -70,7 +69,7 @@ err_file_priv_free:
70 69
71static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) 70static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
72{ 71{
73 exynos_drm_subdrv_close(dev, file); 72 g2d_close(dev, file);
74 kfree(file->driver_priv); 73 kfree(file->driver_priv);
75 file->driver_priv = NULL; 74 file->driver_priv = NULL;
76} 75}
@@ -147,13 +146,12 @@ static struct drm_driver exynos_drm_driver = {
147 .minor = DRIVER_MINOR, 146 .minor = DRIVER_MINOR,
148}; 147};
149 148
150#ifdef CONFIG_PM_SLEEP
151static int exynos_drm_suspend(struct device *dev) 149static int exynos_drm_suspend(struct device *dev)
152{ 150{
153 struct drm_device *drm_dev = dev_get_drvdata(dev); 151 struct drm_device *drm_dev = dev_get_drvdata(dev);
154 struct exynos_drm_private *private; 152 struct exynos_drm_private *private;
155 153
156 if (pm_runtime_suspended(dev) || !drm_dev) 154 if (!drm_dev)
157 return 0; 155 return 0;
158 156
159 private = drm_dev->dev_private; 157 private = drm_dev->dev_private;
@@ -170,25 +168,23 @@ static int exynos_drm_suspend(struct device *dev)
170 return 0; 168 return 0;
171} 169}
172 170
173static int exynos_drm_resume(struct device *dev) 171static void exynos_drm_resume(struct device *dev)
174{ 172{
175 struct drm_device *drm_dev = dev_get_drvdata(dev); 173 struct drm_device *drm_dev = dev_get_drvdata(dev);
176 struct exynos_drm_private *private; 174 struct exynos_drm_private *private;
177 175
178 if (pm_runtime_suspended(dev) || !drm_dev) 176 if (!drm_dev)
179 return 0; 177 return;
180 178
181 private = drm_dev->dev_private; 179 private = drm_dev->dev_private;
182 drm_atomic_helper_resume(drm_dev, private->suspend_state); 180 drm_atomic_helper_resume(drm_dev, private->suspend_state);
183 exynos_drm_fbdev_resume(drm_dev); 181 exynos_drm_fbdev_resume(drm_dev);
184 drm_kms_helper_poll_enable(drm_dev); 182 drm_kms_helper_poll_enable(drm_dev);
185
186 return 0;
187} 183}
188#endif
189 184
190static const struct dev_pm_ops exynos_drm_pm_ops = { 185static const struct dev_pm_ops exynos_drm_pm_ops = {
191 SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_suspend, exynos_drm_resume) 186 .prepare = exynos_drm_suspend,
187 .complete = exynos_drm_resume,
192}; 188};
193 189
194/* forward declaration */ 190/* forward declaration */
@@ -240,6 +236,7 @@ static struct exynos_drm_driver_info exynos_drm_drivers[] = {
240 DRM_COMPONENT_DRIVER | DRM_VIRTUAL_DEVICE 236 DRM_COMPONENT_DRIVER | DRM_VIRTUAL_DEVICE
241 }, { 237 }, {
242 DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D), 238 DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D),
239 DRM_COMPONENT_DRIVER
243 }, { 240 }, {
244 DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC), 241 DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC),
245 DRM_COMPONENT_DRIVER | DRM_FIMC_DEVICE, 242 DRM_COMPONENT_DRIVER | DRM_FIMC_DEVICE,
@@ -376,11 +373,6 @@ static int exynos_drm_bind(struct device *dev)
376 if (ret) 373 if (ret)
377 goto err_unbind_all; 374 goto err_unbind_all;
378 375
379 /* Probe non kms sub drivers and virtual display driver. */
380 ret = exynos_drm_device_subdrv_probe(drm);
381 if (ret)
382 goto err_unbind_all;
383
384 drm_mode_config_reset(drm); 376 drm_mode_config_reset(drm);
385 377
386 /* 378 /*
@@ -411,7 +403,6 @@ err_cleanup_fbdev:
411 exynos_drm_fbdev_fini(drm); 403 exynos_drm_fbdev_fini(drm);
412err_cleanup_poll: 404err_cleanup_poll:
413 drm_kms_helper_poll_fini(drm); 405 drm_kms_helper_poll_fini(drm);
414 exynos_drm_device_subdrv_remove(drm);
415err_unbind_all: 406err_unbind_all:
416 component_unbind_all(drm->dev, drm); 407 component_unbind_all(drm->dev, drm);
417err_mode_config_cleanup: 408err_mode_config_cleanup:
@@ -420,7 +411,7 @@ err_mode_config_cleanup:
420err_free_private: 411err_free_private:
421 kfree(private); 412 kfree(private);
422err_free_drm: 413err_free_drm:
423 drm_dev_unref(drm); 414 drm_dev_put(drm);
424 415
425 return ret; 416 return ret;
426} 417}
@@ -431,8 +422,6 @@ static void exynos_drm_unbind(struct device *dev)
431 422
432 drm_dev_unregister(drm); 423 drm_dev_unregister(drm);
433 424
434 exynos_drm_device_subdrv_remove(drm);
435
436 exynos_drm_fbdev_fini(drm); 425 exynos_drm_fbdev_fini(drm);
437 drm_kms_helper_poll_fini(drm); 426 drm_kms_helper_poll_fini(drm);
438 427
@@ -444,7 +433,7 @@ static void exynos_drm_unbind(struct device *dev)
444 drm->dev_private = NULL; 433 drm->dev_private = NULL;
445 dev_set_drvdata(dev, NULL); 434 dev_set_drvdata(dev, NULL);
446 435
447 drm_dev_unref(drm); 436 drm_dev_put(drm);
448} 437}
449 438
450static const struct component_master_ops exynos_drm_ops = { 439static const struct component_master_ops exynos_drm_ops = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 0f6d079a55c9..c737c4bd2c19 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -179,17 +179,13 @@ static inline void exynos_drm_pipe_clk_enable(struct exynos_drm_crtc *crtc,
179 crtc->pipe_clk->enable(crtc->pipe_clk, enable); 179 crtc->pipe_clk->enable(crtc->pipe_clk, enable);
180} 180}
181 181
182struct exynos_drm_g2d_private { 182struct drm_exynos_file_private {
183 struct device *dev; 183 /* for g2d api */
184 struct list_head inuse_cmdlist; 184 struct list_head inuse_cmdlist;
185 struct list_head event_list; 185 struct list_head event_list;
186 struct list_head userptr_list; 186 struct list_head userptr_list;
187}; 187};
188 188
189struct drm_exynos_file_private {
190 struct exynos_drm_g2d_private *g2d_priv;
191};
192
193/* 189/*
194 * Exynos drm private structure. 190 * Exynos drm private structure.
195 * 191 *
@@ -201,6 +197,7 @@ struct exynos_drm_private {
201 struct drm_fb_helper *fb_helper; 197 struct drm_fb_helper *fb_helper;
202 struct drm_atomic_state *suspend_state; 198 struct drm_atomic_state *suspend_state;
203 199
200 struct device *g2d_dev;
204 struct device *dma_dev; 201 struct device *dma_dev;
205 void *mapping; 202 void *mapping;
206 203
@@ -217,44 +214,6 @@ static inline struct device *to_dma_dev(struct drm_device *dev)
217 return priv->dma_dev; 214 return priv->dma_dev;
218} 215}
219 216
220/*
221 * Exynos drm sub driver structure.
222 *
223 * @list: sub driver has its own list object to register to exynos drm driver.
224 * @dev: pointer to device object for subdrv device driver.
225 * @drm_dev: pointer to drm_device and this pointer would be set
226 * when sub driver calls exynos_drm_subdrv_register().
227 * @probe: this callback would be called by exynos drm driver after
228 * subdrv is registered to it.
229 * @remove: this callback is used to release resources created
230 * by probe callback.
231 * @open: this would be called with drm device file open.
232 * @close: this would be called with drm device file close.
233 */
234struct exynos_drm_subdrv {
235 struct list_head list;
236 struct device *dev;
237 struct drm_device *drm_dev;
238
239 int (*probe)(struct drm_device *drm_dev, struct device *dev);
240 void (*remove)(struct drm_device *drm_dev, struct device *dev);
241 int (*open)(struct drm_device *drm_dev, struct device *dev,
242 struct drm_file *file);
243 void (*close)(struct drm_device *drm_dev, struct device *dev,
244 struct drm_file *file);
245};
246
247 /* This function would be called by non kms drivers such as g2d and ipp. */
248int exynos_drm_subdrv_register(struct exynos_drm_subdrv *drm_subdrv);
249
250/* this function removes subdrv list from exynos drm driver */
251int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv);
252
253int exynos_drm_device_subdrv_probe(struct drm_device *dev);
254int exynos_drm_device_subdrv_remove(struct drm_device *dev);
255int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file);
256void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file);
257
258#ifdef CONFIG_DRM_EXYNOS_DPI 217#ifdef CONFIG_DRM_EXYNOS_DPI
259struct drm_encoder *exynos_dpi_probe(struct device *dev); 218struct drm_encoder *exynos_dpi_probe(struct device *dev);
260int exynos_dpi_remove(struct drm_encoder *encoder); 219int exynos_dpi_remove(struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index a1ed6146a3b5..781b82c2c579 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1863,6 +1863,8 @@ err_clk:
1863 1863
1864static const struct dev_pm_ops exynos_dsi_pm_ops = { 1864static const struct dev_pm_ops exynos_dsi_pm_ops = {
1865 SET_RUNTIME_PM_OPS(exynos_dsi_suspend, exynos_dsi_resume, NULL) 1865 SET_RUNTIME_PM_OPS(exynos_dsi_suspend, exynos_dsi_resume, NULL)
1866 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1867 pm_runtime_force_resume)
1866}; 1868};
1867 1869
1868struct platform_driver dsi_driver = { 1870struct platform_driver dsi_driver = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 7fcc1a7ab1a0..9f52382e19ee 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -101,7 +101,6 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
101{ 101{
102 const struct drm_format_info *info = drm_get_format_info(dev, mode_cmd); 102 const struct drm_format_info *info = drm_get_format_info(dev, mode_cmd);
103 struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER]; 103 struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
104 struct drm_gem_object *obj;
105 struct drm_framebuffer *fb; 104 struct drm_framebuffer *fb;
106 int i; 105 int i;
107 int ret; 106 int ret;
@@ -112,15 +111,14 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
112 unsigned long size = height * mode_cmd->pitches[i] + 111 unsigned long size = height * mode_cmd->pitches[i] +
113 mode_cmd->offsets[i]; 112 mode_cmd->offsets[i];
114 113
115 obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); 114 exynos_gem[i] = exynos_drm_gem_get(file_priv,
116 if (!obj) { 115 mode_cmd->handles[i]);
116 if (!exynos_gem[i]) {
117 DRM_ERROR("failed to lookup gem object\n"); 117 DRM_ERROR("failed to lookup gem object\n");
118 ret = -ENOENT; 118 ret = -ENOENT;
119 goto err; 119 goto err;
120 } 120 }
121 121
122 exynos_gem[i] = to_exynos_gem(obj);
123
124 if (size > exynos_gem[i]->size) { 122 if (size > exynos_gem[i]->size) {
125 i++; 123 i++;
126 ret = -EINVAL; 124 ret = -EINVAL;
@@ -138,7 +136,7 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
138 136
139err: 137err:
140 while (i--) 138 while (i--)
141 drm_gem_object_unreference_unlocked(&exynos_gem[i]->base); 139 exynos_drm_gem_put(exynos_gem[i]);
142 140
143 return ERR_PTR(ret); 141 return ERR_PTR(ret);
144} 142}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 6127ef25acd6..e8d0670bb5f8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -470,17 +470,18 @@ static void fimc_src_set_transf(struct fimc_context *ctx, unsigned int rotation)
470static void fimc_set_window(struct fimc_context *ctx, 470static void fimc_set_window(struct fimc_context *ctx,
471 struct exynos_drm_ipp_buffer *buf) 471 struct exynos_drm_ipp_buffer *buf)
472{ 472{
473 unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0];
473 u32 cfg, h1, h2, v1, v2; 474 u32 cfg, h1, h2, v1, v2;
474 475
475 /* cropped image */ 476 /* cropped image */
476 h1 = buf->rect.x; 477 h1 = buf->rect.x;
477 h2 = buf->buf.width - buf->rect.w - buf->rect.x; 478 h2 = real_width - buf->rect.w - buf->rect.x;
478 v1 = buf->rect.y; 479 v1 = buf->rect.y;
479 v2 = buf->buf.height - buf->rect.h - buf->rect.y; 480 v2 = buf->buf.height - buf->rect.h - buf->rect.y;
480 481
481 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n", 482 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
482 buf->rect.x, buf->rect.y, buf->rect.w, buf->rect.h, 483 buf->rect.x, buf->rect.y, buf->rect.w, buf->rect.h,
483 buf->buf.width, buf->buf.height); 484 real_width, buf->buf.height);
484 DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, v2); 485 DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, v2);
485 486
486 /* 487 /*
@@ -503,12 +504,13 @@ static void fimc_set_window(struct fimc_context *ctx,
503static void fimc_src_set_size(struct fimc_context *ctx, 504static void fimc_src_set_size(struct fimc_context *ctx,
504 struct exynos_drm_ipp_buffer *buf) 505 struct exynos_drm_ipp_buffer *buf)
505{ 506{
507 unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0];
506 u32 cfg; 508 u32 cfg;
507 509
508 DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", buf->buf.width, buf->buf.height); 510 DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", real_width, buf->buf.height);
509 511
510 /* original size */ 512 /* original size */
511 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(buf->buf.width) | 513 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(real_width) |
512 EXYNOS_ORGISIZE_VERTICAL(buf->buf.height)); 514 EXYNOS_ORGISIZE_VERTICAL(buf->buf.height));
513 515
514 fimc_write(ctx, cfg, EXYNOS_ORGISIZE); 516 fimc_write(ctx, cfg, EXYNOS_ORGISIZE);
@@ -529,7 +531,7 @@ static void fimc_src_set_size(struct fimc_context *ctx,
529 * for now, we support only ITU601 8 bit mode 531 * for now, we support only ITU601 8 bit mode
530 */ 532 */
531 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT | 533 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT |
532 EXYNOS_CISRCFMT_SOURCEHSIZE(buf->buf.width) | 534 EXYNOS_CISRCFMT_SOURCEHSIZE(real_width) |
533 EXYNOS_CISRCFMT_SOURCEVSIZE(buf->buf.height)); 535 EXYNOS_CISRCFMT_SOURCEVSIZE(buf->buf.height));
534 fimc_write(ctx, cfg, EXYNOS_CISRCFMT); 536 fimc_write(ctx, cfg, EXYNOS_CISRCFMT);
535 537
@@ -842,12 +844,13 @@ static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
842static void fimc_dst_set_size(struct fimc_context *ctx, 844static void fimc_dst_set_size(struct fimc_context *ctx,
843 struct exynos_drm_ipp_buffer *buf) 845 struct exynos_drm_ipp_buffer *buf)
844{ 846{
847 unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0];
845 u32 cfg, cfg_ext; 848 u32 cfg, cfg_ext;
846 849
847 DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", buf->buf.width, buf->buf.height); 850 DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", real_width, buf->buf.height);
848 851
849 /* original size */ 852 /* original size */
850 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(buf->buf.width) | 853 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(real_width) |
851 EXYNOS_ORGOSIZE_VERTICAL(buf->buf.height)); 854 EXYNOS_ORGOSIZE_VERTICAL(buf->buf.height));
852 855
853 fimc_write(ctx, cfg, EXYNOS_ORGOSIZE); 856 fimc_write(ctx, cfg, EXYNOS_ORGOSIZE);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 01b1570d0c3a..b7f56935a46b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -1192,6 +1192,8 @@ static int exynos_fimd_resume(struct device *dev)
1192 1192
1193static const struct dev_pm_ops exynos_fimd_pm_ops = { 1193static const struct dev_pm_ops exynos_fimd_pm_ops = {
1194 SET_RUNTIME_PM_OPS(exynos_fimd_suspend, exynos_fimd_resume, NULL) 1194 SET_RUNTIME_PM_OPS(exynos_fimd_suspend, exynos_fimd_resume, NULL)
1195 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1196 pm_runtime_force_resume)
1195}; 1197};
1196 1198
1197struct platform_driver fimd_driver = { 1199struct platform_driver fimd_driver = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index f68ef1b3a28c..f2481a2014bb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -9,6 +9,7 @@
9 9
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/clk.h> 11#include <linux/clk.h>
12#include <linux/component.h>
12#include <linux/err.h> 13#include <linux/err.h>
13#include <linux/interrupt.h> 14#include <linux/interrupt.h>
14#include <linux/io.h> 15#include <linux/io.h>
@@ -190,7 +191,7 @@ struct g2d_buf_desc {
190struct g2d_buf_info { 191struct g2d_buf_info {
191 unsigned int map_nr; 192 unsigned int map_nr;
192 enum g2d_reg_type reg_types[MAX_REG_TYPE_NR]; 193 enum g2d_reg_type reg_types[MAX_REG_TYPE_NR];
193 unsigned long handles[MAX_REG_TYPE_NR]; 194 void *obj[MAX_REG_TYPE_NR];
194 unsigned int types[MAX_REG_TYPE_NR]; 195 unsigned int types[MAX_REG_TYPE_NR];
195 struct g2d_buf_desc descs[MAX_REG_TYPE_NR]; 196 struct g2d_buf_desc descs[MAX_REG_TYPE_NR];
196}; 197};
@@ -237,7 +238,7 @@ struct g2d_data {
237 int irq; 238 int irq;
238 struct workqueue_struct *g2d_workq; 239 struct workqueue_struct *g2d_workq;
239 struct work_struct runqueue_work; 240 struct work_struct runqueue_work;
240 struct exynos_drm_subdrv subdrv; 241 struct drm_device *drm_dev;
241 unsigned long flags; 242 unsigned long flags;
242 243
243 /* cmdlist */ 244 /* cmdlist */
@@ -268,14 +269,13 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
268{ 269{
269 struct device *dev = g2d->dev; 270 struct device *dev = g2d->dev;
270 struct g2d_cmdlist_node *node = g2d->cmdlist_node; 271 struct g2d_cmdlist_node *node = g2d->cmdlist_node;
271 struct exynos_drm_subdrv *subdrv = &g2d->subdrv;
272 int nr; 272 int nr;
273 int ret; 273 int ret;
274 struct g2d_buf_info *buf_info; 274 struct g2d_buf_info *buf_info;
275 275
276 g2d->cmdlist_dma_attrs = DMA_ATTR_WRITE_COMBINE; 276 g2d->cmdlist_dma_attrs = DMA_ATTR_WRITE_COMBINE;
277 277
278 g2d->cmdlist_pool_virt = dma_alloc_attrs(to_dma_dev(subdrv->drm_dev), 278 g2d->cmdlist_pool_virt = dma_alloc_attrs(to_dma_dev(g2d->drm_dev),
279 G2D_CMDLIST_POOL_SIZE, 279 G2D_CMDLIST_POOL_SIZE,
280 &g2d->cmdlist_pool, GFP_KERNEL, 280 &g2d->cmdlist_pool, GFP_KERNEL,
281 g2d->cmdlist_dma_attrs); 281 g2d->cmdlist_dma_attrs);
@@ -308,7 +308,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
308 return 0; 308 return 0;
309 309
310err: 310err:
311 dma_free_attrs(to_dma_dev(subdrv->drm_dev), G2D_CMDLIST_POOL_SIZE, 311 dma_free_attrs(to_dma_dev(g2d->drm_dev), G2D_CMDLIST_POOL_SIZE,
312 g2d->cmdlist_pool_virt, 312 g2d->cmdlist_pool_virt,
313 g2d->cmdlist_pool, g2d->cmdlist_dma_attrs); 313 g2d->cmdlist_pool, g2d->cmdlist_dma_attrs);
314 return ret; 314 return ret;
@@ -316,12 +316,10 @@ err:
316 316
317static void g2d_fini_cmdlist(struct g2d_data *g2d) 317static void g2d_fini_cmdlist(struct g2d_data *g2d)
318{ 318{
319 struct exynos_drm_subdrv *subdrv = &g2d->subdrv;
320
321 kfree(g2d->cmdlist_node); 319 kfree(g2d->cmdlist_node);
322 320
323 if (g2d->cmdlist_pool_virt && g2d->cmdlist_pool) { 321 if (g2d->cmdlist_pool_virt && g2d->cmdlist_pool) {
324 dma_free_attrs(to_dma_dev(subdrv->drm_dev), 322 dma_free_attrs(to_dma_dev(g2d->drm_dev),
325 G2D_CMDLIST_POOL_SIZE, 323 G2D_CMDLIST_POOL_SIZE,
326 g2d->cmdlist_pool_virt, 324 g2d->cmdlist_pool_virt,
327 g2d->cmdlist_pool, g2d->cmdlist_dma_attrs); 325 g2d->cmdlist_pool, g2d->cmdlist_dma_attrs);
@@ -355,32 +353,31 @@ static void g2d_put_cmdlist(struct g2d_data *g2d, struct g2d_cmdlist_node *node)
355 mutex_unlock(&g2d->cmdlist_mutex); 353 mutex_unlock(&g2d->cmdlist_mutex);
356} 354}
357 355
358static void g2d_add_cmdlist_to_inuse(struct exynos_drm_g2d_private *g2d_priv, 356static void g2d_add_cmdlist_to_inuse(struct drm_exynos_file_private *file_priv,
359 struct g2d_cmdlist_node *node) 357 struct g2d_cmdlist_node *node)
360{ 358{
361 struct g2d_cmdlist_node *lnode; 359 struct g2d_cmdlist_node *lnode;
362 360
363 if (list_empty(&g2d_priv->inuse_cmdlist)) 361 if (list_empty(&file_priv->inuse_cmdlist))
364 goto add_to_list; 362 goto add_to_list;
365 363
366 /* this links to base address of new cmdlist */ 364 /* this links to base address of new cmdlist */
367 lnode = list_entry(g2d_priv->inuse_cmdlist.prev, 365 lnode = list_entry(file_priv->inuse_cmdlist.prev,
368 struct g2d_cmdlist_node, list); 366 struct g2d_cmdlist_node, list);
369 lnode->cmdlist->data[lnode->cmdlist->last] = node->dma_addr; 367 lnode->cmdlist->data[lnode->cmdlist->last] = node->dma_addr;
370 368
371add_to_list: 369add_to_list:
372 list_add_tail(&node->list, &g2d_priv->inuse_cmdlist); 370 list_add_tail(&node->list, &file_priv->inuse_cmdlist);
373 371
374 if (node->event) 372 if (node->event)
375 list_add_tail(&node->event->base.link, &g2d_priv->event_list); 373 list_add_tail(&node->event->base.link, &file_priv->event_list);
376} 374}
377 375
378static void g2d_userptr_put_dma_addr(struct drm_device *drm_dev, 376static void g2d_userptr_put_dma_addr(struct g2d_data *g2d,
379 unsigned long obj, 377 void *obj,
380 bool force) 378 bool force)
381{ 379{
382 struct g2d_cmdlist_userptr *g2d_userptr = 380 struct g2d_cmdlist_userptr *g2d_userptr = obj;
383 (struct g2d_cmdlist_userptr *)obj;
384 struct page **pages; 381 struct page **pages;
385 382
386 if (!obj) 383 if (!obj)
@@ -398,7 +395,7 @@ static void g2d_userptr_put_dma_addr(struct drm_device *drm_dev,
398 return; 395 return;
399 396
400out: 397out:
401 dma_unmap_sg(to_dma_dev(drm_dev), g2d_userptr->sgt->sgl, 398 dma_unmap_sg(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt->sgl,
402 g2d_userptr->sgt->nents, DMA_BIDIRECTIONAL); 399 g2d_userptr->sgt->nents, DMA_BIDIRECTIONAL);
403 400
404 pages = frame_vector_pages(g2d_userptr->vec); 401 pages = frame_vector_pages(g2d_userptr->vec);
@@ -419,16 +416,14 @@ out:
419 kfree(g2d_userptr); 416 kfree(g2d_userptr);
420} 417}
421 418
422static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, 419static dma_addr_t *g2d_userptr_get_dma_addr(struct g2d_data *g2d,
423 unsigned long userptr, 420 unsigned long userptr,
424 unsigned long size, 421 unsigned long size,
425 struct drm_file *filp, 422 struct drm_file *filp,
426 unsigned long *obj) 423 void **obj)
427{ 424{
428 struct drm_exynos_file_private *file_priv = filp->driver_priv; 425 struct drm_exynos_file_private *file_priv = filp->driver_priv;
429 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
430 struct g2d_cmdlist_userptr *g2d_userptr; 426 struct g2d_cmdlist_userptr *g2d_userptr;
431 struct g2d_data *g2d;
432 struct sg_table *sgt; 427 struct sg_table *sgt;
433 unsigned long start, end; 428 unsigned long start, end;
434 unsigned int npages, offset; 429 unsigned int npages, offset;
@@ -439,10 +434,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
439 return ERR_PTR(-EINVAL); 434 return ERR_PTR(-EINVAL);
440 } 435 }
441 436
442 g2d = dev_get_drvdata(g2d_priv->dev);
443
444 /* check if userptr already exists in userptr_list. */ 437 /* check if userptr already exists in userptr_list. */
445 list_for_each_entry(g2d_userptr, &g2d_priv->userptr_list, list) { 438 list_for_each_entry(g2d_userptr, &file_priv->userptr_list, list) {
446 if (g2d_userptr->userptr == userptr) { 439 if (g2d_userptr->userptr == userptr) {
447 /* 440 /*
448 * also check size because there could be same address 441 * also check size because there could be same address
@@ -450,7 +443,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
450 */ 443 */
451 if (g2d_userptr->size == size) { 444 if (g2d_userptr->size == size) {
452 atomic_inc(&g2d_userptr->refcount); 445 atomic_inc(&g2d_userptr->refcount);
453 *obj = (unsigned long)g2d_userptr; 446 *obj = g2d_userptr;
454 447
455 return &g2d_userptr->dma_addr; 448 return &g2d_userptr->dma_addr;
456 } 449 }
@@ -517,7 +510,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
517 510
518 g2d_userptr->sgt = sgt; 511 g2d_userptr->sgt = sgt;
519 512
520 if (!dma_map_sg(to_dma_dev(drm_dev), sgt->sgl, sgt->nents, 513 if (!dma_map_sg(to_dma_dev(g2d->drm_dev), sgt->sgl, sgt->nents,
521 DMA_BIDIRECTIONAL)) { 514 DMA_BIDIRECTIONAL)) {
522 DRM_ERROR("failed to map sgt with dma region.\n"); 515 DRM_ERROR("failed to map sgt with dma region.\n");
523 ret = -ENOMEM; 516 ret = -ENOMEM;
@@ -527,14 +520,14 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
527 g2d_userptr->dma_addr = sgt->sgl[0].dma_address; 520 g2d_userptr->dma_addr = sgt->sgl[0].dma_address;
528 g2d_userptr->userptr = userptr; 521 g2d_userptr->userptr = userptr;
529 522
530 list_add_tail(&g2d_userptr->list, &g2d_priv->userptr_list); 523 list_add_tail(&g2d_userptr->list, &file_priv->userptr_list);
531 524
532 if (g2d->current_pool + (npages << PAGE_SHIFT) < g2d->max_pool) { 525 if (g2d->current_pool + (npages << PAGE_SHIFT) < g2d->max_pool) {
533 g2d->current_pool += npages << PAGE_SHIFT; 526 g2d->current_pool += npages << PAGE_SHIFT;
534 g2d_userptr->in_pool = true; 527 g2d_userptr->in_pool = true;
535 } 528 }
536 529
537 *obj = (unsigned long)g2d_userptr; 530 *obj = g2d_userptr;
538 531
539 return &g2d_userptr->dma_addr; 532 return &g2d_userptr->dma_addr;
540 533
@@ -556,19 +549,14 @@ err_free:
556 return ERR_PTR(ret); 549 return ERR_PTR(ret);
557} 550}
558 551
559static void g2d_userptr_free_all(struct drm_device *drm_dev, 552static void g2d_userptr_free_all(struct g2d_data *g2d, struct drm_file *filp)
560 struct g2d_data *g2d,
561 struct drm_file *filp)
562{ 553{
563 struct drm_exynos_file_private *file_priv = filp->driver_priv; 554 struct drm_exynos_file_private *file_priv = filp->driver_priv;
564 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
565 struct g2d_cmdlist_userptr *g2d_userptr, *n; 555 struct g2d_cmdlist_userptr *g2d_userptr, *n;
566 556
567 list_for_each_entry_safe(g2d_userptr, n, &g2d_priv->userptr_list, list) 557 list_for_each_entry_safe(g2d_userptr, n, &file_priv->userptr_list, list)
568 if (g2d_userptr->in_pool) 558 if (g2d_userptr->in_pool)
569 g2d_userptr_put_dma_addr(drm_dev, 559 g2d_userptr_put_dma_addr(g2d, g2d_userptr, true);
570 (unsigned long)g2d_userptr,
571 true);
572 560
573 g2d->current_pool = 0; 561 g2d->current_pool = 0;
574} 562}
@@ -723,26 +711,23 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
723 buf_desc = &buf_info->descs[reg_type]; 711 buf_desc = &buf_info->descs[reg_type];
724 712
725 if (buf_info->types[reg_type] == BUF_TYPE_GEM) { 713 if (buf_info->types[reg_type] == BUF_TYPE_GEM) {
726 unsigned long size; 714 struct exynos_drm_gem *exynos_gem;
727 715
728 size = exynos_drm_gem_get_size(drm_dev, handle, file); 716 exynos_gem = exynos_drm_gem_get(file, handle);
729 if (!size) { 717 if (!exynos_gem) {
730 ret = -EFAULT; 718 ret = -EFAULT;
731 goto err; 719 goto err;
732 } 720 }
733 721
734 if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type, 722 if (!g2d_check_buf_desc_is_valid(buf_desc,
735 size)) { 723 reg_type, exynos_gem->size)) {
724 exynos_drm_gem_put(exynos_gem);
736 ret = -EFAULT; 725 ret = -EFAULT;
737 goto err; 726 goto err;
738 } 727 }
739 728
740 addr = exynos_drm_gem_get_dma_addr(drm_dev, handle, 729 addr = &exynos_gem->dma_addr;
741 file); 730 buf_info->obj[reg_type] = exynos_gem;
742 if (IS_ERR(addr)) {
743 ret = -EFAULT;
744 goto err;
745 }
746 } else { 731 } else {
747 struct drm_exynos_g2d_userptr g2d_userptr; 732 struct drm_exynos_g2d_userptr g2d_userptr;
748 733
@@ -758,11 +743,11 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
758 goto err; 743 goto err;
759 } 744 }
760 745
761 addr = g2d_userptr_get_dma_addr(drm_dev, 746 addr = g2d_userptr_get_dma_addr(g2d,
762 g2d_userptr.userptr, 747 g2d_userptr.userptr,
763 g2d_userptr.size, 748 g2d_userptr.size,
764 file, 749 file,
765 &handle); 750 &buf_info->obj[reg_type]);
766 if (IS_ERR(addr)) { 751 if (IS_ERR(addr)) {
767 ret = -EFAULT; 752 ret = -EFAULT;
768 goto err; 753 goto err;
@@ -771,7 +756,6 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
771 756
772 cmdlist->data[reg_pos + 1] = *addr; 757 cmdlist->data[reg_pos + 1] = *addr;
773 buf_info->reg_types[i] = reg_type; 758 buf_info->reg_types[i] = reg_type;
774 buf_info->handles[reg_type] = handle;
775 } 759 }
776 760
777 return 0; 761 return 0;
@@ -785,29 +769,26 @@ static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d,
785 struct g2d_cmdlist_node *node, 769 struct g2d_cmdlist_node *node,
786 struct drm_file *filp) 770 struct drm_file *filp)
787{ 771{
788 struct exynos_drm_subdrv *subdrv = &g2d->subdrv;
789 struct g2d_buf_info *buf_info = &node->buf_info; 772 struct g2d_buf_info *buf_info = &node->buf_info;
790 int i; 773 int i;
791 774
792 for (i = 0; i < buf_info->map_nr; i++) { 775 for (i = 0; i < buf_info->map_nr; i++) {
793 struct g2d_buf_desc *buf_desc; 776 struct g2d_buf_desc *buf_desc;
794 enum g2d_reg_type reg_type; 777 enum g2d_reg_type reg_type;
795 unsigned long handle; 778 void *obj;
796 779
797 reg_type = buf_info->reg_types[i]; 780 reg_type = buf_info->reg_types[i];
798 781
799 buf_desc = &buf_info->descs[reg_type]; 782 buf_desc = &buf_info->descs[reg_type];
800 handle = buf_info->handles[reg_type]; 783 obj = buf_info->obj[reg_type];
801 784
802 if (buf_info->types[reg_type] == BUF_TYPE_GEM) 785 if (buf_info->types[reg_type] == BUF_TYPE_GEM)
803 exynos_drm_gem_put_dma_addr(subdrv->drm_dev, handle, 786 exynos_drm_gem_put(obj);
804 filp);
805 else 787 else
806 g2d_userptr_put_dma_addr(subdrv->drm_dev, handle, 788 g2d_userptr_put_dma_addr(g2d, obj, false);
807 false);
808 789
809 buf_info->reg_types[i] = REG_TYPE_NONE; 790 buf_info->reg_types[i] = REG_TYPE_NONE;
810 buf_info->handles[reg_type] = 0; 791 buf_info->obj[reg_type] = NULL;
811 buf_info->types[reg_type] = 0; 792 buf_info->types[reg_type] = 0;
812 memset(buf_desc, 0x00, sizeof(*buf_desc)); 793 memset(buf_desc, 0x00, sizeof(*buf_desc));
813 } 794 }
@@ -922,7 +903,7 @@ static void g2d_runqueue_worker(struct work_struct *work)
922 903
923static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no) 904static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no)
924{ 905{
925 struct drm_device *drm_dev = g2d->subdrv.drm_dev; 906 struct drm_device *drm_dev = g2d->drm_dev;
926 struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node; 907 struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node;
927 struct drm_exynos_pending_g2d_event *e; 908 struct drm_exynos_pending_g2d_event *e;
928 struct timespec64 now; 909 struct timespec64 now;
@@ -1031,7 +1012,7 @@ out:
1031 mutex_unlock(&g2d->runqueue_mutex); 1012 mutex_unlock(&g2d->runqueue_mutex);
1032} 1013}
1033 1014
1034static int g2d_check_reg_offset(struct device *dev, 1015static int g2d_check_reg_offset(struct g2d_data *g2d,
1035 struct g2d_cmdlist_node *node, 1016 struct g2d_cmdlist_node *node,
1036 int nr, bool for_addr) 1017 int nr, bool for_addr)
1037{ 1018{
@@ -1131,7 +1112,7 @@ static int g2d_check_reg_offset(struct device *dev,
1131 return 0; 1112 return 0;
1132 1113
1133err: 1114err:
1134 dev_err(dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]); 1115 dev_err(g2d->dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]);
1135 return -EINVAL; 1116 return -EINVAL;
1136} 1117}
1137 1118
@@ -1139,23 +1120,8 @@ err:
1139int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data, 1120int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data,
1140 struct drm_file *file) 1121 struct drm_file *file)
1141{ 1122{
1142 struct drm_exynos_file_private *file_priv = file->driver_priv;
1143 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
1144 struct device *dev;
1145 struct g2d_data *g2d;
1146 struct drm_exynos_g2d_get_ver *ver = data; 1123 struct drm_exynos_g2d_get_ver *ver = data;
1147 1124
1148 if (!g2d_priv)
1149 return -ENODEV;
1150
1151 dev = g2d_priv->dev;
1152 if (!dev)
1153 return -ENODEV;
1154
1155 g2d = dev_get_drvdata(dev);
1156 if (!g2d)
1157 return -EFAULT;
1158
1159 ver->major = G2D_HW_MAJOR_VER; 1125 ver->major = G2D_HW_MAJOR_VER;
1160 ver->minor = G2D_HW_MINOR_VER; 1126 ver->minor = G2D_HW_MINOR_VER;
1161 1127
@@ -1166,9 +1132,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1166 struct drm_file *file) 1132 struct drm_file *file)
1167{ 1133{
1168 struct drm_exynos_file_private *file_priv = file->driver_priv; 1134 struct drm_exynos_file_private *file_priv = file->driver_priv;
1169 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; 1135 struct exynos_drm_private *priv = drm_dev->dev_private;
1170 struct device *dev; 1136 struct g2d_data *g2d = dev_get_drvdata(priv->g2d_dev);
1171 struct g2d_data *g2d;
1172 struct drm_exynos_g2d_set_cmdlist *req = data; 1137 struct drm_exynos_g2d_set_cmdlist *req = data;
1173 struct drm_exynos_g2d_cmd *cmd; 1138 struct drm_exynos_g2d_cmd *cmd;
1174 struct drm_exynos_pending_g2d_event *e; 1139 struct drm_exynos_pending_g2d_event *e;
@@ -1177,17 +1142,6 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1177 int size; 1142 int size;
1178 int ret; 1143 int ret;
1179 1144
1180 if (!g2d_priv)
1181 return -ENODEV;
1182
1183 dev = g2d_priv->dev;
1184 if (!dev)
1185 return -ENODEV;
1186
1187 g2d = dev_get_drvdata(dev);
1188 if (!g2d)
1189 return -EFAULT;
1190
1191 node = g2d_get_cmdlist(g2d); 1145 node = g2d_get_cmdlist(g2d);
1192 if (!node) 1146 if (!node)
1193 return -ENOMEM; 1147 return -ENOMEM;
@@ -1199,7 +1153,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1199 */ 1153 */
1200 if (req->cmd_nr > G2D_CMDLIST_DATA_NUM || 1154 if (req->cmd_nr > G2D_CMDLIST_DATA_NUM ||
1201 req->cmd_buf_nr > G2D_CMDLIST_DATA_NUM) { 1155 req->cmd_buf_nr > G2D_CMDLIST_DATA_NUM) {
1202 dev_err(dev, "number of submitted G2D commands exceeds limit\n"); 1156 dev_err(g2d->dev, "number of submitted G2D commands exceeds limit\n");
1203 return -EINVAL; 1157 return -EINVAL;
1204 } 1158 }
1205 1159
@@ -1267,7 +1221,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1267 */ 1221 */
1268 size = cmdlist->last + req->cmd_nr * 2 + req->cmd_buf_nr * 2 + 2; 1222 size = cmdlist->last + req->cmd_nr * 2 + req->cmd_buf_nr * 2 + 2;
1269 if (size > G2D_CMDLIST_DATA_NUM) { 1223 if (size > G2D_CMDLIST_DATA_NUM) {
1270 dev_err(dev, "cmdlist size is too big\n"); 1224 dev_err(g2d->dev, "cmdlist size is too big\n");
1271 ret = -EINVAL; 1225 ret = -EINVAL;
1272 goto err_free_event; 1226 goto err_free_event;
1273 } 1227 }
@@ -1282,7 +1236,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1282 } 1236 }
1283 cmdlist->last += req->cmd_nr * 2; 1237 cmdlist->last += req->cmd_nr * 2;
1284 1238
1285 ret = g2d_check_reg_offset(dev, node, req->cmd_nr, false); 1239 ret = g2d_check_reg_offset(g2d, node, req->cmd_nr, false);
1286 if (ret < 0) 1240 if (ret < 0)
1287 goto err_free_event; 1241 goto err_free_event;
1288 1242
@@ -1301,7 +1255,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1301 } 1255 }
1302 cmdlist->last += req->cmd_buf_nr * 2; 1256 cmdlist->last += req->cmd_buf_nr * 2;
1303 1257
1304 ret = g2d_check_reg_offset(dev, node, req->cmd_buf_nr, true); 1258 ret = g2d_check_reg_offset(g2d, node, req->cmd_buf_nr, true);
1305 if (ret < 0) 1259 if (ret < 0)
1306 goto err_free_event; 1260 goto err_free_event;
1307 1261
@@ -1319,7 +1273,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1319 /* tail */ 1273 /* tail */
1320 cmdlist->data[cmdlist->last] = 0; 1274 cmdlist->data[cmdlist->last] = 0;
1321 1275
1322 g2d_add_cmdlist_to_inuse(g2d_priv, node); 1276 g2d_add_cmdlist_to_inuse(file_priv, node);
1323 1277
1324 return 0; 1278 return 0;
1325 1279
@@ -1337,25 +1291,13 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
1337 struct drm_file *file) 1291 struct drm_file *file)
1338{ 1292{
1339 struct drm_exynos_file_private *file_priv = file->driver_priv; 1293 struct drm_exynos_file_private *file_priv = file->driver_priv;
1340 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; 1294 struct exynos_drm_private *priv = drm_dev->dev_private;
1341 struct device *dev; 1295 struct g2d_data *g2d = dev_get_drvdata(priv->g2d_dev);
1342 struct g2d_data *g2d;
1343 struct drm_exynos_g2d_exec *req = data; 1296 struct drm_exynos_g2d_exec *req = data;
1344 struct g2d_runqueue_node *runqueue_node; 1297 struct g2d_runqueue_node *runqueue_node;
1345 struct list_head *run_cmdlist; 1298 struct list_head *run_cmdlist;
1346 struct list_head *event_list; 1299 struct list_head *event_list;
1347 1300
1348 if (!g2d_priv)
1349 return -ENODEV;
1350
1351 dev = g2d_priv->dev;
1352 if (!dev)
1353 return -ENODEV;
1354
1355 g2d = dev_get_drvdata(dev);
1356 if (!g2d)
1357 return -EFAULT;
1358
1359 runqueue_node = kmem_cache_alloc(g2d->runqueue_slab, GFP_KERNEL); 1301 runqueue_node = kmem_cache_alloc(g2d->runqueue_slab, GFP_KERNEL);
1360 if (!runqueue_node) 1302 if (!runqueue_node)
1361 return -ENOMEM; 1303 return -ENOMEM;
@@ -1367,11 +1309,11 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
1367 init_completion(&runqueue_node->complete); 1309 init_completion(&runqueue_node->complete);
1368 runqueue_node->async = req->async; 1310 runqueue_node->async = req->async;
1369 1311
1370 list_splice_init(&g2d_priv->inuse_cmdlist, run_cmdlist); 1312 list_splice_init(&file_priv->inuse_cmdlist, run_cmdlist);
1371 list_splice_init(&g2d_priv->event_list, event_list); 1313 list_splice_init(&file_priv->event_list, event_list);
1372 1314
1373 if (list_empty(run_cmdlist)) { 1315 if (list_empty(run_cmdlist)) {
1374 dev_err(dev, "there is no inuse cmdlist\n"); 1316 dev_err(g2d->dev, "there is no inuse cmdlist\n");
1375 kmem_cache_free(g2d->runqueue_slab, runqueue_node); 1317 kmem_cache_free(g2d->runqueue_slab, runqueue_node);
1376 return -EPERM; 1318 return -EPERM;
1377 } 1319 }
@@ -1395,71 +1337,28 @@ out:
1395 return 0; 1337 return 0;
1396} 1338}
1397 1339
1398static int g2d_subdrv_probe(struct drm_device *drm_dev, struct device *dev) 1340int g2d_open(struct drm_device *drm_dev, struct drm_file *file)
1399{
1400 struct g2d_data *g2d;
1401 int ret;
1402
1403 g2d = dev_get_drvdata(dev);
1404 if (!g2d)
1405 return -EFAULT;
1406
1407 /* allocate dma-aware cmdlist buffer. */
1408 ret = g2d_init_cmdlist(g2d);
1409 if (ret < 0) {
1410 dev_err(dev, "cmdlist init failed\n");
1411 return ret;
1412 }
1413
1414 ret = drm_iommu_attach_device(drm_dev, dev);
1415 if (ret < 0) {
1416 dev_err(dev, "failed to enable iommu.\n");
1417 g2d_fini_cmdlist(g2d);
1418 }
1419
1420 return ret;
1421
1422}
1423
1424static void g2d_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
1425{
1426 drm_iommu_detach_device(drm_dev, dev);
1427}
1428
1429static int g2d_open(struct drm_device *drm_dev, struct device *dev,
1430 struct drm_file *file)
1431{ 1341{
1432 struct drm_exynos_file_private *file_priv = file->driver_priv; 1342 struct drm_exynos_file_private *file_priv = file->driver_priv;
1433 struct exynos_drm_g2d_private *g2d_priv;
1434
1435 g2d_priv = kzalloc(sizeof(*g2d_priv), GFP_KERNEL);
1436 if (!g2d_priv)
1437 return -ENOMEM;
1438 1343
1439 g2d_priv->dev = dev; 1344 INIT_LIST_HEAD(&file_priv->inuse_cmdlist);
1440 file_priv->g2d_priv = g2d_priv; 1345 INIT_LIST_HEAD(&file_priv->event_list);
1441 1346 INIT_LIST_HEAD(&file_priv->userptr_list);
1442 INIT_LIST_HEAD(&g2d_priv->inuse_cmdlist);
1443 INIT_LIST_HEAD(&g2d_priv->event_list);
1444 INIT_LIST_HEAD(&g2d_priv->userptr_list);
1445 1347
1446 return 0; 1348 return 0;
1447} 1349}
1448 1350
1449static void g2d_close(struct drm_device *drm_dev, struct device *dev, 1351void g2d_close(struct drm_device *drm_dev, struct drm_file *file)
1450 struct drm_file *file)
1451{ 1352{
1452 struct drm_exynos_file_private *file_priv = file->driver_priv; 1353 struct drm_exynos_file_private *file_priv = file->driver_priv;
1453 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; 1354 struct exynos_drm_private *priv = drm_dev->dev_private;
1454 struct g2d_data *g2d; 1355 struct g2d_data *g2d;
1455 struct g2d_cmdlist_node *node, *n; 1356 struct g2d_cmdlist_node *node, *n;
1456 1357
1457 if (!dev) 1358 if (!priv->g2d_dev)
1458 return; 1359 return;
1459 1360
1460 g2d = dev_get_drvdata(dev); 1361 g2d = dev_get_drvdata(priv->g2d_dev);
1461 if (!g2d)
1462 return;
1463 1362
1464 /* Remove the runqueue nodes that belong to us. */ 1363 /* Remove the runqueue nodes that belong to us. */
1465 mutex_lock(&g2d->runqueue_mutex); 1364 mutex_lock(&g2d->runqueue_mutex);
@@ -1480,24 +1379,70 @@ static void g2d_close(struct drm_device *drm_dev, struct device *dev,
1480 * Properly unmap these buffers here. 1379 * Properly unmap these buffers here.
1481 */ 1380 */
1482 mutex_lock(&g2d->cmdlist_mutex); 1381 mutex_lock(&g2d->cmdlist_mutex);
1483 list_for_each_entry_safe(node, n, &g2d_priv->inuse_cmdlist, list) { 1382 list_for_each_entry_safe(node, n, &file_priv->inuse_cmdlist, list) {
1484 g2d_unmap_cmdlist_gem(g2d, node, file); 1383 g2d_unmap_cmdlist_gem(g2d, node, file);
1485 list_move_tail(&node->list, &g2d->free_cmdlist); 1384 list_move_tail(&node->list, &g2d->free_cmdlist);
1486 } 1385 }
1487 mutex_unlock(&g2d->cmdlist_mutex); 1386 mutex_unlock(&g2d->cmdlist_mutex);
1488 1387
1489 /* release all g2d_userptr in pool. */ 1388 /* release all g2d_userptr in pool. */
1490 g2d_userptr_free_all(drm_dev, g2d, file); 1389 g2d_userptr_free_all(g2d, file);
1390}
1391
1392static int g2d_bind(struct device *dev, struct device *master, void *data)
1393{
1394 struct g2d_data *g2d = dev_get_drvdata(dev);
1395 struct drm_device *drm_dev = data;
1396 struct exynos_drm_private *priv = drm_dev->dev_private;
1397 int ret;
1398
1399 g2d->drm_dev = drm_dev;
1491 1400
1492 kfree(file_priv->g2d_priv); 1401 /* allocate dma-aware cmdlist buffer. */
1402 ret = g2d_init_cmdlist(g2d);
1403 if (ret < 0) {
1404 dev_err(dev, "cmdlist init failed\n");
1405 return ret;
1406 }
1407
1408 ret = drm_iommu_attach_device(drm_dev, dev);
1409 if (ret < 0) {
1410 dev_err(dev, "failed to enable iommu.\n");
1411 g2d_fini_cmdlist(g2d);
1412 return ret;
1413 }
1414 priv->g2d_dev = dev;
1415
1416 dev_info(dev, "The Exynos G2D (ver %d.%d) successfully registered.\n",
1417 G2D_HW_MAJOR_VER, G2D_HW_MINOR_VER);
1418 return 0;
1419}
1420
1421static void g2d_unbind(struct device *dev, struct device *master, void *data)
1422{
1423 struct g2d_data *g2d = dev_get_drvdata(dev);
1424 struct drm_device *drm_dev = data;
1425 struct exynos_drm_private *priv = drm_dev->dev_private;
1426
1427 /* Suspend operation and wait for engine idle. */
1428 set_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags);
1429 g2d_wait_finish(g2d, NULL);
1430 priv->g2d_dev = NULL;
1431
1432 cancel_work_sync(&g2d->runqueue_work);
1433 drm_iommu_detach_device(g2d->drm_dev, dev);
1493} 1434}
1494 1435
1436static const struct component_ops g2d_component_ops = {
1437 .bind = g2d_bind,
1438 .unbind = g2d_unbind,
1439};
1440
1495static int g2d_probe(struct platform_device *pdev) 1441static int g2d_probe(struct platform_device *pdev)
1496{ 1442{
1497 struct device *dev = &pdev->dev; 1443 struct device *dev = &pdev->dev;
1498 struct resource *res; 1444 struct resource *res;
1499 struct g2d_data *g2d; 1445 struct g2d_data *g2d;
1500 struct exynos_drm_subdrv *subdrv;
1501 int ret; 1446 int ret;
1502 1447
1503 g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL); 1448 g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL);
@@ -1564,22 +1509,12 @@ static int g2d_probe(struct platform_device *pdev)
1564 1509
1565 platform_set_drvdata(pdev, g2d); 1510 platform_set_drvdata(pdev, g2d);
1566 1511
1567 subdrv = &g2d->subdrv; 1512 ret = component_add(dev, &g2d_component_ops);
1568 subdrv->dev = dev;
1569 subdrv->probe = g2d_subdrv_probe;
1570 subdrv->remove = g2d_subdrv_remove;
1571 subdrv->open = g2d_open;
1572 subdrv->close = g2d_close;
1573
1574 ret = exynos_drm_subdrv_register(subdrv);
1575 if (ret < 0) { 1513 if (ret < 0) {
1576 dev_err(dev, "failed to register drm g2d device\n"); 1514 dev_err(dev, "failed to register drm g2d device\n");
1577 goto err_put_clk; 1515 goto err_put_clk;
1578 } 1516 }
1579 1517
1580 dev_info(dev, "The Exynos G2D (ver %d.%d) successfully probed.\n",
1581 G2D_HW_MAJOR_VER, G2D_HW_MINOR_VER);
1582
1583 return 0; 1518 return 0;
1584 1519
1585err_put_clk: 1520err_put_clk:
@@ -1595,12 +1530,7 @@ static int g2d_remove(struct platform_device *pdev)
1595{ 1530{
1596 struct g2d_data *g2d = platform_get_drvdata(pdev); 1531 struct g2d_data *g2d = platform_get_drvdata(pdev);
1597 1532
1598 /* Suspend operation and wait for engine idle. */ 1533 component_del(&pdev->dev, &g2d_component_ops);
1599 set_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags);
1600 g2d_wait_finish(g2d, NULL);
1601
1602 cancel_work_sync(&g2d->runqueue_work);
1603 exynos_drm_subdrv_unregister(&g2d->subdrv);
1604 1534
1605 /* There should be no locking needed here. */ 1535 /* There should be no locking needed here. */
1606 g2d_remove_runqueue_nodes(g2d, NULL); 1536 g2d_remove_runqueue_nodes(g2d, NULL);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.h b/drivers/gpu/drm/exynos/exynos_drm_g2d.h
index 1a9c7ca8c15b..287b2ed8f178 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.h
@@ -14,6 +14,9 @@ extern int exynos_g2d_set_cmdlist_ioctl(struct drm_device *dev, void *data,
14 struct drm_file *file_priv); 14 struct drm_file *file_priv);
15extern int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data, 15extern int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data,
16 struct drm_file *file_priv); 16 struct drm_file *file_priv);
17
18extern int g2d_open(struct drm_device *drm_dev, struct drm_file *file);
19extern void g2d_close(struct drm_device *drm_dev, struct drm_file *file);
17#else 20#else
18static inline int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data, 21static inline int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data,
19 struct drm_file *file_priv) 22 struct drm_file *file_priv)
@@ -33,4 +36,12 @@ static inline int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data,
33{ 36{
34 return -ENODEV; 37 return -ENODEV;
35} 38}
39
40int g2d_open(struct drm_device *drm_dev, struct drm_file *file)
41{
42 return 0;
43}
44
45void g2d_close(struct drm_device *drm_dev, struct drm_file *file)
46{ }
36#endif 47#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 6e1494fa71b4..34ace85feb68 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -143,7 +143,7 @@ static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
143 DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle); 143 DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
144 144
145 /* drop reference from allocate - handle holds it now. */ 145 /* drop reference from allocate - handle holds it now. */
146 drm_gem_object_unreference_unlocked(obj); 146 drm_gem_object_put_unlocked(obj);
147 147
148 return 0; 148 return 0;
149} 149}
@@ -171,26 +171,6 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem)
171 kfree(exynos_gem); 171 kfree(exynos_gem);
172} 172}
173 173
174unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
175 unsigned int gem_handle,
176 struct drm_file *file_priv)
177{
178 struct exynos_drm_gem *exynos_gem;
179 struct drm_gem_object *obj;
180
181 obj = drm_gem_object_lookup(file_priv, gem_handle);
182 if (!obj) {
183 DRM_ERROR("failed to lookup gem object.\n");
184 return 0;
185 }
186
187 exynos_gem = to_exynos_gem(obj);
188
189 drm_gem_object_unreference_unlocked(obj);
190
191 return exynos_gem->size;
192}
193
194static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev, 174static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
195 unsigned long size) 175 unsigned long size)
196{ 176{
@@ -299,43 +279,15 @@ int exynos_drm_gem_map_ioctl(struct drm_device *dev, void *data,
299 &args->offset); 279 &args->offset);
300} 280}
301 281
302dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev, 282struct exynos_drm_gem *exynos_drm_gem_get(struct drm_file *filp,
303 unsigned int gem_handle, 283 unsigned int gem_handle)
304 struct drm_file *filp)
305{
306 struct exynos_drm_gem *exynos_gem;
307 struct drm_gem_object *obj;
308
309 obj = drm_gem_object_lookup(filp, gem_handle);
310 if (!obj) {
311 DRM_ERROR("failed to lookup gem object.\n");
312 return ERR_PTR(-EINVAL);
313 }
314
315 exynos_gem = to_exynos_gem(obj);
316
317 return &exynos_gem->dma_addr;
318}
319
320void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
321 unsigned int gem_handle,
322 struct drm_file *filp)
323{ 284{
324 struct drm_gem_object *obj; 285 struct drm_gem_object *obj;
325 286
326 obj = drm_gem_object_lookup(filp, gem_handle); 287 obj = drm_gem_object_lookup(filp, gem_handle);
327 if (!obj) { 288 if (!obj)
328 DRM_ERROR("failed to lookup gem object.\n"); 289 return NULL;
329 return; 290 return to_exynos_gem(obj);
330 }
331
332 drm_gem_object_unreference_unlocked(obj);
333
334 /*
335 * decrease obj->refcount one more time because we has already
336 * increased it at exynos_drm_gem_get_dma_addr().
337 */
338 drm_gem_object_unreference_unlocked(obj);
339} 291}
340 292
341static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem, 293static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
@@ -383,7 +335,7 @@ int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
383 args->flags = exynos_gem->flags; 335 args->flags = exynos_gem->flags;
384 args->size = exynos_gem->size; 336 args->size = exynos_gem->size;
385 337
386 drm_gem_object_unreference_unlocked(obj); 338 drm_gem_object_put_unlocked(obj);
387 339
388 return 0; 340 return 0;
389} 341}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index 9057d7f1d6ed..d46a62c30812 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -77,32 +77,26 @@ int exynos_drm_gem_map_ioctl(struct drm_device *dev, void *data,
77 struct drm_file *file_priv); 77 struct drm_file *file_priv);
78 78
79/* 79/*
80 * get dma address from gem handle and this function could be used for 80 * get exynos drm object from gem handle, this function could be used for
81 * other drivers such as 2d/3d acceleration drivers. 81 * other drivers such as 2d/3d acceleration drivers.
82 * with this function call, gem object reference count would be increased. 82 * with this function call, gem object reference count would be increased.
83 */ 83 */
84dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev, 84struct exynos_drm_gem *exynos_drm_gem_get(struct drm_file *filp,
85 unsigned int gem_handle, 85 unsigned int gem_handle);
86 struct drm_file *filp);
87 86
88/* 87/*
89 * put dma address from gem handle and this function could be used for 88 * put exynos drm object acquired from exynos_drm_gem_get(),
90 * other drivers such as 2d/3d acceleration drivers. 89 * gem object reference count would be decreased.
91 * with this function call, gem object reference count would be decreased.
92 */ 90 */
93void exynos_drm_gem_put_dma_addr(struct drm_device *dev, 91static inline void exynos_drm_gem_put(struct exynos_drm_gem *exynos_gem)
94 unsigned int gem_handle, 92{
95 struct drm_file *filp); 93 drm_gem_object_put_unlocked(&exynos_gem->base);
94}
96 95
97/* get buffer information to memory region allocated by gem. */ 96/* get buffer information to memory region allocated by gem. */
98int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data, 97int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
99 struct drm_file *file_priv); 98 struct drm_file *file_priv);
100 99
101/* get buffer size to gem handle. */
102unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
103 unsigned int gem_handle,
104 struct drm_file *file_priv);
105
106/* free gem object. */ 100/* free gem object. */
107void exynos_drm_gem_free_object(struct drm_gem_object *obj); 101void exynos_drm_gem_free_object(struct drm_gem_object *obj);
108 102
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 35ac66730563..7ba414b52faa 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -492,21 +492,25 @@ static void gsc_src_set_fmt(struct gsc_context *ctx, u32 fmt)
492 GSC_IN_CHROMA_ORDER_CRCB); 492 GSC_IN_CHROMA_ORDER_CRCB);
493 break; 493 break;
494 case DRM_FORMAT_NV21: 494 case DRM_FORMAT_NV21:
495 cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_2P);
496 break;
495 case DRM_FORMAT_NV61: 497 case DRM_FORMAT_NV61:
496 cfg |= (GSC_IN_CHROMA_ORDER_CRCB | 498 cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV422_2P);
497 GSC_IN_YUV420_2P);
498 break; 499 break;
499 case DRM_FORMAT_YUV422: 500 case DRM_FORMAT_YUV422:
500 cfg |= GSC_IN_YUV422_3P; 501 cfg |= GSC_IN_YUV422_3P;
501 break; 502 break;
502 case DRM_FORMAT_YUV420: 503 case DRM_FORMAT_YUV420:
504 cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_3P);
505 break;
503 case DRM_FORMAT_YVU420: 506 case DRM_FORMAT_YVU420:
504 cfg |= GSC_IN_YUV420_3P; 507 cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_3P);
505 break; 508 break;
506 case DRM_FORMAT_NV12: 509 case DRM_FORMAT_NV12:
510 cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_2P);
511 break;
507 case DRM_FORMAT_NV16: 512 case DRM_FORMAT_NV16:
508 cfg |= (GSC_IN_CHROMA_ORDER_CBCR | 513 cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV422_2P);
509 GSC_IN_YUV420_2P);
510 break; 514 break;
511 } 515 }
512 516
@@ -523,30 +527,30 @@ static void gsc_src_set_transf(struct gsc_context *ctx, unsigned int rotation)
523 527
524 switch (degree) { 528 switch (degree) {
525 case DRM_MODE_ROTATE_0: 529 case DRM_MODE_ROTATE_0:
526 if (rotation & DRM_MODE_REFLECT_Y)
527 cfg |= GSC_IN_ROT_XFLIP;
528 if (rotation & DRM_MODE_REFLECT_X) 530 if (rotation & DRM_MODE_REFLECT_X)
531 cfg |= GSC_IN_ROT_XFLIP;
532 if (rotation & DRM_MODE_REFLECT_Y)
529 cfg |= GSC_IN_ROT_YFLIP; 533 cfg |= GSC_IN_ROT_YFLIP;
530 break; 534 break;
531 case DRM_MODE_ROTATE_90: 535 case DRM_MODE_ROTATE_90:
532 cfg |= GSC_IN_ROT_90; 536 cfg |= GSC_IN_ROT_90;
533 if (rotation & DRM_MODE_REFLECT_Y)
534 cfg |= GSC_IN_ROT_XFLIP;
535 if (rotation & DRM_MODE_REFLECT_X) 537 if (rotation & DRM_MODE_REFLECT_X)
538 cfg |= GSC_IN_ROT_XFLIP;
539 if (rotation & DRM_MODE_REFLECT_Y)
536 cfg |= GSC_IN_ROT_YFLIP; 540 cfg |= GSC_IN_ROT_YFLIP;
537 break; 541 break;
538 case DRM_MODE_ROTATE_180: 542 case DRM_MODE_ROTATE_180:
539 cfg |= GSC_IN_ROT_180; 543 cfg |= GSC_IN_ROT_180;
540 if (rotation & DRM_MODE_REFLECT_Y)
541 cfg &= ~GSC_IN_ROT_XFLIP;
542 if (rotation & DRM_MODE_REFLECT_X) 544 if (rotation & DRM_MODE_REFLECT_X)
545 cfg &= ~GSC_IN_ROT_XFLIP;
546 if (rotation & DRM_MODE_REFLECT_Y)
543 cfg &= ~GSC_IN_ROT_YFLIP; 547 cfg &= ~GSC_IN_ROT_YFLIP;
544 break; 548 break;
545 case DRM_MODE_ROTATE_270: 549 case DRM_MODE_ROTATE_270:
546 cfg |= GSC_IN_ROT_270; 550 cfg |= GSC_IN_ROT_270;
547 if (rotation & DRM_MODE_REFLECT_Y)
548 cfg &= ~GSC_IN_ROT_XFLIP;
549 if (rotation & DRM_MODE_REFLECT_X) 551 if (rotation & DRM_MODE_REFLECT_X)
552 cfg &= ~GSC_IN_ROT_XFLIP;
553 if (rotation & DRM_MODE_REFLECT_Y)
550 cfg &= ~GSC_IN_ROT_YFLIP; 554 cfg &= ~GSC_IN_ROT_YFLIP;
551 break; 555 break;
552 } 556 }
@@ -577,7 +581,7 @@ static void gsc_src_set_size(struct gsc_context *ctx,
577 cfg &= ~(GSC_SRCIMG_HEIGHT_MASK | 581 cfg &= ~(GSC_SRCIMG_HEIGHT_MASK |
578 GSC_SRCIMG_WIDTH_MASK); 582 GSC_SRCIMG_WIDTH_MASK);
579 583
580 cfg |= (GSC_SRCIMG_WIDTH(buf->buf.width) | 584 cfg |= (GSC_SRCIMG_WIDTH(buf->buf.pitch[0] / buf->format->cpp[0]) |
581 GSC_SRCIMG_HEIGHT(buf->buf.height)); 585 GSC_SRCIMG_HEIGHT(buf->buf.height));
582 586
583 gsc_write(cfg, GSC_SRCIMG_SIZE); 587 gsc_write(cfg, GSC_SRCIMG_SIZE);
@@ -672,18 +676,25 @@ static void gsc_dst_set_fmt(struct gsc_context *ctx, u32 fmt)
672 GSC_OUT_CHROMA_ORDER_CRCB); 676 GSC_OUT_CHROMA_ORDER_CRCB);
673 break; 677 break;
674 case DRM_FORMAT_NV21: 678 case DRM_FORMAT_NV21:
675 case DRM_FORMAT_NV61:
676 cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_2P); 679 cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_2P);
677 break; 680 break;
681 case DRM_FORMAT_NV61:
682 cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV422_2P);
683 break;
678 case DRM_FORMAT_YUV422: 684 case DRM_FORMAT_YUV422:
685 cfg |= GSC_OUT_YUV422_3P;
686 break;
679 case DRM_FORMAT_YUV420: 687 case DRM_FORMAT_YUV420:
688 cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_3P);
689 break;
680 case DRM_FORMAT_YVU420: 690 case DRM_FORMAT_YVU420:
681 cfg |= GSC_OUT_YUV420_3P; 691 cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_3P);
682 break; 692 break;
683 case DRM_FORMAT_NV12: 693 case DRM_FORMAT_NV12:
694 cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_2P);
695 break;
684 case DRM_FORMAT_NV16: 696 case DRM_FORMAT_NV16:
685 cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | 697 cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV422_2P);
686 GSC_OUT_YUV420_2P);
687 break; 698 break;
688 } 699 }
689 700
@@ -868,7 +879,7 @@ static void gsc_dst_set_size(struct gsc_context *ctx,
868 /* original size */ 879 /* original size */
869 cfg = gsc_read(GSC_DSTIMG_SIZE); 880 cfg = gsc_read(GSC_DSTIMG_SIZE);
870 cfg &= ~(GSC_DSTIMG_HEIGHT_MASK | GSC_DSTIMG_WIDTH_MASK); 881 cfg &= ~(GSC_DSTIMG_HEIGHT_MASK | GSC_DSTIMG_WIDTH_MASK);
871 cfg |= GSC_DSTIMG_WIDTH(buf->buf.width) | 882 cfg |= GSC_DSTIMG_WIDTH(buf->buf.pitch[0] / buf->format->cpp[0]) |
872 GSC_DSTIMG_HEIGHT(buf->buf.height); 883 GSC_DSTIMG_HEIGHT(buf->buf.height);
873 gsc_write(cfg, GSC_DSTIMG_SIZE); 884 gsc_write(cfg, GSC_DSTIMG_SIZE);
874 885
@@ -1341,7 +1352,7 @@ static const struct drm_exynos_ipp_limit gsc_5420_limits[] = {
1341}; 1352};
1342 1353
1343static const struct drm_exynos_ipp_limit gsc_5433_limits[] = { 1354static const struct drm_exynos_ipp_limit gsc_5433_limits[] = {
1344 { IPP_SIZE_LIMIT(BUFFER, .h = { 32, 8191, 2 }, .v = { 16, 8191, 2 }) }, 1355 { IPP_SIZE_LIMIT(BUFFER, .h = { 32, 8191, 16 }, .v = { 16, 8191, 2 }) },
1345 { IPP_SIZE_LIMIT(AREA, .h = { 16, 4800, 1 }, .v = { 8, 3344, 1 }) }, 1356 { IPP_SIZE_LIMIT(AREA, .h = { 16, 4800, 1 }, .v = { 8, 3344, 1 }) },
1346 { IPP_SIZE_LIMIT(ROTATED, .h = { 32, 2047 }, .v = { 8, 8191 }) }, 1357 { IPP_SIZE_LIMIT(ROTATED, .h = { 32, 2047 }, .v = { 8, 8191 }) },
1347 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 16, (1 << 16) * 8 }, 1358 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 16, (1 << 16) * 8 },
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 26374e58c557..23226a0212e8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -345,39 +345,18 @@ static int exynos_drm_ipp_task_setup_buffer(struct exynos_drm_ipp_buffer *buf,
345 int ret = 0; 345 int ret = 0;
346 int i; 346 int i;
347 347
348 /* basic checks */
349 if (buf->buf.width == 0 || buf->buf.height == 0)
350 return -EINVAL;
351 buf->format = drm_format_info(buf->buf.fourcc);
352 for (i = 0; i < buf->format->num_planes; i++) {
353 unsigned int width = (i == 0) ? buf->buf.width :
354 DIV_ROUND_UP(buf->buf.width, buf->format->hsub);
355
356 if (buf->buf.pitch[i] == 0)
357 buf->buf.pitch[i] = width * buf->format->cpp[i];
358 if (buf->buf.pitch[i] < width * buf->format->cpp[i])
359 return -EINVAL;
360 if (!buf->buf.gem_id[i])
361 return -ENOENT;
362 }
363
364 /* pitch for additional planes must match */
365 if (buf->format->num_planes > 2 &&
366 buf->buf.pitch[1] != buf->buf.pitch[2])
367 return -EINVAL;
368
369 /* get GEM buffers and check their size */ 348 /* get GEM buffers and check their size */
370 for (i = 0; i < buf->format->num_planes; i++) { 349 for (i = 0; i < buf->format->num_planes; i++) {
371 unsigned int height = (i == 0) ? buf->buf.height : 350 unsigned int height = (i == 0) ? buf->buf.height :
372 DIV_ROUND_UP(buf->buf.height, buf->format->vsub); 351 DIV_ROUND_UP(buf->buf.height, buf->format->vsub);
373 unsigned long size = height * buf->buf.pitch[i]; 352 unsigned long size = height * buf->buf.pitch[i];
374 struct drm_gem_object *obj = drm_gem_object_lookup(filp, 353 struct exynos_drm_gem *gem = exynos_drm_gem_get(filp,
375 buf->buf.gem_id[i]); 354 buf->buf.gem_id[i]);
376 if (!obj) { 355 if (!gem) {
377 ret = -ENOENT; 356 ret = -ENOENT;
378 goto gem_free; 357 goto gem_free;
379 } 358 }
380 buf->exynos_gem[i] = to_exynos_gem(obj); 359 buf->exynos_gem[i] = gem;
381 360
382 if (size + buf->buf.offset[i] > buf->exynos_gem[i]->size) { 361 if (size + buf->buf.offset[i] > buf->exynos_gem[i]->size) {
383 i++; 362 i++;
@@ -391,7 +370,7 @@ static int exynos_drm_ipp_task_setup_buffer(struct exynos_drm_ipp_buffer *buf,
391 return 0; 370 return 0;
392gem_free: 371gem_free:
393 while (i--) { 372 while (i--) {
394 drm_gem_object_put_unlocked(&buf->exynos_gem[i]->base); 373 exynos_drm_gem_put(buf->exynos_gem[i]);
395 buf->exynos_gem[i] = NULL; 374 buf->exynos_gem[i] = NULL;
396 } 375 }
397 return ret; 376 return ret;
@@ -404,7 +383,7 @@ static void exynos_drm_ipp_task_release_buf(struct exynos_drm_ipp_buffer *buf)
404 if (!buf->exynos_gem[0]) 383 if (!buf->exynos_gem[0])
405 return; 384 return;
406 for (i = 0; i < buf->format->num_planes; i++) 385 for (i = 0; i < buf->format->num_planes; i++)
407 drm_gem_object_put_unlocked(&buf->exynos_gem[i]->base); 386 exynos_drm_gem_put(buf->exynos_gem[i]);
408} 387}
409 388
410static void exynos_drm_ipp_task_free(struct exynos_drm_ipp *ipp, 389static void exynos_drm_ipp_task_free(struct exynos_drm_ipp *ipp,
@@ -428,7 +407,7 @@ enum drm_ipp_size_id {
428 IPP_LIMIT_BUFFER, IPP_LIMIT_AREA, IPP_LIMIT_ROTATED, IPP_LIMIT_MAX 407 IPP_LIMIT_BUFFER, IPP_LIMIT_AREA, IPP_LIMIT_ROTATED, IPP_LIMIT_MAX
429}; 408};
430 409
431static const enum drm_ipp_size_id limit_id_fallback[IPP_LIMIT_MAX][4] = { 410static const enum drm_exynos_ipp_limit_type limit_id_fallback[IPP_LIMIT_MAX][4] = {
432 [IPP_LIMIT_BUFFER] = { DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER }, 411 [IPP_LIMIT_BUFFER] = { DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER },
433 [IPP_LIMIT_AREA] = { DRM_EXYNOS_IPP_LIMIT_SIZE_AREA, 412 [IPP_LIMIT_AREA] = { DRM_EXYNOS_IPP_LIMIT_SIZE_AREA,
434 DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER }, 413 DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER },
@@ -495,12 +474,13 @@ static int exynos_drm_ipp_check_size_limits(struct exynos_drm_ipp_buffer *buf,
495 enum drm_ipp_size_id id = rotate ? IPP_LIMIT_ROTATED : IPP_LIMIT_AREA; 474 enum drm_ipp_size_id id = rotate ? IPP_LIMIT_ROTATED : IPP_LIMIT_AREA;
496 struct drm_ipp_limit l; 475 struct drm_ipp_limit l;
497 struct drm_exynos_ipp_limit_val *lh = &l.h, *lv = &l.v; 476 struct drm_exynos_ipp_limit_val *lh = &l.h, *lv = &l.v;
477 int real_width = buf->buf.pitch[0] / buf->format->cpp[0];
498 478
499 if (!limits) 479 if (!limits)
500 return 0; 480 return 0;
501 481
502 __get_size_limit(limits, num_limits, IPP_LIMIT_BUFFER, &l); 482 __get_size_limit(limits, num_limits, IPP_LIMIT_BUFFER, &l);
503 if (!__size_limit_check(buf->buf.width, &l.h) || 483 if (!__size_limit_check(real_width, &l.h) ||
504 !__size_limit_check(buf->buf.height, &l.v)) 484 !__size_limit_check(buf->buf.height, &l.v))
505 return -EINVAL; 485 return -EINVAL;
506 486
@@ -560,10 +540,62 @@ static int exynos_drm_ipp_check_scale_limits(
560 return 0; 540 return 0;
561} 541}
562 542
543static int exynos_drm_ipp_check_format(struct exynos_drm_ipp_task *task,
544 struct exynos_drm_ipp_buffer *buf,
545 struct exynos_drm_ipp_buffer *src,
546 struct exynos_drm_ipp_buffer *dst,
547 bool rotate, bool swap)
548{
549 const struct exynos_drm_ipp_formats *fmt;
550 int ret, i;
551
552 fmt = __ipp_format_get(task->ipp, buf->buf.fourcc, buf->buf.modifier,
553 buf == src ? DRM_EXYNOS_IPP_FORMAT_SOURCE :
554 DRM_EXYNOS_IPP_FORMAT_DESTINATION);
555 if (!fmt) {
556 DRM_DEBUG_DRIVER("Task %pK: %s format not supported\n", task,
557 buf == src ? "src" : "dst");
558 return -EINVAL;
559 }
560
561 /* basic checks */
562 if (buf->buf.width == 0 || buf->buf.height == 0)
563 return -EINVAL;
564
565 buf->format = drm_format_info(buf->buf.fourcc);
566 for (i = 0; i < buf->format->num_planes; i++) {
567 unsigned int width = (i == 0) ? buf->buf.width :
568 DIV_ROUND_UP(buf->buf.width, buf->format->hsub);
569
570 if (buf->buf.pitch[i] == 0)
571 buf->buf.pitch[i] = width * buf->format->cpp[i];
572 if (buf->buf.pitch[i] < width * buf->format->cpp[i])
573 return -EINVAL;
574 if (!buf->buf.gem_id[i])
575 return -ENOENT;
576 }
577
578 /* pitch for additional planes must match */
579 if (buf->format->num_planes > 2 &&
580 buf->buf.pitch[1] != buf->buf.pitch[2])
581 return -EINVAL;
582
583 /* check driver limits */
584 ret = exynos_drm_ipp_check_size_limits(buf, fmt->limits,
585 fmt->num_limits,
586 rotate,
587 buf == dst ? swap : false);
588 if (ret)
589 return ret;
590 ret = exynos_drm_ipp_check_scale_limits(&src->rect, &dst->rect,
591 fmt->limits,
592 fmt->num_limits, swap);
593 return ret;
594}
595
563static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task) 596static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task)
564{ 597{
565 struct exynos_drm_ipp *ipp = task->ipp; 598 struct exynos_drm_ipp *ipp = task->ipp;
566 const struct exynos_drm_ipp_formats *src_fmt, *dst_fmt;
567 struct exynos_drm_ipp_buffer *src = &task->src, *dst = &task->dst; 599 struct exynos_drm_ipp_buffer *src = &task->src, *dst = &task->dst;
568 unsigned int rotation = task->transform.rotation; 600 unsigned int rotation = task->transform.rotation;
569 int ret = 0; 601 int ret = 0;
@@ -607,37 +639,11 @@ static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task)
607 return -EINVAL; 639 return -EINVAL;
608 } 640 }
609 641
610 src_fmt = __ipp_format_get(ipp, src->buf.fourcc, src->buf.modifier, 642 ret = exynos_drm_ipp_check_format(task, src, src, dst, rotate, swap);
611 DRM_EXYNOS_IPP_FORMAT_SOURCE);
612 if (!src_fmt) {
613 DRM_DEBUG_DRIVER("Task %pK: src format not supported\n", task);
614 return -EINVAL;
615 }
616 ret = exynos_drm_ipp_check_size_limits(src, src_fmt->limits,
617 src_fmt->num_limits,
618 rotate, false);
619 if (ret)
620 return ret;
621 ret = exynos_drm_ipp_check_scale_limits(&src->rect, &dst->rect,
622 src_fmt->limits,
623 src_fmt->num_limits, swap);
624 if (ret) 643 if (ret)
625 return ret; 644 return ret;
626 645
627 dst_fmt = __ipp_format_get(ipp, dst->buf.fourcc, dst->buf.modifier, 646 ret = exynos_drm_ipp_check_format(task, dst, src, dst, false, swap);
628 DRM_EXYNOS_IPP_FORMAT_DESTINATION);
629 if (!dst_fmt) {
630 DRM_DEBUG_DRIVER("Task %pK: dst format not supported\n", task);
631 return -EINVAL;
632 }
633 ret = exynos_drm_ipp_check_size_limits(dst, dst_fmt->limits,
634 dst_fmt->num_limits,
635 false, swap);
636 if (ret)
637 return ret;
638 ret = exynos_drm_ipp_check_scale_limits(&src->rect, &dst->rect,
639 dst_fmt->limits,
640 dst_fmt->num_limits, swap);
641 if (ret) 647 if (ret)
642 return ret; 648 return ret;
643 649
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index 2174814273e2..2fd299a58297 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -367,6 +367,8 @@ static int exynos_mic_resume(struct device *dev)
367 367
368static const struct dev_pm_ops exynos_mic_pm_ops = { 368static const struct dev_pm_ops exynos_mic_pm_ops = {
369 SET_RUNTIME_PM_OPS(exynos_mic_suspend, exynos_mic_resume, NULL) 369 SET_RUNTIME_PM_OPS(exynos_mic_suspend, exynos_mic_resume, NULL)
370 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
371 pm_runtime_force_resume)
370}; 372};
371 373
372static int exynos_mic_probe(struct platform_device *pdev) 374static int exynos_mic_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index eb9915da7dec..dba29aec59b4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -132,7 +132,7 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
132 if (plane->state) { 132 if (plane->state) {
133 exynos_state = to_exynos_plane_state(plane->state); 133 exynos_state = to_exynos_plane_state(plane->state);
134 if (exynos_state->base.fb) 134 if (exynos_state->base.fb)
135 drm_framebuffer_unreference(exynos_state->base.fb); 135 drm_framebuffer_put(exynos_state->base.fb);
136 kfree(exynos_state); 136 kfree(exynos_state);
137 plane->state = NULL; 137 plane->state = NULL;
138 } 138 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index 1a76dd3d52e1..a820a68429b9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -168,9 +168,9 @@ static void rotator_dst_set_transf(struct rot_context *rot,
168 val &= ~ROT_CONTROL_FLIP_MASK; 168 val &= ~ROT_CONTROL_FLIP_MASK;
169 169
170 if (rotation & DRM_MODE_REFLECT_X) 170 if (rotation & DRM_MODE_REFLECT_X)
171 val |= ROT_CONTROL_FLIP_HORIZONTAL;
172 if (rotation & DRM_MODE_REFLECT_Y)
173 val |= ROT_CONTROL_FLIP_VERTICAL; 171 val |= ROT_CONTROL_FLIP_VERTICAL;
172 if (rotation & DRM_MODE_REFLECT_Y)
173 val |= ROT_CONTROL_FLIP_HORIZONTAL;
174 174
175 val &= ~ROT_CONTROL_ROT_MASK; 175 val &= ~ROT_CONTROL_ROT_MASK;
176 176
diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
index 91d4382343d0..0ddb6eec7b11 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
@@ -30,6 +30,7 @@
30#define scaler_write(cfg, offset) writel(cfg, scaler->regs + (offset)) 30#define scaler_write(cfg, offset) writel(cfg, scaler->regs + (offset))
31#define SCALER_MAX_CLK 4 31#define SCALER_MAX_CLK 4
32#define SCALER_AUTOSUSPEND_DELAY 2000 32#define SCALER_AUTOSUSPEND_DELAY 2000
33#define SCALER_RESET_WAIT_RETRIES 100
33 34
34struct scaler_data { 35struct scaler_data {
35 const char *clk_name[SCALER_MAX_CLK]; 36 const char *clk_name[SCALER_MAX_CLK];
@@ -51,9 +52,9 @@ struct scaler_context {
51static u32 scaler_get_format(u32 drm_fmt) 52static u32 scaler_get_format(u32 drm_fmt)
52{ 53{
53 switch (drm_fmt) { 54 switch (drm_fmt) {
54 case DRM_FORMAT_NV21:
55 return SCALER_YUV420_2P_UV;
56 case DRM_FORMAT_NV12: 55 case DRM_FORMAT_NV12:
56 return SCALER_YUV420_2P_UV;
57 case DRM_FORMAT_NV21:
57 return SCALER_YUV420_2P_VU; 58 return SCALER_YUV420_2P_VU;
58 case DRM_FORMAT_YUV420: 59 case DRM_FORMAT_YUV420:
59 return SCALER_YUV420_3P; 60 return SCALER_YUV420_3P;
@@ -63,15 +64,15 @@ static u32 scaler_get_format(u32 drm_fmt)
63 return SCALER_YUV422_1P_UYVY; 64 return SCALER_YUV422_1P_UYVY;
64 case DRM_FORMAT_YVYU: 65 case DRM_FORMAT_YVYU:
65 return SCALER_YUV422_1P_YVYU; 66 return SCALER_YUV422_1P_YVYU;
66 case DRM_FORMAT_NV61:
67 return SCALER_YUV422_2P_UV;
68 case DRM_FORMAT_NV16: 67 case DRM_FORMAT_NV16:
68 return SCALER_YUV422_2P_UV;
69 case DRM_FORMAT_NV61:
69 return SCALER_YUV422_2P_VU; 70 return SCALER_YUV422_2P_VU;
70 case DRM_FORMAT_YUV422: 71 case DRM_FORMAT_YUV422:
71 return SCALER_YUV422_3P; 72 return SCALER_YUV422_3P;
72 case DRM_FORMAT_NV42:
73 return SCALER_YUV444_2P_UV;
74 case DRM_FORMAT_NV24: 73 case DRM_FORMAT_NV24:
74 return SCALER_YUV444_2P_UV;
75 case DRM_FORMAT_NV42:
75 return SCALER_YUV444_2P_VU; 76 return SCALER_YUV444_2P_VU;
76 case DRM_FORMAT_YUV444: 77 case DRM_FORMAT_YUV444:
77 return SCALER_YUV444_3P; 78 return SCALER_YUV444_3P;
@@ -100,6 +101,23 @@ static u32 scaler_get_format(u32 drm_fmt)
100 return 0; 101 return 0;
101} 102}
102 103
104static inline int scaler_reset(struct scaler_context *scaler)
105{
106 int retry = SCALER_RESET_WAIT_RETRIES;
107
108 scaler_write(SCALER_CFG_SOFT_RESET, SCALER_CFG);
109 do {
110 cpu_relax();
111 } while (retry > 1 &&
112 scaler_read(SCALER_CFG) & SCALER_CFG_SOFT_RESET);
113 do {
114 cpu_relax();
115 scaler_write(1, SCALER_INT_EN);
116 } while (retry > 0 && scaler_read(SCALER_INT_EN) != 1);
117
118 return retry ? 0 : -EIO;
119}
120
103static inline void scaler_enable_int(struct scaler_context *scaler) 121static inline void scaler_enable_int(struct scaler_context *scaler)
104{ 122{
105 u32 val; 123 u32 val;
@@ -354,9 +372,13 @@ static int scaler_commit(struct exynos_drm_ipp *ipp,
354 u32 dst_fmt = scaler_get_format(task->dst.buf.fourcc); 372 u32 dst_fmt = scaler_get_format(task->dst.buf.fourcc);
355 struct drm_exynos_ipp_task_rect *dst_pos = &task->dst.rect; 373 struct drm_exynos_ipp_task_rect *dst_pos = &task->dst.rect;
356 374
357 scaler->task = task;
358
359 pm_runtime_get_sync(scaler->dev); 375 pm_runtime_get_sync(scaler->dev);
376 if (scaler_reset(scaler)) {
377 pm_runtime_put(scaler->dev);
378 return -EIO;
379 }
380
381 scaler->task = task;
360 382
361 scaler_set_src_fmt(scaler, src_fmt); 383 scaler_set_src_fmt(scaler, src_fmt);
362 scaler_set_src_base(scaler, &task->src); 384 scaler_set_src_base(scaler, &task->src);
@@ -394,7 +416,11 @@ static inline void scaler_disable_int(struct scaler_context *scaler)
394 416
395static inline u32 scaler_get_int_status(struct scaler_context *scaler) 417static inline u32 scaler_get_int_status(struct scaler_context *scaler)
396{ 418{
397 return scaler_read(SCALER_INT_STATUS); 419 u32 val = scaler_read(SCALER_INT_STATUS);
420
421 scaler_write(val, SCALER_INT_STATUS);
422
423 return val;
398} 424}
399 425
400static inline int scaler_task_done(u32 val) 426static inline int scaler_task_done(u32 val)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 3a11c719a580..2092a650df7d 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -2093,6 +2093,8 @@ static int __maybe_unused exynos_hdmi_resume(struct device *dev)
2093 2093
2094static const struct dev_pm_ops exynos_hdmi_pm_ops = { 2094static const struct dev_pm_ops exynos_hdmi_pm_ops = {
2095 SET_RUNTIME_PM_OPS(exynos_hdmi_suspend, exynos_hdmi_resume, NULL) 2095 SET_RUNTIME_PM_OPS(exynos_hdmi_suspend, exynos_hdmi_resume, NULL)
2096 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
2097 pm_runtime_force_resume)
2096}; 2098};
2097 2099
2098struct platform_driver hdmi_driver = { 2100struct platform_driver hdmi_driver = {
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 272c79f5f5bf..ffbf4a950f69 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -837,8 +837,6 @@ static int mixer_initialize(struct mixer_context *mixer_ctx,
837 struct drm_device *drm_dev) 837 struct drm_device *drm_dev)
838{ 838{
839 int ret; 839 int ret;
840 struct exynos_drm_private *priv;
841 priv = drm_dev->dev_private;
842 840
843 mixer_ctx->drm_dev = drm_dev; 841 mixer_ctx->drm_dev = drm_dev;
844 842
@@ -1271,6 +1269,8 @@ static int __maybe_unused exynos_mixer_resume(struct device *dev)
1271 1269
1272static const struct dev_pm_ops exynos_mixer_pm_ops = { 1270static const struct dev_pm_ops exynos_mixer_pm_ops = {
1273 SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL) 1271 SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL)
1272 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1273 pm_runtime_force_resume)
1274}; 1274};
1275 1275
1276struct platform_driver mixer_driver = { 1276struct platform_driver mixer_driver = {
diff --git a/drivers/gpu/drm/exynos/regs-gsc.h b/drivers/gpu/drm/exynos/regs-gsc.h
index 4704a993cbb7..16b39734115c 100644
--- a/drivers/gpu/drm/exynos/regs-gsc.h
+++ b/drivers/gpu/drm/exynos/regs-gsc.h
@@ -138,6 +138,7 @@
138#define GSC_OUT_YUV420_3P (3 << 4) 138#define GSC_OUT_YUV420_3P (3 << 4)
139#define GSC_OUT_YUV422_1P (4 << 4) 139#define GSC_OUT_YUV422_1P (4 << 4)
140#define GSC_OUT_YUV422_2P (5 << 4) 140#define GSC_OUT_YUV422_2P (5 << 4)
141#define GSC_OUT_YUV422_3P (6 << 4)
141#define GSC_OUT_YUV444 (7 << 4) 142#define GSC_OUT_YUV444 (7 << 4)
142#define GSC_OUT_TILE_TYPE_MASK (1 << 2) 143#define GSC_OUT_TILE_TYPE_MASK (1 << 2)
143#define GSC_OUT_TILE_C_16x8 (0 << 2) 144#define GSC_OUT_TILE_C_16x8 (0 << 2)