diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_plane.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_plane.c | 163 |
1 files changed, 163 insertions, 0 deletions
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 00000000000..bdcf770aa22 --- /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, false); | ||
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 | } | ||