18bb0daffSRob Clark /* 28bb0daffSRob Clark * drivers/gpu/drm/omapdrm/omap_plane.c 38bb0daffSRob Clark * 48bb0daffSRob Clark * Copyright (C) 2011 Texas Instruments 58bb0daffSRob Clark * Author: Rob Clark <rob.clark@linaro.org> 68bb0daffSRob Clark * 78bb0daffSRob Clark * This program is free software; you can redistribute it and/or modify it 88bb0daffSRob Clark * under the terms of the GNU General Public License version 2 as published by 98bb0daffSRob Clark * the Free Software Foundation. 108bb0daffSRob Clark * 118bb0daffSRob Clark * This program is distributed in the hope that it will be useful, but WITHOUT 128bb0daffSRob Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 138bb0daffSRob Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 148bb0daffSRob Clark * more details. 158bb0daffSRob Clark * 168bb0daffSRob Clark * You should have received a copy of the GNU General Public License along with 178bb0daffSRob Clark * this program. If not, see <http://www.gnu.org/licenses/>. 188bb0daffSRob Clark */ 198bb0daffSRob Clark 205833bd2fSRob Clark #include "drm_flip_work.h" 218bb0daffSRob Clark 228bb0daffSRob Clark #include "omap_drv.h" 238bb0daffSRob Clark #include "omap_dmm_tiler.h" 248bb0daffSRob Clark 258bb0daffSRob Clark /* some hackery because omapdss has an 'enum omap_plane' (which would be 268bb0daffSRob Clark * better named omap_plane_id).. and compiler seems unhappy about having 278bb0daffSRob Clark * both a 'struct omap_plane' and 'enum omap_plane' 288bb0daffSRob Clark */ 298bb0daffSRob Clark #define omap_plane _omap_plane 308bb0daffSRob Clark 318bb0daffSRob Clark /* 328bb0daffSRob Clark * plane funcs 338bb0daffSRob Clark */ 348bb0daffSRob Clark 358bb0daffSRob Clark struct callback { 368bb0daffSRob Clark void (*fxn)(void *); 378bb0daffSRob Clark void *arg; 388bb0daffSRob Clark }; 398bb0daffSRob Clark 408bb0daffSRob Clark #define to_omap_plane(x) container_of(x, struct omap_plane, base) 418bb0daffSRob Clark 428bb0daffSRob Clark struct omap_plane { 438bb0daffSRob Clark struct drm_plane base; 448bb0daffSRob Clark int id; /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */ 458bb0daffSRob Clark const char *name; 468bb0daffSRob Clark struct omap_overlay_info info; 478bb0daffSRob Clark struct omap_drm_apply apply; 488bb0daffSRob Clark 498bb0daffSRob Clark /* position/orientation of scanout within the fb: */ 508bb0daffSRob Clark struct omap_drm_window win; 518bb0daffSRob Clark bool enabled; 528bb0daffSRob Clark 538bb0daffSRob Clark /* last fb that we pinned: */ 548bb0daffSRob Clark struct drm_framebuffer *pinned_fb; 558bb0daffSRob Clark 568bb0daffSRob Clark uint32_t nformats; 578bb0daffSRob Clark uint32_t formats[32]; 588bb0daffSRob Clark 598bb0daffSRob Clark struct omap_drm_irq error_irq; 608bb0daffSRob Clark 615833bd2fSRob Clark /* for deferring bo unpin's until next post_apply(): */ 625833bd2fSRob Clark struct drm_flip_work unpin_work; 638bb0daffSRob Clark 648bb0daffSRob Clark // XXX maybe get rid of this and handle vblank in crtc too? 658bb0daffSRob Clark struct callback apply_done_cb; 668bb0daffSRob Clark }; 678bb0daffSRob Clark 685833bd2fSRob Clark static void unpin_worker(struct drm_flip_work *work, void *val) 698bb0daffSRob Clark { 705833bd2fSRob Clark struct omap_plane *omap_plane = 715833bd2fSRob Clark container_of(work, struct omap_plane, unpin_work); 725833bd2fSRob Clark struct drm_device *dev = omap_plane->base.dev; 738bb0daffSRob Clark 745833bd2fSRob Clark omap_framebuffer_unpin(val); 755833bd2fSRob Clark mutex_lock(&dev->mode_config.mutex); 765833bd2fSRob Clark drm_framebuffer_unreference(val); 775833bd2fSRob Clark mutex_unlock(&dev->mode_config.mutex); 788bb0daffSRob Clark } 798bb0daffSRob Clark 808bb0daffSRob Clark /* update which fb (if any) is pinned for scanout */ 818bb0daffSRob Clark static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb) 828bb0daffSRob Clark { 838bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 848bb0daffSRob Clark struct drm_framebuffer *pinned_fb = omap_plane->pinned_fb; 858bb0daffSRob Clark 868bb0daffSRob Clark if (pinned_fb != fb) { 875833bd2fSRob Clark int ret = 0; 888bb0daffSRob Clark 898bb0daffSRob Clark DBG("%p -> %p", pinned_fb, fb); 908bb0daffSRob Clark 915833bd2fSRob Clark if (fb) { 928bb0daffSRob Clark drm_framebuffer_reference(fb); 935833bd2fSRob Clark ret = omap_framebuffer_pin(fb); 945833bd2fSRob Clark } 958bb0daffSRob Clark 968bb0daffSRob Clark if (pinned_fb) 975833bd2fSRob Clark drm_flip_work_queue(&omap_plane->unpin_work, pinned_fb); 988bb0daffSRob Clark 998bb0daffSRob Clark if (ret) { 1008bb0daffSRob Clark dev_err(plane->dev->dev, "could not swap %p -> %p\n", 1018bb0daffSRob Clark omap_plane->pinned_fb, fb); 1028bb0daffSRob Clark drm_framebuffer_unreference(fb); 1038bb0daffSRob Clark omap_plane->pinned_fb = NULL; 1048bb0daffSRob Clark return ret; 1058bb0daffSRob Clark } 1068bb0daffSRob Clark 1078bb0daffSRob Clark omap_plane->pinned_fb = fb; 1088bb0daffSRob Clark } 1098bb0daffSRob Clark 1108bb0daffSRob Clark return 0; 1118bb0daffSRob Clark } 1128bb0daffSRob Clark 1138bb0daffSRob Clark static void omap_plane_pre_apply(struct omap_drm_apply *apply) 1148bb0daffSRob Clark { 1158bb0daffSRob Clark struct omap_plane *omap_plane = 1168bb0daffSRob Clark container_of(apply, struct omap_plane, apply); 1178bb0daffSRob Clark struct omap_drm_window *win = &omap_plane->win; 1188bb0daffSRob Clark struct drm_plane *plane = &omap_plane->base; 1198bb0daffSRob Clark struct drm_device *dev = plane->dev; 1208bb0daffSRob Clark struct omap_overlay_info *info = &omap_plane->info; 1218bb0daffSRob Clark struct drm_crtc *crtc = plane->crtc; 1228bb0daffSRob Clark enum omap_channel channel; 1238bb0daffSRob Clark bool enabled = omap_plane->enabled && crtc; 1248bb0daffSRob Clark bool ilace, replication; 1258bb0daffSRob Clark int ret; 1268bb0daffSRob Clark 1278bb0daffSRob Clark DBG("%s, enabled=%d", omap_plane->name, enabled); 1288bb0daffSRob Clark 1298bb0daffSRob Clark /* if fb has changed, pin new fb: */ 1308bb0daffSRob Clark update_pin(plane, enabled ? plane->fb : NULL); 1318bb0daffSRob Clark 1328bb0daffSRob Clark if (!enabled) { 1338bb0daffSRob Clark dispc_ovl_enable(omap_plane->id, false); 1348bb0daffSRob Clark return; 1358bb0daffSRob Clark } 1368bb0daffSRob Clark 1378bb0daffSRob Clark channel = omap_crtc_channel(crtc); 1388bb0daffSRob Clark 1398bb0daffSRob Clark /* update scanout: */ 1408bb0daffSRob Clark omap_framebuffer_update_scanout(plane->fb, win, info); 1418bb0daffSRob Clark 1428bb0daffSRob Clark DBG("%dx%d -> %dx%d (%d)", info->width, info->height, 1438bb0daffSRob Clark info->out_width, info->out_height, 1448bb0daffSRob Clark info->screen_width); 1452d31ca3aSRussell King DBG("%d,%d %pad %pad", info->pos_x, info->pos_y, 1462d31ca3aSRussell King &info->paddr, &info->p_uv_addr); 1478bb0daffSRob Clark 1488bb0daffSRob Clark /* TODO: */ 1498bb0daffSRob Clark ilace = false; 1508bb0daffSRob Clark replication = false; 1518bb0daffSRob Clark 1528bb0daffSRob Clark /* and finally, update omapdss: */ 1538bb0daffSRob Clark ret = dispc_ovl_setup(omap_plane->id, info, 1548bb0daffSRob Clark replication, omap_crtc_timings(crtc), false); 1558bb0daffSRob Clark if (ret) { 1568bb0daffSRob Clark dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret); 1578bb0daffSRob Clark return; 1588bb0daffSRob Clark } 1598bb0daffSRob Clark 1608bb0daffSRob Clark dispc_ovl_enable(omap_plane->id, true); 1618bb0daffSRob Clark dispc_ovl_set_channel_out(omap_plane->id, channel); 1628bb0daffSRob Clark } 1638bb0daffSRob Clark 1648bb0daffSRob Clark static void omap_plane_post_apply(struct omap_drm_apply *apply) 1658bb0daffSRob Clark { 1668bb0daffSRob Clark struct omap_plane *omap_plane = 1678bb0daffSRob Clark container_of(apply, struct omap_plane, apply); 1688bb0daffSRob Clark struct drm_plane *plane = &omap_plane->base; 1695833bd2fSRob Clark struct omap_drm_private *priv = plane->dev->dev_private; 1708bb0daffSRob Clark struct omap_overlay_info *info = &omap_plane->info; 1718bb0daffSRob Clark struct callback cb; 1728bb0daffSRob Clark 1738bb0daffSRob Clark cb = omap_plane->apply_done_cb; 1748bb0daffSRob Clark omap_plane->apply_done_cb.fxn = NULL; 1758bb0daffSRob Clark 1765833bd2fSRob Clark drm_flip_work_commit(&omap_plane->unpin_work, priv->wq); 1778bb0daffSRob Clark 1788bb0daffSRob Clark if (cb.fxn) 1798bb0daffSRob Clark cb.fxn(cb.arg); 1808bb0daffSRob Clark 1818bb0daffSRob Clark if (omap_plane->enabled) { 1828bb0daffSRob Clark omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y, 1838bb0daffSRob Clark info->out_width, info->out_height); 1848bb0daffSRob Clark } 1858bb0daffSRob Clark } 1868bb0daffSRob Clark 1878bb0daffSRob Clark static int apply(struct drm_plane *plane) 1888bb0daffSRob Clark { 1898bb0daffSRob Clark if (plane->crtc) { 1908bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 1918bb0daffSRob Clark return omap_crtc_apply(plane->crtc, &omap_plane->apply); 1928bb0daffSRob Clark } 1938bb0daffSRob Clark return 0; 1948bb0daffSRob Clark } 1958bb0daffSRob Clark 1968bb0daffSRob Clark int omap_plane_mode_set(struct drm_plane *plane, 1978bb0daffSRob Clark struct drm_crtc *crtc, struct drm_framebuffer *fb, 1988bb0daffSRob Clark int crtc_x, int crtc_y, 1998bb0daffSRob Clark unsigned int crtc_w, unsigned int crtc_h, 2008bb0daffSRob Clark uint32_t src_x, uint32_t src_y, 2018bb0daffSRob Clark uint32_t src_w, uint32_t src_h, 2028bb0daffSRob Clark void (*fxn)(void *), void *arg) 2038bb0daffSRob Clark { 2048bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 2058bb0daffSRob Clark struct omap_drm_window *win = &omap_plane->win; 2068bb0daffSRob Clark 2078bb0daffSRob Clark win->crtc_x = crtc_x; 2088bb0daffSRob Clark win->crtc_y = crtc_y; 2098bb0daffSRob Clark win->crtc_w = crtc_w; 2108bb0daffSRob Clark win->crtc_h = crtc_h; 2118bb0daffSRob Clark 2128bb0daffSRob Clark /* src values are in Q16 fixed point, convert to integer: */ 2138bb0daffSRob Clark win->src_x = src_x >> 16; 2148bb0daffSRob Clark win->src_y = src_y >> 16; 2158bb0daffSRob Clark win->src_w = src_w >> 16; 2168bb0daffSRob Clark win->src_h = src_h >> 16; 2178bb0daffSRob Clark 2188bb0daffSRob Clark if (fxn) { 2198bb0daffSRob Clark /* omap_crtc should ensure that a new page flip 2208bb0daffSRob Clark * isn't permitted while there is one pending: 2218bb0daffSRob Clark */ 2228bb0daffSRob Clark BUG_ON(omap_plane->apply_done_cb.fxn); 2238bb0daffSRob Clark 2248bb0daffSRob Clark omap_plane->apply_done_cb.fxn = fxn; 2258bb0daffSRob Clark omap_plane->apply_done_cb.arg = arg; 2268bb0daffSRob Clark } 2278bb0daffSRob Clark 228f2d022aaSTomi Valkeinen if (plane->fb) 229f2d022aaSTomi Valkeinen drm_framebuffer_unreference(plane->fb); 230f2d022aaSTomi Valkeinen 231f2d022aaSTomi Valkeinen drm_framebuffer_reference(fb); 232f2d022aaSTomi Valkeinen 2338bb0daffSRob Clark plane->fb = fb; 2348bb0daffSRob Clark plane->crtc = crtc; 2358bb0daffSRob Clark 2368bb0daffSRob Clark return apply(plane); 2378bb0daffSRob Clark } 2388bb0daffSRob Clark 2398bb0daffSRob Clark static int omap_plane_update(struct drm_plane *plane, 2408bb0daffSRob Clark struct drm_crtc *crtc, struct drm_framebuffer *fb, 2418bb0daffSRob Clark int crtc_x, int crtc_y, 2428bb0daffSRob Clark unsigned int crtc_w, unsigned int crtc_h, 2438bb0daffSRob Clark uint32_t src_x, uint32_t src_y, 2448bb0daffSRob Clark uint32_t src_w, uint32_t src_h) 2458bb0daffSRob Clark { 2468bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 2478bb0daffSRob Clark omap_plane->enabled = true; 248b03e14fdSArchit Taneja 249d4586604SGrazvydas Ignotas /* omap_plane_mode_set() takes adjusted src */ 250d4586604SGrazvydas Ignotas switch (omap_plane->win.rotation & 0xf) { 251d4586604SGrazvydas Ignotas case BIT(DRM_ROTATE_90): 252d4586604SGrazvydas Ignotas case BIT(DRM_ROTATE_270): 253d4586604SGrazvydas Ignotas swap(src_w, src_h); 254d4586604SGrazvydas Ignotas break; 255d4586604SGrazvydas Ignotas } 256d4586604SGrazvydas Ignotas 2578bb0daffSRob Clark return omap_plane_mode_set(plane, crtc, fb, 2588bb0daffSRob Clark crtc_x, crtc_y, crtc_w, crtc_h, 2598bb0daffSRob Clark src_x, src_y, src_w, src_h, 2608bb0daffSRob Clark NULL, NULL); 2618bb0daffSRob Clark } 2628bb0daffSRob Clark 2638bb0daffSRob Clark static int omap_plane_disable(struct drm_plane *plane) 2648bb0daffSRob Clark { 2658bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 2668bb0daffSRob Clark omap_plane->win.rotation = BIT(DRM_ROTATE_0); 2678bb0daffSRob Clark return omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); 2688bb0daffSRob Clark } 2698bb0daffSRob Clark 2708bb0daffSRob Clark static void omap_plane_destroy(struct drm_plane *plane) 2718bb0daffSRob Clark { 2728bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 2738bb0daffSRob Clark 2748bb0daffSRob Clark DBG("%s", omap_plane->name); 2758bb0daffSRob Clark 2768bb0daffSRob Clark omap_irq_unregister(plane->dev, &omap_plane->error_irq); 2778bb0daffSRob Clark 2788bb0daffSRob Clark omap_plane_disable(plane); 2798bb0daffSRob Clark drm_plane_cleanup(plane); 2808bb0daffSRob Clark 2815833bd2fSRob Clark drm_flip_work_cleanup(&omap_plane->unpin_work); 2828bb0daffSRob Clark 2838bb0daffSRob Clark kfree(omap_plane); 2848bb0daffSRob Clark } 2858bb0daffSRob Clark 2868bb0daffSRob Clark int omap_plane_dpms(struct drm_plane *plane, int mode) 2878bb0daffSRob Clark { 2888bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 2898bb0daffSRob Clark bool enabled = (mode == DRM_MODE_DPMS_ON); 2908bb0daffSRob Clark int ret = 0; 2918bb0daffSRob Clark 2928bb0daffSRob Clark if (enabled != omap_plane->enabled) { 2938bb0daffSRob Clark omap_plane->enabled = enabled; 2948bb0daffSRob Clark ret = apply(plane); 2958bb0daffSRob Clark } 2968bb0daffSRob Clark 2978bb0daffSRob Clark return ret; 2988bb0daffSRob Clark } 2998bb0daffSRob Clark 3008bb0daffSRob Clark /* helper to install properties which are common to planes and crtcs */ 3018bb0daffSRob Clark void omap_plane_install_properties(struct drm_plane *plane, 3028bb0daffSRob Clark struct drm_mode_object *obj) 3038bb0daffSRob Clark { 3048bb0daffSRob Clark struct drm_device *dev = plane->dev; 3058bb0daffSRob Clark struct omap_drm_private *priv = dev->dev_private; 3068bb0daffSRob Clark struct drm_property *prop; 3078bb0daffSRob Clark 3088bb0daffSRob Clark if (priv->has_dmm) { 3098bb0daffSRob Clark prop = priv->rotation_prop; 3108bb0daffSRob Clark if (!prop) { 311a4969dd7SVille Syrjälä prop = drm_mode_create_rotation_property(dev, 312a4969dd7SVille Syrjälä BIT(DRM_ROTATE_0) | 313a4969dd7SVille Syrjälä BIT(DRM_ROTATE_90) | 314a4969dd7SVille Syrjälä BIT(DRM_ROTATE_180) | 315a4969dd7SVille Syrjälä BIT(DRM_ROTATE_270) | 316a4969dd7SVille Syrjälä BIT(DRM_REFLECT_X) | 317a4969dd7SVille Syrjälä BIT(DRM_REFLECT_Y)); 3188bb0daffSRob Clark if (prop == NULL) 3198bb0daffSRob Clark return; 3208bb0daffSRob Clark priv->rotation_prop = prop; 3218bb0daffSRob Clark } 3228bb0daffSRob Clark drm_object_attach_property(obj, prop, 0); 3238bb0daffSRob Clark } 3248bb0daffSRob Clark 3258bb0daffSRob Clark prop = priv->zorder_prop; 3268bb0daffSRob Clark if (!prop) { 3278bb0daffSRob Clark prop = drm_property_create_range(dev, 0, "zorder", 0, 3); 3288bb0daffSRob Clark if (prop == NULL) 3298bb0daffSRob Clark return; 3308bb0daffSRob Clark priv->zorder_prop = prop; 3318bb0daffSRob Clark } 3328bb0daffSRob Clark drm_object_attach_property(obj, prop, 0); 3338bb0daffSRob Clark } 3348bb0daffSRob Clark 3358bb0daffSRob Clark int omap_plane_set_property(struct drm_plane *plane, 3368bb0daffSRob Clark struct drm_property *property, uint64_t val) 3378bb0daffSRob Clark { 3388bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 3398bb0daffSRob Clark struct omap_drm_private *priv = plane->dev->dev_private; 3408bb0daffSRob Clark int ret = -EINVAL; 3418bb0daffSRob Clark 3428bb0daffSRob Clark if (property == priv->rotation_prop) { 3438bb0daffSRob Clark DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val); 3448bb0daffSRob Clark omap_plane->win.rotation = val; 3458bb0daffSRob Clark ret = apply(plane); 3468bb0daffSRob Clark } else if (property == priv->zorder_prop) { 3478bb0daffSRob Clark DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val); 3488bb0daffSRob Clark omap_plane->info.zorder = val; 3498bb0daffSRob Clark ret = apply(plane); 3508bb0daffSRob Clark } 3518bb0daffSRob Clark 3528bb0daffSRob Clark return ret; 3538bb0daffSRob Clark } 3548bb0daffSRob Clark 3558bb0daffSRob Clark static const struct drm_plane_funcs omap_plane_funcs = { 3568bb0daffSRob Clark .update_plane = omap_plane_update, 3578bb0daffSRob Clark .disable_plane = omap_plane_disable, 3588bb0daffSRob Clark .destroy = omap_plane_destroy, 3598bb0daffSRob Clark .set_property = omap_plane_set_property, 3608bb0daffSRob Clark }; 3618bb0daffSRob Clark 3628bb0daffSRob Clark static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) 3638bb0daffSRob Clark { 3648bb0daffSRob Clark struct omap_plane *omap_plane = 3658bb0daffSRob Clark container_of(irq, struct omap_plane, error_irq); 3668bb0daffSRob Clark DRM_ERROR("%s: errors: %08x\n", omap_plane->name, irqstatus); 3678bb0daffSRob Clark } 3688bb0daffSRob Clark 3698bb0daffSRob Clark static const char *plane_names[] = { 3708bb0daffSRob Clark [OMAP_DSS_GFX] = "gfx", 3718bb0daffSRob Clark [OMAP_DSS_VIDEO1] = "vid1", 3728bb0daffSRob Clark [OMAP_DSS_VIDEO2] = "vid2", 3738bb0daffSRob Clark [OMAP_DSS_VIDEO3] = "vid3", 3748bb0daffSRob Clark }; 3758bb0daffSRob Clark 3768bb0daffSRob Clark static const uint32_t error_irqs[] = { 3778bb0daffSRob Clark [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW, 3788bb0daffSRob Clark [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW, 3798bb0daffSRob Clark [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW, 3808bb0daffSRob Clark [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW, 3818bb0daffSRob Clark }; 3828bb0daffSRob Clark 3838bb0daffSRob Clark /* initialize plane */ 3848bb0daffSRob Clark struct drm_plane *omap_plane_init(struct drm_device *dev, 3858bb0daffSRob Clark int id, bool private_plane) 3868bb0daffSRob Clark { 3878bb0daffSRob Clark struct omap_drm_private *priv = dev->dev_private; 3888bb0daffSRob Clark struct drm_plane *plane = NULL; 3898bb0daffSRob Clark struct omap_plane *omap_plane; 3908bb0daffSRob Clark struct omap_overlay_info *info; 3918bb0daffSRob Clark 3928bb0daffSRob Clark DBG("%s: priv=%d", plane_names[id], private_plane); 3938bb0daffSRob Clark 3948bb0daffSRob Clark omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); 395fffddfd6SLinus Torvalds if (!omap_plane) 396fb9a35f8SLaurent Pinchart return ERR_PTR(-ENOMEM); 3978bb0daffSRob Clark 398d7f8db53SBoris BREZILLON drm_flip_work_init(&omap_plane->unpin_work, 3995833bd2fSRob Clark "unpin", unpin_worker); 4008bb0daffSRob Clark 4018bb0daffSRob Clark omap_plane->nformats = omap_framebuffer_get_formats( 4028bb0daffSRob Clark omap_plane->formats, ARRAY_SIZE(omap_plane->formats), 4038bb0daffSRob Clark dss_feat_get_supported_color_modes(id)); 4048bb0daffSRob Clark omap_plane->id = id; 4058bb0daffSRob Clark omap_plane->name = plane_names[id]; 4068bb0daffSRob Clark 4078bb0daffSRob Clark plane = &omap_plane->base; 4088bb0daffSRob Clark 4098bb0daffSRob Clark omap_plane->apply.pre_apply = omap_plane_pre_apply; 4108bb0daffSRob Clark omap_plane->apply.post_apply = omap_plane_post_apply; 4118bb0daffSRob Clark 4128bb0daffSRob Clark omap_plane->error_irq.irqmask = error_irqs[id]; 4138bb0daffSRob Clark omap_plane->error_irq.irq = omap_plane_error_irq; 4148bb0daffSRob Clark omap_irq_register(dev, &omap_plane->error_irq); 4158bb0daffSRob Clark 4168bb0daffSRob Clark drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs, 4178bb0daffSRob Clark omap_plane->formats, omap_plane->nformats, private_plane); 4188bb0daffSRob Clark 4198bb0daffSRob Clark omap_plane_install_properties(plane, &plane->base); 4208bb0daffSRob Clark 4218bb0daffSRob Clark /* get our starting configuration, set defaults for parameters 4228bb0daffSRob Clark * we don't currently use, etc: 4238bb0daffSRob Clark */ 4248bb0daffSRob Clark info = &omap_plane->info; 4258bb0daffSRob Clark info->rotation_type = OMAP_DSS_ROT_DMA; 4268bb0daffSRob Clark info->rotation = OMAP_DSS_ROT_0; 4278bb0daffSRob Clark info->global_alpha = 0xff; 4288bb0daffSRob Clark info->mirror = 0; 4298bb0daffSRob Clark 4308bb0daffSRob Clark /* Set defaults depending on whether we are a CRTC or overlay 4318bb0daffSRob Clark * layer. 4328bb0daffSRob Clark * TODO add ioctl to give userspace an API to change this.. this 4338bb0daffSRob Clark * will come in a subsequent patch. 4348bb0daffSRob Clark */ 4358bb0daffSRob Clark if (private_plane) 4368bb0daffSRob Clark omap_plane->info.zorder = 0; 4378bb0daffSRob Clark else 4388bb0daffSRob Clark omap_plane->info.zorder = id; 4398bb0daffSRob Clark 4408bb0daffSRob Clark return plane; 4418bb0daffSRob Clark } 442