diff options
author | Joonyoung Shim <jy0922.shim@samsung.com> | 2011-12-08 03:54:07 -0500 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2011-12-21 01:14:17 -0500 |
commit | 864ee9e6f643b479e0469c9865cae238590d5f6e (patch) | |
tree | dcb8ad130f42bac96fe3f03a234ffbcbe0c58bd2 /drivers/gpu | |
parent | cb91f6a078097cdfe23bc1bd997e4310b06b87a3 (diff) |
drm/exynos: Add plane support with fimd
The exynos fimd supports 5 window overlays. Only one window overlay of
fimd is used by the crtc, so we need plane feature to use the rest
window overlays.
This creates one ioctl exynos specific - DRM_EXYNOS_PLANE_SET_ZPOS, it
is the ioctl to decide for user to assign which window overlay.
Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/exynos/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_encoder.c | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_encoder.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_plane.c | 163 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_plane.h | 14 |
9 files changed, 244 insertions, 15 deletions
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 0496d3ff2683..c99127214f8e 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile | |||
@@ -5,7 +5,8 @@ | |||
5 | ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos | 5 | ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos |
6 | exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ | 6 | exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ |
7 | exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ | 7 | exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ |
8 | exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o | 8 | exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ |
9 | exynos_drm_plane.o | ||
9 | 10 | ||
10 | obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o | 11 | obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o |
11 | obj-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o | 12 | obj-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index a435c3390332..e1ce9fd5a160 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c | |||
@@ -380,6 +380,7 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) | |||
380 | 380 | ||
381 | exynos_crtc->pipe = nr; | 381 | exynos_crtc->pipe = nr; |
382 | exynos_crtc->dpms = DRM_MODE_DPMS_OFF; | 382 | exynos_crtc->dpms = DRM_MODE_DPMS_OFF; |
383 | exynos_crtc->overlay.zpos = DEFAULT_ZPOS; | ||
383 | crtc = &exynos_crtc->drm_crtc; | 384 | crtc = &exynos_crtc->drm_crtc; |
384 | 385 | ||
385 | private->crtc[nr] = crtc; | 386 | private->crtc[nr] = crtc; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index b86a04bd9399..050684ceab9d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "exynos_drm_fbdev.h" | 36 | #include "exynos_drm_fbdev.h" |
37 | #include "exynos_drm_fb.h" | 37 | #include "exynos_drm_fb.h" |
38 | #include "exynos_drm_gem.h" | 38 | #include "exynos_drm_gem.h" |
39 | #include "exynos_drm_plane.h" | ||
39 | 40 | ||
40 | #define DRIVER_NAME "exynos-drm" | 41 | #define DRIVER_NAME "exynos-drm" |
41 | #define DRIVER_DESC "Samsung SoC DRM" | 42 | #define DRIVER_DESC "Samsung SoC DRM" |
@@ -77,6 +78,12 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) | |||
77 | goto err_crtc; | 78 | goto err_crtc; |
78 | } | 79 | } |
79 | 80 | ||
81 | for (nr = 0; nr < MAX_PLANE; nr++) { | ||
82 | ret = exynos_plane_init(dev, nr); | ||
83 | if (ret) | ||
84 | goto err_crtc; | ||
85 | } | ||
86 | |||
80 | ret = drm_vblank_init(dev, MAX_CRTC); | 87 | ret = drm_vblank_init(dev, MAX_CRTC); |
81 | if (ret) | 88 | if (ret) |
82 | goto err_crtc; | 89 | goto err_crtc; |
@@ -163,6 +170,8 @@ static struct drm_ioctl_desc exynos_ioctls[] = { | |||
163 | DRM_AUTH), | 170 | DRM_AUTH), |
164 | DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, | 171 | DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, |
165 | exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), | 172 | exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), |
173 | DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS, exynos_plane_set_zpos_ioctl, | ||
174 | DRM_UNLOCKED | DRM_AUTH), | ||
166 | }; | 175 | }; |
167 | 176 | ||
168 | static const struct file_operations exynos_drm_driver_fops = { | 177 | static const struct file_operations exynos_drm_driver_fops = { |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 8018798710df..8e8d8f0f8f33 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
@@ -33,6 +33,8 @@ | |||
33 | #include "drm.h" | 33 | #include "drm.h" |
34 | 34 | ||
35 | #define MAX_CRTC 2 | 35 | #define MAX_CRTC 2 |
36 | #define MAX_PLANE 5 | ||
37 | #define DEFAULT_ZPOS -1 | ||
36 | 38 | ||
37 | struct drm_device; | 39 | struct drm_device; |
38 | struct exynos_drm_overlay; | 40 | struct exynos_drm_overlay; |
@@ -57,8 +59,8 @@ enum exynos_drm_output_type { | |||
57 | struct exynos_drm_overlay_ops { | 59 | struct exynos_drm_overlay_ops { |
58 | void (*mode_set)(struct device *subdrv_dev, | 60 | void (*mode_set)(struct device *subdrv_dev, |
59 | struct exynos_drm_overlay *overlay); | 61 | struct exynos_drm_overlay *overlay); |
60 | void (*commit)(struct device *subdrv_dev); | 62 | void (*commit)(struct device *subdrv_dev, int zpos); |
61 | void (*disable)(struct device *subdrv_dev); | 63 | void (*disable)(struct device *subdrv_dev, int zpos); |
62 | }; | 64 | }; |
63 | 65 | ||
64 | /* | 66 | /* |
@@ -83,6 +85,7 @@ struct exynos_drm_overlay_ops { | |||
83 | * @dma_addr: bus(accessed by dma) address to the memory region allocated | 85 | * @dma_addr: bus(accessed by dma) address to the memory region allocated |
84 | * for a overlay. | 86 | * for a overlay. |
85 | * @vaddr: virtual memory addresss to this overlay. | 87 | * @vaddr: virtual memory addresss to this overlay. |
88 | * @zpos: order of overlay layer(z position). | ||
86 | * @default_win: a window to be enabled. | 89 | * @default_win: a window to be enabled. |
87 | * @color_key: color key on or off. | 90 | * @color_key: color key on or off. |
88 | * @index_color: if using color key feature then this value would be used | 91 | * @index_color: if using color key feature then this value would be used |
@@ -111,6 +114,7 @@ struct exynos_drm_overlay { | |||
111 | unsigned int pitch; | 114 | unsigned int pitch; |
112 | dma_addr_t dma_addr; | 115 | dma_addr_t dma_addr; |
113 | void __iomem *vaddr; | 116 | void __iomem *vaddr; |
117 | int zpos; | ||
114 | 118 | ||
115 | bool default_win; | 119 | bool default_win; |
116 | bool color_key; | 120 | bool color_key; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 4ff4a217c1d6..86b93dde219a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c | |||
@@ -294,12 +294,27 @@ void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data) | |||
294 | manager_ops->disable_vblank(manager->dev); | 294 | manager_ops->disable_vblank(manager->dev); |
295 | } | 295 | } |
296 | 296 | ||
297 | void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) | 297 | void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder, |
298 | void *data) | ||
298 | { | 299 | { |
299 | struct exynos_drm_manager *manager = | 300 | struct exynos_drm_manager *manager = |
300 | to_exynos_encoder(encoder)->manager; | 301 | to_exynos_encoder(encoder)->manager; |
301 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; | 302 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; |
303 | int zpos = DEFAULT_ZPOS; | ||
304 | |||
305 | if (data) | ||
306 | zpos = *(int *)data; | ||
307 | |||
308 | if (overlay_ops && overlay_ops->commit) | ||
309 | overlay_ops->commit(manager->dev, zpos); | ||
310 | } | ||
311 | |||
312 | void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) | ||
313 | { | ||
314 | struct exynos_drm_manager *manager = | ||
315 | to_exynos_encoder(encoder)->manager; | ||
302 | int crtc = *(int *)data; | 316 | int crtc = *(int *)data; |
317 | int zpos = DEFAULT_ZPOS; | ||
303 | 318 | ||
304 | DRM_DEBUG_KMS("%s\n", __FILE__); | 319 | DRM_DEBUG_KMS("%s\n", __FILE__); |
305 | 320 | ||
@@ -309,8 +324,7 @@ void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) | |||
309 | */ | 324 | */ |
310 | manager->pipe = crtc; | 325 | manager->pipe = crtc; |
311 | 326 | ||
312 | if (overlay_ops && overlay_ops->commit) | 327 | exynos_drm_encoder_crtc_plane_commit(encoder, &zpos); |
313 | overlay_ops->commit(manager->dev); | ||
314 | } | 328 | } |
315 | 329 | ||
316 | void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, void *data) | 330 | void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, void *data) |
@@ -375,11 +389,15 @@ void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data) | |||
375 | struct exynos_drm_manager *manager = | 389 | struct exynos_drm_manager *manager = |
376 | to_exynos_encoder(encoder)->manager; | 390 | to_exynos_encoder(encoder)->manager; |
377 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; | 391 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; |
392 | int zpos = DEFAULT_ZPOS; | ||
378 | 393 | ||
379 | DRM_DEBUG_KMS("\n"); | 394 | DRM_DEBUG_KMS("\n"); |
380 | 395 | ||
396 | if (data) | ||
397 | zpos = *(int *)data; | ||
398 | |||
381 | if (overlay_ops && overlay_ops->disable) | 399 | if (overlay_ops && overlay_ops->disable) |
382 | overlay_ops->disable(manager->dev); | 400 | overlay_ops->disable(manager->dev, zpos); |
383 | } | 401 | } |
384 | 402 | ||
385 | MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); | 403 | MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h index 72f15b021c43..97b087a51cb6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h | |||
@@ -39,6 +39,8 @@ void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, | |||
39 | void (*fn)(struct drm_encoder *, void *)); | 39 | void (*fn)(struct drm_encoder *, void *)); |
40 | void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data); | 40 | void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data); |
41 | void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); | 41 | void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); |
42 | void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder, | ||
43 | void *data); | ||
42 | void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data); | 44 | void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data); |
43 | void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, | 45 | void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, |
44 | void *data); | 46 | void *data); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 0b76bc058bca..fe4172e48ad2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
@@ -161,12 +161,15 @@ static void fimd_apply(struct device *subdrv_dev) | |||
161 | struct exynos_drm_manager_ops *mgr_ops = mgr->ops; | 161 | struct exynos_drm_manager_ops *mgr_ops = mgr->ops; |
162 | struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops; | 162 | struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops; |
163 | struct fimd_win_data *win_data; | 163 | struct fimd_win_data *win_data; |
164 | int i; | ||
164 | 165 | ||
165 | DRM_DEBUG_KMS("%s\n", __FILE__); | 166 | DRM_DEBUG_KMS("%s\n", __FILE__); |
166 | 167 | ||
167 | win_data = &ctx->win_data[ctx->default_win]; | 168 | for (i = 0; i < WINDOWS_NR; i++) { |
168 | if (win_data->enabled && (ovl_ops && ovl_ops->commit)) | 169 | win_data = &ctx->win_data[i]; |
169 | ovl_ops->commit(subdrv_dev); | 170 | if (win_data->enabled && (ovl_ops && ovl_ops->commit)) |
171 | ovl_ops->commit(subdrv_dev, i); | ||
172 | } | ||
170 | 173 | ||
171 | if (mgr_ops && mgr_ops->commit) | 174 | if (mgr_ops && mgr_ops->commit) |
172 | mgr_ops->commit(subdrv_dev); | 175 | mgr_ops->commit(subdrv_dev); |
@@ -277,6 +280,7 @@ static void fimd_win_mode_set(struct device *dev, | |||
277 | { | 280 | { |
278 | struct fimd_context *ctx = get_fimd_context(dev); | 281 | struct fimd_context *ctx = get_fimd_context(dev); |
279 | struct fimd_win_data *win_data; | 282 | struct fimd_win_data *win_data; |
283 | int win; | ||
280 | unsigned long offset; | 284 | unsigned long offset; |
281 | 285 | ||
282 | DRM_DEBUG_KMS("%s\n", __FILE__); | 286 | DRM_DEBUG_KMS("%s\n", __FILE__); |
@@ -286,12 +290,19 @@ static void fimd_win_mode_set(struct device *dev, | |||
286 | return; | 290 | return; |
287 | } | 291 | } |
288 | 292 | ||
293 | win = overlay->zpos; | ||
294 | if (win == DEFAULT_ZPOS) | ||
295 | win = ctx->default_win; | ||
296 | |||
297 | if (win < 0 || win > WINDOWS_NR) | ||
298 | return; | ||
299 | |||
289 | offset = overlay->fb_x * (overlay->bpp >> 3); | 300 | offset = overlay->fb_x * (overlay->bpp >> 3); |
290 | offset += overlay->fb_y * overlay->pitch; | 301 | offset += overlay->fb_y * overlay->pitch; |
291 | 302 | ||
292 | DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch); | 303 | DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch); |
293 | 304 | ||
294 | win_data = &ctx->win_data[ctx->default_win]; | 305 | win_data = &ctx->win_data[win]; |
295 | 306 | ||
296 | win_data->offset_x = overlay->crtc_x; | 307 | win_data->offset_x = overlay->crtc_x; |
297 | win_data->offset_y = overlay->crtc_y; | 308 | win_data->offset_y = overlay->crtc_y; |
@@ -394,15 +405,18 @@ static void fimd_win_set_colkey(struct device *dev, unsigned int win) | |||
394 | writel(keycon1, ctx->regs + WKEYCON1_BASE(win)); | 405 | writel(keycon1, ctx->regs + WKEYCON1_BASE(win)); |
395 | } | 406 | } |
396 | 407 | ||
397 | static void fimd_win_commit(struct device *dev) | 408 | static void fimd_win_commit(struct device *dev, int zpos) |
398 | { | 409 | { |
399 | struct fimd_context *ctx = get_fimd_context(dev); | 410 | struct fimd_context *ctx = get_fimd_context(dev); |
400 | struct fimd_win_data *win_data; | 411 | struct fimd_win_data *win_data; |
401 | int win = ctx->default_win; | 412 | int win = zpos; |
402 | unsigned long val, alpha, size; | 413 | unsigned long val, alpha, size; |
403 | 414 | ||
404 | DRM_DEBUG_KMS("%s\n", __FILE__); | 415 | DRM_DEBUG_KMS("%s\n", __FILE__); |
405 | 416 | ||
417 | if (win == DEFAULT_ZPOS) | ||
418 | win = ctx->default_win; | ||
419 | |||
406 | if (win < 0 || win > WINDOWS_NR) | 420 | if (win < 0 || win > WINDOWS_NR) |
407 | return; | 421 | return; |
408 | 422 | ||
@@ -499,15 +513,18 @@ static void fimd_win_commit(struct device *dev) | |||
499 | win_data->enabled = true; | 513 | win_data->enabled = true; |
500 | } | 514 | } |
501 | 515 | ||
502 | static void fimd_win_disable(struct device *dev) | 516 | static void fimd_win_disable(struct device *dev, int zpos) |
503 | { | 517 | { |
504 | struct fimd_context *ctx = get_fimd_context(dev); | 518 | struct fimd_context *ctx = get_fimd_context(dev); |
505 | struct fimd_win_data *win_data; | 519 | struct fimd_win_data *win_data; |
506 | int win = ctx->default_win; | 520 | int win = zpos; |
507 | u32 val; | 521 | u32 val; |
508 | 522 | ||
509 | DRM_DEBUG_KMS("%s\n", __FILE__); | 523 | DRM_DEBUG_KMS("%s\n", __FILE__); |
510 | 524 | ||
525 | if (win == DEFAULT_ZPOS) | ||
526 | win = ctx->default_win; | ||
527 | |||
511 | if (win < 0 || win > WINDOWS_NR) | 528 | if (win < 0 || win > WINDOWS_NR) |
512 | return; | 529 | return; |
513 | 530 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c new file mode 100644 index 000000000000..c785e34ccff9 --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
3 | * Authors: Joonyoung Shim <jy0922.shim@samsung.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include "drmP.h" | ||
13 | |||
14 | #include "exynos_drm.h" | ||
15 | #include "exynos_drm_crtc.h" | ||
16 | #include "exynos_drm_drv.h" | ||
17 | #include "exynos_drm_encoder.h" | ||
18 | |||
19 | struct exynos_plane { | ||
20 | struct drm_plane base; | ||
21 | struct exynos_drm_overlay overlay; | ||
22 | bool enabled; | ||
23 | }; | ||
24 | |||
25 | static int | ||
26 | exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | ||
27 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, | ||
28 | unsigned int crtc_w, unsigned int crtc_h, | ||
29 | uint32_t src_x, uint32_t src_y, | ||
30 | uint32_t src_w, uint32_t src_h) | ||
31 | { | ||
32 | struct exynos_plane *exynos_plane = | ||
33 | container_of(plane, struct exynos_plane, base); | ||
34 | struct exynos_drm_overlay *overlay = &exynos_plane->overlay; | ||
35 | struct exynos_drm_crtc_pos pos; | ||
36 | unsigned int x = src_x >> 16; | ||
37 | unsigned int y = src_y >> 16; | ||
38 | int ret; | ||
39 | |||
40 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
41 | |||
42 | memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos)); | ||
43 | pos.crtc_x = crtc_x; | ||
44 | pos.crtc_y = crtc_y; | ||
45 | pos.crtc_w = crtc_w; | ||
46 | pos.crtc_h = crtc_h; | ||
47 | |||
48 | pos.fb_x = x; | ||
49 | pos.fb_y = y; | ||
50 | |||
51 | /* TODO: scale feature */ | ||
52 | ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos); | ||
53 | if (ret < 0) | ||
54 | return ret; | ||
55 | |||
56 | exynos_drm_fn_encoder(crtc, overlay, | ||
57 | exynos_drm_encoder_crtc_mode_set); | ||
58 | exynos_drm_fn_encoder(crtc, &overlay->zpos, | ||
59 | exynos_drm_encoder_crtc_plane_commit); | ||
60 | |||
61 | exynos_plane->enabled = true; | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int exynos_disable_plane(struct drm_plane *plane) | ||
67 | { | ||
68 | struct exynos_plane *exynos_plane = | ||
69 | container_of(plane, struct exynos_plane, base); | ||
70 | struct exynos_drm_overlay *overlay = &exynos_plane->overlay; | ||
71 | |||
72 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
73 | |||
74 | if (!exynos_plane->enabled) | ||
75 | return 0; | ||
76 | |||
77 | exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, | ||
78 | exynos_drm_encoder_crtc_disable); | ||
79 | |||
80 | exynos_plane->enabled = false; | ||
81 | exynos_plane->overlay.zpos = DEFAULT_ZPOS; | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static void exynos_plane_destroy(struct drm_plane *plane) | ||
87 | { | ||
88 | struct exynos_plane *exynos_plane = | ||
89 | container_of(plane, struct exynos_plane, base); | ||
90 | |||
91 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
92 | |||
93 | exynos_disable_plane(plane); | ||
94 | drm_plane_cleanup(plane); | ||
95 | kfree(exynos_plane); | ||
96 | } | ||
97 | |||
98 | static struct drm_plane_funcs exynos_plane_funcs = { | ||
99 | .update_plane = exynos_update_plane, | ||
100 | .disable_plane = exynos_disable_plane, | ||
101 | .destroy = exynos_plane_destroy, | ||
102 | }; | ||
103 | |||
104 | int exynos_plane_init(struct drm_device *dev, unsigned int nr) | ||
105 | { | ||
106 | struct exynos_plane *exynos_plane; | ||
107 | uint32_t possible_crtcs; | ||
108 | |||
109 | exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); | ||
110 | if (!exynos_plane) | ||
111 | return -ENOMEM; | ||
112 | |||
113 | /* all CRTCs are available */ | ||
114 | possible_crtcs = (1 << MAX_CRTC) - 1; | ||
115 | |||
116 | exynos_plane->overlay.zpos = DEFAULT_ZPOS; | ||
117 | |||
118 | /* TODO: format */ | ||
119 | return drm_plane_init(dev, &exynos_plane->base, possible_crtcs, | ||
120 | &exynos_plane_funcs, NULL, 0); | ||
121 | } | ||
122 | |||
123 | int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data, | ||
124 | struct drm_file *file_priv) | ||
125 | { | ||
126 | struct drm_exynos_plane_set_zpos *zpos_req = data; | ||
127 | struct drm_mode_object *obj; | ||
128 | struct drm_plane *plane; | ||
129 | struct exynos_plane *exynos_plane; | ||
130 | int ret = 0; | ||
131 | |||
132 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
133 | |||
134 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
135 | return -EINVAL; | ||
136 | |||
137 | if (zpos_req->zpos < 0 || zpos_req->zpos >= MAX_PLANE) { | ||
138 | if (zpos_req->zpos != DEFAULT_ZPOS) { | ||
139 | DRM_ERROR("zpos not within limits\n"); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | mutex_lock(&dev->mode_config.mutex); | ||
145 | |||
146 | obj = drm_mode_object_find(dev, zpos_req->plane_id, | ||
147 | DRM_MODE_OBJECT_PLANE); | ||
148 | if (!obj) { | ||
149 | DRM_DEBUG_KMS("Unknown plane ID %d\n", | ||
150 | zpos_req->plane_id); | ||
151 | ret = -EINVAL; | ||
152 | goto out; | ||
153 | } | ||
154 | |||
155 | plane = obj_to_plane(obj); | ||
156 | exynos_plane = container_of(plane, struct exynos_plane, base); | ||
157 | |||
158 | exynos_plane->overlay.zpos = zpos_req->zpos; | ||
159 | |||
160 | out: | ||
161 | mutex_unlock(&dev->mode_config.mutex); | ||
162 | return ret; | ||
163 | } | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h new file mode 100644 index 000000000000..16b71f8217e7 --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
3 | * Authors: Joonyoung Shim <jy0922.shim@samsung.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | int exynos_plane_init(struct drm_device *dev, unsigned int nr); | ||
13 | int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data, | ||
14 | struct drm_file *file_priv); | ||