blob: c277a3a445f5a206209dc898ded6f15500b084a7 [file] [log] [blame]
Joonyoung Shim864ee9e2011-12-08 17:54:07 +09001/*
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
19struct exynos_plane {
20 struct drm_plane base;
21 struct exynos_drm_overlay overlay;
22 bool enabled;
23};
24
Eunchul Kimba3849d2012-03-16 18:47:15 +090025static const uint32_t formats[] = {
26 DRM_FORMAT_XRGB8888,
27};
28
Joonyoung Shim864ee9e2011-12-08 17:54:07 +090029static int
30exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
31 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
32 unsigned int crtc_w, unsigned int crtc_h,
33 uint32_t src_x, uint32_t src_y,
34 uint32_t src_w, uint32_t src_h)
35{
36 struct exynos_plane *exynos_plane =
37 container_of(plane, struct exynos_plane, base);
38 struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
39 struct exynos_drm_crtc_pos pos;
40 unsigned int x = src_x >> 16;
41 unsigned int y = src_y >> 16;
42 int ret;
43
44 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
45
46 memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos));
47 pos.crtc_x = crtc_x;
48 pos.crtc_y = crtc_y;
49 pos.crtc_w = crtc_w;
50 pos.crtc_h = crtc_h;
51
52 pos.fb_x = x;
53 pos.fb_y = y;
54
55 /* TODO: scale feature */
56 ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos);
57 if (ret < 0)
58 return ret;
59
60 exynos_drm_fn_encoder(crtc, overlay,
61 exynos_drm_encoder_crtc_mode_set);
62 exynos_drm_fn_encoder(crtc, &overlay->zpos,
63 exynos_drm_encoder_crtc_plane_commit);
64
65 exynos_plane->enabled = true;
66
67 return 0;
68}
69
70static int exynos_disable_plane(struct drm_plane *plane)
71{
72 struct exynos_plane *exynos_plane =
73 container_of(plane, struct exynos_plane, base);
74 struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
75
76 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
77
78 if (!exynos_plane->enabled)
79 return 0;
80
81 exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
82 exynos_drm_encoder_crtc_disable);
83
84 exynos_plane->enabled = false;
85 exynos_plane->overlay.zpos = DEFAULT_ZPOS;
86
87 return 0;
88}
89
90static void exynos_plane_destroy(struct drm_plane *plane)
91{
92 struct exynos_plane *exynos_plane =
93 container_of(plane, struct exynos_plane, base);
94
95 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
96
97 exynos_disable_plane(plane);
98 drm_plane_cleanup(plane);
99 kfree(exynos_plane);
100}
101
102static struct drm_plane_funcs exynos_plane_funcs = {
103 .update_plane = exynos_update_plane,
104 .disable_plane = exynos_disable_plane,
105 .destroy = exynos_plane_destroy,
106};
107
108int exynos_plane_init(struct drm_device *dev, unsigned int nr)
109{
110 struct exynos_plane *exynos_plane;
111 uint32_t possible_crtcs;
112
113 exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL);
114 if (!exynos_plane)
115 return -ENOMEM;
116
117 /* all CRTCs are available */
118 possible_crtcs = (1 << MAX_CRTC) - 1;
119
120 exynos_plane->overlay.zpos = DEFAULT_ZPOS;
121
Joonyoung Shim864ee9e2011-12-08 17:54:07 +0900122 return drm_plane_init(dev, &exynos_plane->base, possible_crtcs,
Eunchul Kimba3849d2012-03-16 18:47:15 +0900123 &exynos_plane_funcs, formats, ARRAY_SIZE(formats),
124 false);
Joonyoung Shim864ee9e2011-12-08 17:54:07 +0900125}
126
127int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data,
128 struct drm_file *file_priv)
129{
130 struct drm_exynos_plane_set_zpos *zpos_req = data;
131 struct drm_mode_object *obj;
132 struct drm_plane *plane;
133 struct exynos_plane *exynos_plane;
134 int ret = 0;
135
136 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
137
138 if (!drm_core_check_feature(dev, DRIVER_MODESET))
139 return -EINVAL;
140
141 if (zpos_req->zpos < 0 || zpos_req->zpos >= MAX_PLANE) {
142 if (zpos_req->zpos != DEFAULT_ZPOS) {
143 DRM_ERROR("zpos not within limits\n");
144 return -EINVAL;
145 }
146 }
147
148 mutex_lock(&dev->mode_config.mutex);
149
150 obj = drm_mode_object_find(dev, zpos_req->plane_id,
151 DRM_MODE_OBJECT_PLANE);
152 if (!obj) {
153 DRM_DEBUG_KMS("Unknown plane ID %d\n",
154 zpos_req->plane_id);
155 ret = -EINVAL;
156 goto out;
157 }
158
159 plane = obj_to_plane(obj);
160 exynos_plane = container_of(plane, struct exynos_plane, base);
161
162 exynos_plane->overlay.zpos = zpos_req->zpos;
163
164out:
165 mutex_unlock(&dev->mode_config.mutex);
166 return ret;
167}