blob: fcc5d96032929628e56fa02d1c0b20b9659f10b8 [file] [log] [blame]
Rob Clarkbb5c2d92012-01-16 12:51:16 -06001/*
Rob Clark8bb0daf2013-02-11 12:43:09 -05002 * drivers/gpu/drm/omapdrm/omap_plane.c
Rob Clarkbb5c2d92012-01-16 12:51:16 -06003 *
4 * Copyright (C) 2011 Texas Instruments
5 * Author: Rob Clark <rob.clark@linaro.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
Laurent Pinchart69a12262015-03-05 21:38:16 +020020#include <drm/drm_atomic_helper.h>
Laurent Pinchartde8e4102015-03-05 13:39:56 +020021#include <drm/drm_plane_helper.h>
Laurent Pinchart69a12262015-03-05 21:38:16 +020022
Rob Clark3c810c62012-08-15 15:18:01 -050023#include "omap_dmm_tiler.h"
Laurent Pinchart2d278f52015-03-05 21:31:37 +020024#include "omap_drv.h"
Rob Clarkbb5c2d92012-01-16 12:51:16 -060025
26/* some hackery because omapdss has an 'enum omap_plane' (which would be
27 * better named omap_plane_id).. and compiler seems unhappy about having
28 * both a 'struct omap_plane' and 'enum omap_plane'
29 */
30#define omap_plane _omap_plane
31
32/*
33 * plane funcs
34 */
35
36#define to_omap_plane(x) container_of(x, struct omap_plane, base)
37
38struct omap_plane {
39 struct drm_plane base;
Rob Clarkf5f94542012-12-04 13:59:12 -060040 int id; /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */
41 const char *name;
Rob Clarkbb5c2d92012-01-16 12:51:16 -060042 struct omap_overlay_info info;
43
Rob Clark3c810c62012-08-15 15:18:01 -050044 /* position/orientation of scanout within the fb: */
45 struct omap_drm_window win;
Rob Clarkf5f94542012-12-04 13:59:12 -060046 bool enabled;
Rob Clark9a0774e2012-01-16 12:51:17 -060047
48 /* last fb that we pinned: */
49 struct drm_framebuffer *pinned_fb;
Rob Clarkbb5c2d92012-01-16 12:51:16 -060050
Rob Clarka890e662012-03-05 10:48:31 -060051 uint32_t nformats;
52 uint32_t formats[32];
Rob Clarkb33f34d2012-03-05 10:48:35 -060053
Rob Clarkf5f94542012-12-04 13:59:12 -060054 struct omap_drm_irq error_irq;
Rob Clarka890e662012-03-05 10:48:31 -060055};
Rob Clarkbb5c2d92012-01-16 12:51:16 -060056
Rob Clark9a0774e2012-01-16 12:51:17 -060057/* update which fb (if any) is pinned for scanout */
Laurent Pincharta42133a2015-01-17 19:09:26 +020058static int omap_plane_update_pin(struct drm_plane *plane)
Rob Clark9a0774e2012-01-16 12:51:17 -060059{
60 struct omap_plane *omap_plane = to_omap_plane(plane);
Rob Clarkb33f34d2012-03-05 10:48:35 -060061 struct drm_framebuffer *pinned_fb = omap_plane->pinned_fb;
Laurent Pincharta42133a2015-01-17 19:09:26 +020062 struct drm_framebuffer *fb = omap_plane->enabled ? plane->fb : NULL;
63 int ret = 0;
Rob Clark9a0774e2012-01-16 12:51:17 -060064
Laurent Pincharta42133a2015-01-17 19:09:26 +020065 if (pinned_fb == fb)
66 return 0;
Rob Clarkb33f34d2012-03-05 10:48:35 -060067
Laurent Pincharta42133a2015-01-17 19:09:26 +020068 DBG("%p -> %p", pinned_fb, fb);
Rob Clarkb33f34d2012-03-05 10:48:35 -060069
Laurent Pincharta42133a2015-01-17 19:09:26 +020070 if (fb) {
71 drm_framebuffer_reference(fb);
72 ret = omap_framebuffer_pin(fb);
Rob Clark9a0774e2012-01-16 12:51:17 -060073 }
74
Laurent Pincharta42133a2015-01-17 19:09:26 +020075 if (pinned_fb)
76 omap_crtc_queue_unpin(plane->crtc, pinned_fb);
77
78 if (ret) {
79 dev_err(plane->dev->dev, "could not swap %p -> %p\n",
80 omap_plane->pinned_fb, fb);
81 drm_framebuffer_unreference(fb);
82 omap_plane->pinned_fb = NULL;
83 return ret;
84 }
85
86 omap_plane->pinned_fb = fb;
87
Rob Clarkb33f34d2012-03-05 10:48:35 -060088 return 0;
Rob Clark9a0774e2012-01-16 12:51:17 -060089}
90
Laurent Pinchartde8e4102015-03-05 13:39:56 +020091static int __omap_plane_setup(struct omap_plane *omap_plane,
92 struct drm_crtc *crtc,
93 struct drm_framebuffer *fb)
Rob Clarkbb5c2d92012-01-16 12:51:16 -060094{
Laurent Pincharta42133a2015-01-17 19:09:26 +020095 struct omap_overlay_info *info = &omap_plane->info;
Laurent Pinchartde8e4102015-03-05 13:39:56 +020096 struct drm_device *dev = omap_plane->base.dev;
Rob Clark9a0774e2012-01-16 12:51:17 -060097 int ret;
Rob Clarkbb5c2d92012-01-16 12:51:16 -060098
Laurent Pincharta42133a2015-01-17 19:09:26 +020099 DBG("%s, enabled=%d", omap_plane->name, omap_plane->enabled);
Rob Clarkf5f94542012-12-04 13:59:12 -0600100
Laurent Pincharta42133a2015-01-17 19:09:26 +0200101 if (!omap_plane->enabled) {
Rob Clarkf5f94542012-12-04 13:59:12 -0600102 dispc_ovl_enable(omap_plane->id, false);
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200103 return 0;
Rob Clark9a0774e2012-01-16 12:51:17 -0600104 }
105
Rob Clarkf5f94542012-12-04 13:59:12 -0600106 /* update scanout: */
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200107 omap_framebuffer_update_scanout(fb, &omap_plane->win, info);
Rob Clark9a0774e2012-01-16 12:51:17 -0600108
Rob Clarkf5f94542012-12-04 13:59:12 -0600109 DBG("%dx%d -> %dx%d (%d)", info->width, info->height,
110 info->out_width, info->out_height,
Rob Clark9a0774e2012-01-16 12:51:17 -0600111 info->screen_width);
Russell King2d31ca32014-07-12 10:53:41 +0100112 DBG("%d,%d %pad %pad", info->pos_x, info->pos_y,
113 &info->paddr, &info->p_uv_addr);
Rob Clarkf5f94542012-12-04 13:59:12 -0600114
Laurent Pincharta42133a2015-01-17 19:09:26 +0200115 dispc_ovl_set_channel_out(omap_plane->id,
116 omap_crtc_channel(crtc));
Tomi Valkeinen2dd38872014-10-03 15:14:08 +0000117
Rob Clarkf5f94542012-12-04 13:59:12 -0600118 /* and finally, update omapdss: */
Laurent Pinchart9c660b72015-01-12 16:44:03 +0200119 ret = dispc_ovl_setup(omap_plane->id, info, false,
120 omap_crtc_timings(crtc), false);
Rob Clarkf5f94542012-12-04 13:59:12 -0600121 if (ret) {
122 dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret);
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200123 return ret;
Rob Clarkf5f94542012-12-04 13:59:12 -0600124 }
125
126 dispc_ovl_enable(omap_plane->id, true);
Rob Clarkf5f94542012-12-04 13:59:12 -0600127
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200128 return 0;
129}
130
131static int omap_plane_setup(struct omap_plane *omap_plane)
132{
133 struct drm_plane *plane = &omap_plane->base;
134 int ret;
135
136 ret = omap_plane_update_pin(plane);
137 if (ret < 0)
138 return ret;
139
140 dispc_runtime_get();
141 ret = __omap_plane_setup(omap_plane, plane->crtc, plane->fb);
Laurent Pincharta42133a2015-01-17 19:09:26 +0200142 dispc_runtime_put();
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200143
Laurent Pincharta42133a2015-01-17 19:09:26 +0200144 return ret;
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600145}
146
Rob Clark2f537002012-01-16 12:51:18 -0600147int omap_plane_mode_set(struct drm_plane *plane,
Laurent Pincharta350da82015-01-17 22:31:42 +0200148 struct drm_crtc *crtc, struct drm_framebuffer *fb,
149 int crtc_x, int crtc_y,
150 unsigned int crtc_w, unsigned int crtc_h,
151 unsigned int src_x, unsigned int src_y,
Laurent Pincharta42133a2015-01-17 19:09:26 +0200152 unsigned int src_w, unsigned int src_h)
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600153{
154 struct omap_plane *omap_plane = to_omap_plane(plane);
Rob Clark3c810c62012-08-15 15:18:01 -0500155 struct omap_drm_window *win = &omap_plane->win;
156
157 win->crtc_x = crtc_x;
158 win->crtc_y = crtc_y;
159 win->crtc_w = crtc_w;
160 win->crtc_h = crtc_h;
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600161
Laurent Pincharta350da82015-01-17 22:31:42 +0200162 win->src_x = src_x;
163 win->src_y = src_y;
164 win->src_w = src_w;
165 win->src_h = src_h;
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600166
Laurent Pincharta42133a2015-01-17 19:09:26 +0200167 return omap_plane_setup(omap_plane);
168}
Rob Clarkf5f94542012-12-04 13:59:12 -0600169
Laurent Pincharta42133a2015-01-17 19:09:26 +0200170int omap_plane_set_enable(struct drm_plane *plane, bool enable)
171{
172 struct omap_plane *omap_plane = to_omap_plane(plane);
Rob Clarkf5f94542012-12-04 13:59:12 -0600173
Laurent Pincharta42133a2015-01-17 19:09:26 +0200174 if (enable == omap_plane->enabled)
175 return 0;
176
177 omap_plane->enabled = enable;
178 return omap_plane_setup(omap_plane);
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600179}
180
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200181static int omap_plane_prepare_fb(struct drm_plane *plane,
182 struct drm_framebuffer *fb,
183 const struct drm_plane_state *new_state)
184{
185 return omap_framebuffer_pin(fb);
186}
187
188static void omap_plane_cleanup_fb(struct drm_plane *plane,
189 struct drm_framebuffer *fb,
190 const struct drm_plane_state *old_state)
191{
192 omap_framebuffer_unpin(fb);
193}
194
195static void omap_plane_atomic_update(struct drm_plane *plane,
196 struct drm_plane_state *old_state)
Rob Clark2f537002012-01-16 12:51:18 -0600197{
Rob Clarkf5f94542012-12-04 13:59:12 -0600198 struct omap_plane *omap_plane = to_omap_plane(plane);
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200199 struct omap_drm_window *win = &omap_plane->win;
200 struct drm_plane_state *state = plane->state;
201 uint32_t src_w;
202 uint32_t src_h;
Laurent Pincharta42133a2015-01-17 19:09:26 +0200203
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200204 if (!state->fb || !state->crtc)
205 return;
Archit Tanejab03e14f2013-04-09 15:26:00 +0300206
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200207 /* omap_framebuffer_update_scanout() takes adjusted src */
Grazvydas Ignotasd4586602014-04-05 21:33:51 +0300208 switch (omap_plane->win.rotation & 0xf) {
209 case BIT(DRM_ROTATE_90):
210 case BIT(DRM_ROTATE_270):
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200211 src_w = state->src_h;
212 src_h = state->src_w;
213 break;
214 default:
215 src_w = state->src_w;
216 src_h = state->src_h;
Grazvydas Ignotasd4586602014-04-05 21:33:51 +0300217 break;
218 }
219
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200220 /* src values are in Q16 fixed point, convert to integer. */
221 win->crtc_x = state->crtc_x;
222 win->crtc_y = state->crtc_y;
223 win->crtc_w = state->crtc_w;
224 win->crtc_h = state->crtc_h;
Laurent Pinchartef6b0e02015-01-11 00:11:18 +0200225
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200226 win->src_x = state->src_x >> 16;
227 win->src_y = state->src_y >> 16;
228 win->src_w = src_w >> 16;
229 win->src_h = src_h >> 16;
Laurent Pincharta42133a2015-01-17 19:09:26 +0200230
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200231 omap_plane->enabled = true;
232 __omap_plane_setup(omap_plane, state->crtc, state->fb);
Rob Clark2f537002012-01-16 12:51:18 -0600233}
234
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200235static void omap_plane_atomic_disable(struct drm_plane *plane,
236 struct drm_plane_state *old_state)
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600237{
Rob Clark3c810c62012-08-15 15:18:01 -0500238 struct omap_plane *omap_plane = to_omap_plane(plane);
Laurent Pinchart2debab92015-01-12 22:38:16 +0200239
Rob Clark3c810c62012-08-15 15:18:01 -0500240 omap_plane->win.rotation = BIT(DRM_ROTATE_0);
Laurent Pinchart82e588552015-01-12 23:56:57 +0200241 omap_plane->info.zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
242 ? 0 : omap_plane->id;
243
Laurent Pincharta42133a2015-01-17 19:09:26 +0200244 if (!omap_plane->enabled)
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200245 return;
Laurent Pincharta42133a2015-01-17 19:09:26 +0200246
Laurent Pincharta42133a2015-01-17 19:09:26 +0200247 omap_plane->enabled = false;
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200248 __omap_plane_setup(omap_plane, NULL, NULL);
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600249}
250
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200251static const struct drm_plane_helper_funcs omap_plane_helper_funcs = {
252 .prepare_fb = omap_plane_prepare_fb,
253 .cleanup_fb = omap_plane_cleanup_fb,
254 .atomic_update = omap_plane_atomic_update,
255 .atomic_disable = omap_plane_atomic_disable,
256};
257
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600258static void omap_plane_destroy(struct drm_plane *plane)
259{
260 struct omap_plane *omap_plane = to_omap_plane(plane);
Rob Clarkf5f94542012-12-04 13:59:12 -0600261
262 DBG("%s", omap_plane->name);
263
264 omap_irq_unregister(plane->dev, &omap_plane->error_irq);
265
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600266 drm_plane_cleanup(plane);
Rob Clarkf5f94542012-12-04 13:59:12 -0600267
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600268 kfree(omap_plane);
269}
270
Rob Clark3c810c62012-08-15 15:18:01 -0500271/* helper to install properties which are common to planes and crtcs */
272void omap_plane_install_properties(struct drm_plane *plane,
273 struct drm_mode_object *obj)
274{
275 struct drm_device *dev = plane->dev;
276 struct omap_drm_private *priv = dev->dev_private;
Rob Clark3c810c62012-08-15 15:18:01 -0500277
Rob Clarkc2a6a552012-10-25 17:14:13 -0500278 if (priv->has_dmm) {
Laurent Pincharte2cd09b2015-03-06 17:16:43 +0200279 struct drm_property *prop = dev->mode_config.rotation_property;
280
Rob Clarkc2a6a552012-10-25 17:14:13 -0500281 drm_object_attach_property(obj, prop, 0);
Rob Clark3c810c62012-08-15 15:18:01 -0500282 }
Andre Renaud8451b5a2012-08-15 15:18:02 -0500283
Laurent Pincharte2cd09b2015-03-06 17:16:43 +0200284 drm_object_attach_property(obj, priv->zorder_prop, 0);
Rob Clark3c810c62012-08-15 15:18:01 -0500285}
286
287int omap_plane_set_property(struct drm_plane *plane,
288 struct drm_property *property, uint64_t val)
289{
290 struct omap_plane *omap_plane = to_omap_plane(plane);
291 struct omap_drm_private *priv = plane->dev->dev_private;
Laurent Pincharta42133a2015-01-17 19:09:26 +0200292 int ret;
Rob Clark3c810c62012-08-15 15:18:01 -0500293
Laurent Pincharte2cd09b2015-03-06 17:16:43 +0200294 if (property == plane->dev->mode_config.rotation_property) {
Rob Clarkf5f94542012-12-04 13:59:12 -0600295 DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val);
Rob Clark3c810c62012-08-15 15:18:01 -0500296 omap_plane->win.rotation = val;
Andre Renaud8451b5a2012-08-15 15:18:02 -0500297 } else if (property == priv->zorder_prop) {
Rob Clarkf5f94542012-12-04 13:59:12 -0600298 DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val);
Andre Renaud8451b5a2012-08-15 15:18:02 -0500299 omap_plane->info.zorder = val;
Laurent Pincharta42133a2015-01-17 19:09:26 +0200300 } else {
301 return -EINVAL;
Rob Clark3c810c62012-08-15 15:18:01 -0500302 }
303
Laurent Pincharta42133a2015-01-17 19:09:26 +0200304 /*
305 * We're done if the plane is disabled, properties will be applied the
306 * next time it becomes enabled.
307 */
308 if (!omap_plane->enabled)
309 return 0;
310
311 ret = omap_plane_setup(omap_plane);
312 if (ret < 0)
313 return ret;
314
315 return omap_crtc_flush(plane->crtc);
Rob Clark3c810c62012-08-15 15:18:01 -0500316}
317
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600318static const struct drm_plane_funcs omap_plane_funcs = {
Laurent Pinchartcef77d42015-03-05 21:50:00 +0200319 .update_plane = drm_atomic_helper_update_plane,
320 .disable_plane = drm_atomic_helper_disable_plane,
Laurent Pinchart69a12262015-03-05 21:38:16 +0200321 .reset = drm_atomic_helper_plane_reset,
Laurent Pinchart222025e2015-01-11 00:02:07 +0200322 .destroy = omap_plane_destroy,
323 .set_property = omap_plane_set_property,
Laurent Pinchart69a12262015-03-05 21:38:16 +0200324 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
325 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600326};
327
Rob Clarkf5f94542012-12-04 13:59:12 -0600328static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
329{
330 struct omap_plane *omap_plane =
331 container_of(irq, struct omap_plane, error_irq);
Tomi Valkeinen3b143fc2014-11-19 12:50:13 +0200332 DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_plane->name,
333 irqstatus);
Rob Clarkf5f94542012-12-04 13:59:12 -0600334}
335
336static const char *plane_names[] = {
Laurent Pinchart222025e2015-01-11 00:02:07 +0200337 [OMAP_DSS_GFX] = "gfx",
338 [OMAP_DSS_VIDEO1] = "vid1",
339 [OMAP_DSS_VIDEO2] = "vid2",
340 [OMAP_DSS_VIDEO3] = "vid3",
Rob Clarkf5f94542012-12-04 13:59:12 -0600341};
342
343static const uint32_t error_irqs[] = {
Laurent Pinchart222025e2015-01-11 00:02:07 +0200344 [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
345 [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
346 [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
347 [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
Rob Clarkf5f94542012-12-04 13:59:12 -0600348};
349
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600350/* initialize plane */
351struct drm_plane *omap_plane_init(struct drm_device *dev,
Laurent Pinchartef6b0e02015-01-11 00:11:18 +0200352 int id, enum drm_plane_type type)
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600353{
Rob Clarkf5f94542012-12-04 13:59:12 -0600354 struct omap_drm_private *priv = dev->dev_private;
Laurent Pinchartef6b0e02015-01-11 00:11:18 +0200355 struct drm_plane *plane;
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600356 struct omap_plane *omap_plane;
Rob Clarkf5f94542012-12-04 13:59:12 -0600357 struct omap_overlay_info *info;
Laurent Pinchartef6b0e02015-01-11 00:11:18 +0200358 int ret;
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600359
Laurent Pinchartef6b0e02015-01-11 00:11:18 +0200360 DBG("%s: type=%d", plane_names[id], type);
Rob Clarkb33f34d2012-03-05 10:48:35 -0600361
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600362 omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
Joe Perches78110bb2013-02-11 09:41:29 -0800363 if (!omap_plane)
Laurent Pinchartfb9a35f2015-01-11 16:30:44 +0200364 return ERR_PTR(-ENOMEM);
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600365
Rob Clarka890e662012-03-05 10:48:31 -0600366 omap_plane->nformats = omap_framebuffer_get_formats(
367 omap_plane->formats, ARRAY_SIZE(omap_plane->formats),
Rob Clarkf5f94542012-12-04 13:59:12 -0600368 dss_feat_get_supported_color_modes(id));
369 omap_plane->id = id;
370 omap_plane->name = plane_names[id];
371
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600372 plane = &omap_plane->base;
373
Rob Clarkf5f94542012-12-04 13:59:12 -0600374 omap_plane->error_irq.irqmask = error_irqs[id];
375 omap_plane->error_irq.irq = omap_plane_error_irq;
376 omap_irq_register(dev, &omap_plane->error_irq);
377
Laurent Pinchartef6b0e02015-01-11 00:11:18 +0200378 ret = drm_universal_plane_init(dev, plane, (1 << priv->num_crtcs) - 1,
379 &omap_plane_funcs, omap_plane->formats,
380 omap_plane->nformats, type);
381 if (ret < 0)
382 goto error;
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600383
Laurent Pinchartde8e4102015-03-05 13:39:56 +0200384 drm_plane_helper_add(plane, &omap_plane_helper_funcs);
385
Rob Clark3c810c62012-08-15 15:18:01 -0500386 omap_plane_install_properties(plane, &plane->base);
387
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600388 /* get our starting configuration, set defaults for parameters
389 * we don't currently use, etc:
390 */
Rob Clarkf5f94542012-12-04 13:59:12 -0600391 info = &omap_plane->info;
392 info->rotation_type = OMAP_DSS_ROT_DMA;
393 info->rotation = OMAP_DSS_ROT_0;
394 info->global_alpha = 0xff;
395 info->mirror = 0;
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600396
397 /* Set defaults depending on whether we are a CRTC or overlay
398 * layer.
399 * TODO add ioctl to give userspace an API to change this.. this
400 * will come in a subsequent patch.
401 */
Laurent Pinchartef6b0e02015-01-11 00:11:18 +0200402 if (type == DRM_PLANE_TYPE_PRIMARY)
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600403 omap_plane->info.zorder = 0;
404 else
Rob Clarkf5f94542012-12-04 13:59:12 -0600405 omap_plane->info.zorder = id;
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600406
407 return plane;
Laurent Pinchartef6b0e02015-01-11 00:11:18 +0200408
409error:
410 omap_irq_unregister(plane->dev, &omap_plane->error_irq);
411 kfree(omap_plane);
412 return NULL;
Rob Clarkbb5c2d92012-01-16 12:51:16 -0600413}