aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_plane.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_plane.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_plane.c444
1 files changed, 190 insertions, 254 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 1c6b63f39474..098904696a5c 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -17,10 +17,12 @@
17 * this program. If not, see <http://www.gnu.org/licenses/>. 17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
20#include "drm_flip_work.h" 20#include <drm/drm_atomic.h>
21#include <drm/drm_atomic_helper.h>
22#include <drm/drm_plane_helper.h>
21 23
22#include "omap_drv.h"
23#include "omap_dmm_tiler.h" 24#include "omap_dmm_tiler.h"
25#include "omap_drv.h"
24 26
25/* some hackery because omapdss has an 'enum omap_plane' (which would be 27/* some hackery because omapdss has an 'enum omap_plane' (which would be
26 * better named omap_plane_id).. and compiler seems unhappy about having 28 * better named omap_plane_id).. and compiler seems unhappy about having
@@ -32,237 +34,183 @@
32 * plane funcs 34 * plane funcs
33 */ 35 */
34 36
35struct callback {
36 void (*fxn)(void *);
37 void *arg;
38};
39
40#define to_omap_plane(x) container_of(x, struct omap_plane, base) 37#define to_omap_plane(x) container_of(x, struct omap_plane, base)
41 38
42struct omap_plane { 39struct omap_plane {
43 struct drm_plane base; 40 struct drm_plane base;
44 int id; /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */ 41 int id; /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */
45 const char *name; 42 const char *name;
46 struct omap_overlay_info info;
47 struct omap_drm_apply apply;
48
49 /* position/orientation of scanout within the fb: */
50 struct omap_drm_window win;
51 bool enabled;
52
53 /* last fb that we pinned: */
54 struct drm_framebuffer *pinned_fb;
55 43
56 uint32_t nformats; 44 uint32_t nformats;
57 uint32_t formats[32]; 45 uint32_t formats[32];
58 46
59 struct omap_drm_irq error_irq; 47 struct omap_drm_irq error_irq;
48};
60 49
61 /* for deferring bo unpin's until next post_apply(): */ 50struct omap_plane_state {
62 struct drm_flip_work unpin_work; 51 struct drm_plane_state base;
63 52
64 // XXX maybe get rid of this and handle vblank in crtc too? 53 unsigned int zorder;
65 struct callback apply_done_cb;
66}; 54};
67 55
68static void omap_plane_unpin_worker(struct drm_flip_work *work, void *val) 56static inline struct omap_plane_state *
57to_omap_plane_state(struct drm_plane_state *state)
69{ 58{
70 struct omap_plane *omap_plane = 59 return container_of(state, struct omap_plane_state, base);
71 container_of(work, struct omap_plane, unpin_work);
72 struct drm_device *dev = omap_plane->base.dev;
73
74 /*
75 * omap_framebuffer_pin/unpin are always called from priv->wq,
76 * so there's no need for locking here.
77 */
78 omap_framebuffer_unpin(val);
79 mutex_lock(&dev->mode_config.mutex);
80 drm_framebuffer_unreference(val);
81 mutex_unlock(&dev->mode_config.mutex);
82} 60}
83 61
84/* update which fb (if any) is pinned for scanout */ 62static int omap_plane_prepare_fb(struct drm_plane *plane,
85static int omap_plane_update_pin(struct drm_plane *plane, 63 struct drm_framebuffer *fb,
86 struct drm_framebuffer *fb) 64 const struct drm_plane_state *new_state)
87{ 65{
88 struct omap_plane *omap_plane = to_omap_plane(plane); 66 return omap_framebuffer_pin(fb);
89 struct drm_framebuffer *pinned_fb = omap_plane->pinned_fb; 67}
90
91 if (pinned_fb != fb) {
92 int ret = 0;
93
94 DBG("%p -> %p", pinned_fb, fb);
95
96 if (fb) {
97 drm_framebuffer_reference(fb);
98 ret = omap_framebuffer_pin(fb);
99 }
100
101 if (pinned_fb)
102 drm_flip_work_queue(&omap_plane->unpin_work, pinned_fb);
103
104 if (ret) {
105 dev_err(plane->dev->dev, "could not swap %p -> %p\n",
106 omap_plane->pinned_fb, fb);
107 drm_framebuffer_unreference(fb);
108 omap_plane->pinned_fb = NULL;
109 return ret;
110 }
111
112 omap_plane->pinned_fb = fb;
113 }
114 68
115 return 0; 69static void omap_plane_cleanup_fb(struct drm_plane *plane,
70 struct drm_framebuffer *fb,
71 const struct drm_plane_state *old_state)
72{
73 omap_framebuffer_unpin(fb);
116} 74}
117 75
118static void omap_plane_pre_apply(struct omap_drm_apply *apply) 76static void omap_plane_atomic_update(struct drm_plane *plane,
77 struct drm_plane_state *old_state)
119{ 78{
120 struct omap_plane *omap_plane = 79 struct omap_plane *omap_plane = to_omap_plane(plane);
121 container_of(apply, struct omap_plane, apply); 80 struct drm_plane_state *state = plane->state;
122 struct omap_drm_window *win = &omap_plane->win; 81 struct omap_plane_state *omap_state = to_omap_plane_state(state);
123 struct drm_plane *plane = &omap_plane->base; 82 struct omap_overlay_info info;
124 struct drm_device *dev = plane->dev; 83 struct omap_drm_window win;
125 struct omap_overlay_info *info = &omap_plane->info;
126 struct drm_crtc *crtc = plane->crtc;
127 enum omap_channel channel;
128 bool enabled = omap_plane->enabled && crtc;
129 int ret; 84 int ret;
130 85
131 DBG("%s, enabled=%d", omap_plane->name, enabled); 86 DBG("%s, crtc=%p fb=%p", omap_plane->name, state->crtc, state->fb);
132 87
133 /* if fb has changed, pin new fb: */ 88 memset(&info, 0, sizeof(info));
134 omap_plane_update_pin(plane, enabled ? plane->fb : NULL); 89 info.rotation_type = OMAP_DSS_ROT_DMA;
90 info.rotation = OMAP_DSS_ROT_0;
91 info.global_alpha = 0xff;
92 info.mirror = 0;
93 info.zorder = omap_state->zorder;
135 94
136 if (!enabled) { 95 memset(&win, 0, sizeof(win));
137 dispc_ovl_enable(omap_plane->id, false); 96 win.rotation = state->rotation;
138 return; 97 win.crtc_x = state->crtc_x;
139 } 98 win.crtc_y = state->crtc_y;
99 win.crtc_w = state->crtc_w;
100 win.crtc_h = state->crtc_h;
101
102 /*
103 * src values are in Q16 fixed point, convert to integer.
104 * omap_framebuffer_update_scanout() takes adjusted src.
105 */
106 win.src_x = state->src_x >> 16;
107 win.src_y = state->src_y >> 16;
140 108
141 channel = omap_crtc_channel(crtc); 109 switch (state->rotation & 0xf) {
110 case BIT(DRM_ROTATE_90):
111 case BIT(DRM_ROTATE_270):
112 win.src_w = state->src_h >> 16;
113 win.src_h = state->src_w >> 16;
114 break;
115 default:
116 win.src_w = state->src_w >> 16;
117 win.src_h = state->src_h >> 16;
118 break;
119 }
142 120
143 /* update scanout: */ 121 /* update scanout: */
144 omap_framebuffer_update_scanout(plane->fb, win, info); 122 omap_framebuffer_update_scanout(state->fb, &win, &info);
145 123
146 DBG("%dx%d -> %dx%d (%d)", info->width, info->height, 124 DBG("%dx%d -> %dx%d (%d)", info.width, info.height,
147 info->out_width, info->out_height, 125 info.out_width, info.out_height,
148 info->screen_width); 126 info.screen_width);
149 DBG("%d,%d %pad %pad", info->pos_x, info->pos_y, 127 DBG("%d,%d %pad %pad", info.pos_x, info.pos_y,
150 &info->paddr, &info->p_uv_addr); 128 &info.paddr, &info.p_uv_addr);
151 129
152 dispc_ovl_set_channel_out(omap_plane->id, channel); 130 dispc_ovl_set_channel_out(omap_plane->id,
131 omap_crtc_channel(state->crtc));
153 132
154 /* and finally, update omapdss: */ 133 /* and finally, update omapdss: */
155 ret = dispc_ovl_setup(omap_plane->id, info, false, 134 ret = dispc_ovl_setup(omap_plane->id, &info, false,
156 omap_crtc_timings(crtc), false); 135 omap_crtc_timings(state->crtc), false);
157 if (ret) { 136 if (WARN_ON(ret)) {
158 dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret); 137 dispc_ovl_enable(omap_plane->id, false);
159 return; 138 return;
160 } 139 }
161 140
162 dispc_ovl_enable(omap_plane->id, true); 141 dispc_ovl_enable(omap_plane->id, true);
163} 142}
164 143
165static void omap_plane_post_apply(struct omap_drm_apply *apply) 144static void omap_plane_atomic_disable(struct drm_plane *plane,
145 struct drm_plane_state *old_state)
166{ 146{
167 struct omap_plane *omap_plane = 147 struct omap_plane_state *omap_state = to_omap_plane_state(plane->state);
168 container_of(apply, struct omap_plane, apply); 148 struct omap_plane *omap_plane = to_omap_plane(plane);
169 struct drm_plane *plane = &omap_plane->base;
170 struct omap_drm_private *priv = plane->dev->dev_private;
171 struct callback cb;
172
173 cb = omap_plane->apply_done_cb;
174 omap_plane->apply_done_cb.fxn = NULL;
175 149
176 drm_flip_work_commit(&omap_plane->unpin_work, priv->wq); 150 plane->state->rotation = BIT(DRM_ROTATE_0);
151 omap_state->zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
152 ? 0 : omap_plane->id;
177 153
178 if (cb.fxn) 154 dispc_ovl_enable(omap_plane->id, false);
179 cb.fxn(cb.arg);
180} 155}
181 156
182static int omap_plane_apply(struct drm_plane *plane) 157static int omap_plane_atomic_check(struct drm_plane *plane,
158 struct drm_plane_state *state)
183{ 159{
184 if (plane->crtc) { 160 struct drm_crtc_state *crtc_state;
185 struct omap_plane *omap_plane = to_omap_plane(plane); 161
186 return omap_crtc_apply(plane->crtc, &omap_plane->apply); 162 if (!state->crtc)
187 } 163 return 0;
164
165 crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
166 if (IS_ERR(crtc_state))
167 return PTR_ERR(crtc_state);
168
169 if (state->crtc_x < 0 || state->crtc_y < 0)
170 return -EINVAL;
171
172 if (state->crtc_x + state->crtc_w > crtc_state->adjusted_mode.hdisplay)
173 return -EINVAL;
174
175 if (state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay)
176 return -EINVAL;
177
188 return 0; 178 return 0;
189} 179}
190 180
191int omap_plane_mode_set(struct drm_plane *plane, 181static const struct drm_plane_helper_funcs omap_plane_helper_funcs = {
192 struct drm_crtc *crtc, struct drm_framebuffer *fb, 182 .prepare_fb = omap_plane_prepare_fb,
193 int crtc_x, int crtc_y, 183 .cleanup_fb = omap_plane_cleanup_fb,
194 unsigned int crtc_w, unsigned int crtc_h, 184 .atomic_check = omap_plane_atomic_check,
195 unsigned int src_x, unsigned int src_y, 185 .atomic_update = omap_plane_atomic_update,
196 unsigned int src_w, unsigned int src_h, 186 .atomic_disable = omap_plane_atomic_disable,
197 void (*fxn)(void *), void *arg) 187};
188
189static void omap_plane_reset(struct drm_plane *plane)
198{ 190{
199 struct omap_plane *omap_plane = to_omap_plane(plane); 191 struct omap_plane *omap_plane = to_omap_plane(plane);
200 struct omap_drm_window *win = &omap_plane->win; 192 struct omap_plane_state *omap_state;
201
202 win->crtc_x = crtc_x;
203 win->crtc_y = crtc_y;
204 win->crtc_w = crtc_w;
205 win->crtc_h = crtc_h;
206
207 win->src_x = src_x;
208 win->src_y = src_y;
209 win->src_w = src_w;
210 win->src_h = src_h;
211
212 if (fxn) {
213 /* omap_crtc should ensure that a new page flip
214 * isn't permitted while there is one pending:
215 */
216 BUG_ON(omap_plane->apply_done_cb.fxn);
217
218 omap_plane->apply_done_cb.fxn = fxn;
219 omap_plane->apply_done_cb.arg = arg;
220 }
221 193
222 return omap_plane_apply(plane); 194 if (plane->state && plane->state->fb)
223} 195 drm_framebuffer_unreference(plane->state->fb);
224 196
225static int omap_plane_update(struct drm_plane *plane, 197 kfree(plane->state);
226 struct drm_crtc *crtc, struct drm_framebuffer *fb, 198 plane->state = NULL;
227 int crtc_x, int crtc_y,
228 unsigned int crtc_w, unsigned int crtc_h,
229 uint32_t src_x, uint32_t src_y,
230 uint32_t src_w, uint32_t src_h)
231{
232 struct omap_plane *omap_plane = to_omap_plane(plane);
233 omap_plane->enabled = true;
234 199
235 /* omap_plane_mode_set() takes adjusted src */ 200 omap_state = kzalloc(sizeof(*omap_state), GFP_KERNEL);
236 switch (omap_plane->win.rotation & 0xf) { 201 if (omap_state == NULL)
237 case BIT(DRM_ROTATE_90): 202 return;
238 case BIT(DRM_ROTATE_270):
239 swap(src_w, src_h);
240 break;
241 }
242 203
243 /* 204 /*
244 * We don't need to take a reference to the framebuffer as the DRM core 205 * Set defaults depending on whether we are a primary or overlay
245 * has already done so for the purpose of setting plane->fb. 206 * plane.
246 */ 207 */
247 plane->fb = fb; 208 omap_state->zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
248 plane->crtc = crtc; 209 ? 0 : omap_plane->id;
249 210 omap_state->base.rotation = BIT(DRM_ROTATE_0);
250 /* src values are in Q16 fixed point, convert to integer: */
251 return omap_plane_mode_set(plane, crtc, fb,
252 crtc_x, crtc_y, crtc_w, crtc_h,
253 src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16,
254 NULL, NULL);
255}
256
257static int omap_plane_disable(struct drm_plane *plane)
258{
259 struct omap_plane *omap_plane = to_omap_plane(plane);
260
261 omap_plane->win.rotation = BIT(DRM_ROTATE_0);
262 omap_plane->info.zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
263 ? 0 : omap_plane->id;
264 211
265 return omap_plane_set_enable(plane, false); 212 plane->state = &omap_state->base;
213 plane->state->plane = plane;
266} 214}
267 215
268static void omap_plane_destroy(struct drm_plane *plane) 216static void omap_plane_destroy(struct drm_plane *plane)
@@ -275,82 +223,94 @@ static void omap_plane_destroy(struct drm_plane *plane)
275 223
276 drm_plane_cleanup(plane); 224 drm_plane_cleanup(plane);
277 225
278 drm_flip_work_cleanup(&omap_plane->unpin_work);
279
280 kfree(omap_plane); 226 kfree(omap_plane);
281} 227}
282 228
283int omap_plane_set_enable(struct drm_plane *plane, bool enable)
284{
285 struct omap_plane *omap_plane = to_omap_plane(plane);
286
287 if (enable == omap_plane->enabled)
288 return 0;
289
290 omap_plane->enabled = enable;
291 return omap_plane_apply(plane);
292}
293
294/* helper to install properties which are common to planes and crtcs */ 229/* helper to install properties which are common to planes and crtcs */
295void omap_plane_install_properties(struct drm_plane *plane, 230void omap_plane_install_properties(struct drm_plane *plane,
296 struct drm_mode_object *obj) 231 struct drm_mode_object *obj)
297{ 232{
298 struct drm_device *dev = plane->dev; 233 struct drm_device *dev = plane->dev;
299 struct omap_drm_private *priv = dev->dev_private; 234 struct omap_drm_private *priv = dev->dev_private;
300 struct drm_property *prop;
301 235
302 if (priv->has_dmm) { 236 if (priv->has_dmm) {
303 prop = priv->rotation_prop; 237 struct drm_property *prop = dev->mode_config.rotation_property;
304 if (!prop) { 238
305 prop = drm_mode_create_rotation_property(dev,
306 BIT(DRM_ROTATE_0) |
307 BIT(DRM_ROTATE_90) |
308 BIT(DRM_ROTATE_180) |
309 BIT(DRM_ROTATE_270) |
310 BIT(DRM_REFLECT_X) |
311 BIT(DRM_REFLECT_Y));
312 if (prop == NULL)
313 return;
314 priv->rotation_prop = prop;
315 }
316 drm_object_attach_property(obj, prop, 0); 239 drm_object_attach_property(obj, prop, 0);
317 } 240 }
318 241
319 prop = priv->zorder_prop; 242 drm_object_attach_property(obj, priv->zorder_prop, 0);
320 if (!prop) {
321 prop = drm_property_create_range(dev, 0, "zorder", 0, 3);
322 if (prop == NULL)
323 return;
324 priv->zorder_prop = prop;
325 }
326 drm_object_attach_property(obj, prop, 0);
327} 243}
328 244
329int omap_plane_set_property(struct drm_plane *plane, 245static struct drm_plane_state *
330 struct drm_property *property, uint64_t val) 246omap_plane_atomic_duplicate_state(struct drm_plane *plane)
247{
248 struct omap_plane_state *state;
249 struct omap_plane_state *copy;
250
251 if (WARN_ON(!plane->state))
252 return NULL;
253
254 state = to_omap_plane_state(plane->state);
255 copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
256 if (copy == NULL)
257 return NULL;
258
259 __drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
260
261 return &copy->base;
262}
263
264static void omap_plane_atomic_destroy_state(struct drm_plane *plane,
265 struct drm_plane_state *state)
266{
267 __drm_atomic_helper_plane_destroy_state(plane, state);
268 kfree(to_omap_plane_state(state));
269}
270
271static int omap_plane_atomic_set_property(struct drm_plane *plane,
272 struct drm_plane_state *state,
273 struct drm_property *property,
274 uint64_t val)
331{ 275{
332 struct omap_plane *omap_plane = to_omap_plane(plane);
333 struct omap_drm_private *priv = plane->dev->dev_private; 276 struct omap_drm_private *priv = plane->dev->dev_private;
334 int ret = -EINVAL; 277 struct omap_plane_state *omap_state = to_omap_plane_state(state);
335 278
336 if (property == priv->rotation_prop) { 279 if (property == priv->zorder_prop)
337 DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val); 280 omap_state->zorder = val;
338 omap_plane->win.rotation = val; 281 else
339 ret = omap_plane_apply(plane); 282 return -EINVAL;
340 } else if (property == priv->zorder_prop) {
341 DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val);
342 omap_plane->info.zorder = val;
343 ret = omap_plane_apply(plane);
344 }
345 283
346 return ret; 284 return 0;
285}
286
287static int omap_plane_atomic_get_property(struct drm_plane *plane,
288 const struct drm_plane_state *state,
289 struct drm_property *property,
290 uint64_t *val)
291{
292 struct omap_drm_private *priv = plane->dev->dev_private;
293 const struct omap_plane_state *omap_state =
294 container_of(state, const struct omap_plane_state, base);
295
296 if (property == priv->zorder_prop)
297 *val = omap_state->zorder;
298 else
299 return -EINVAL;
300
301 return 0;
347} 302}
348 303
349static const struct drm_plane_funcs omap_plane_funcs = { 304static const struct drm_plane_funcs omap_plane_funcs = {
350 .update_plane = omap_plane_update, 305 .update_plane = drm_atomic_helper_update_plane,
351 .disable_plane = omap_plane_disable, 306 .disable_plane = drm_atomic_helper_disable_plane,
307 .reset = omap_plane_reset,
352 .destroy = omap_plane_destroy, 308 .destroy = omap_plane_destroy,
353 .set_property = omap_plane_set_property, 309 .set_property = drm_atomic_helper_plane_set_property,
310 .atomic_duplicate_state = omap_plane_atomic_duplicate_state,
311 .atomic_destroy_state = omap_plane_atomic_destroy_state,
312 .atomic_set_property = omap_plane_atomic_set_property,
313 .atomic_get_property = omap_plane_atomic_get_property,
354}; 314};
355 315
356static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) 316static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
@@ -382,7 +342,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
382 struct omap_drm_private *priv = dev->dev_private; 342 struct omap_drm_private *priv = dev->dev_private;
383 struct drm_plane *plane; 343 struct drm_plane *plane;
384 struct omap_plane *omap_plane; 344 struct omap_plane *omap_plane;
385 struct omap_overlay_info *info;
386 int ret; 345 int ret;
387 346
388 DBG("%s: type=%d", plane_names[id], type); 347 DBG("%s: type=%d", plane_names[id], type);
@@ -391,9 +350,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
391 if (!omap_plane) 350 if (!omap_plane)
392 return ERR_PTR(-ENOMEM); 351 return ERR_PTR(-ENOMEM);
393 352
394 drm_flip_work_init(&omap_plane->unpin_work,
395 "unpin", omap_plane_unpin_worker);
396
397 omap_plane->nformats = omap_framebuffer_get_formats( 353 omap_plane->nformats = omap_framebuffer_get_formats(
398 omap_plane->formats, ARRAY_SIZE(omap_plane->formats), 354 omap_plane->formats, ARRAY_SIZE(omap_plane->formats),
399 dss_feat_get_supported_color_modes(id)); 355 dss_feat_get_supported_color_modes(id));
@@ -402,9 +358,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
402 358
403 plane = &omap_plane->base; 359 plane = &omap_plane->base;
404 360
405 omap_plane->apply.pre_apply = omap_plane_pre_apply;
406 omap_plane->apply.post_apply = omap_plane_post_apply;
407
408 omap_plane->error_irq.irqmask = error_irqs[id]; 361 omap_plane->error_irq.irqmask = error_irqs[id];
409 omap_plane->error_irq.irq = omap_plane_error_irq; 362 omap_plane->error_irq.irq = omap_plane_error_irq;
410 omap_irq_register(dev, &omap_plane->error_irq); 363 omap_irq_register(dev, &omap_plane->error_irq);
@@ -415,26 +368,9 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
415 if (ret < 0) 368 if (ret < 0)
416 goto error; 369 goto error;
417 370
418 omap_plane_install_properties(plane, &plane->base); 371 drm_plane_helper_add(plane, &omap_plane_helper_funcs);
419 372
420 /* get our starting configuration, set defaults for parameters 373 omap_plane_install_properties(plane, &plane->base);
421 * we don't currently use, etc:
422 */
423 info = &omap_plane->info;
424 info->rotation_type = OMAP_DSS_ROT_DMA;
425 info->rotation = OMAP_DSS_ROT_0;
426 info->global_alpha = 0xff;
427 info->mirror = 0;
428
429 /* Set defaults depending on whether we are a CRTC or overlay
430 * layer.
431 * TODO add ioctl to give userspace an API to change this.. this
432 * will come in a subsequent patch.
433 */
434 if (type == DRM_PLANE_TYPE_PRIMARY)
435 omap_plane->info.zorder = 0;
436 else
437 omap_plane->info.zorder = id;
438 374
439 return plane; 375 return plane;
440 376