1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 28bb0daffSRob Clark /* 31b409fdaSAlexander A. Klimov * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/ 48bb0daffSRob Clark * Author: Rob Clark <rob.clark@linaro.org> 58bb0daffSRob Clark */ 68bb0daffSRob Clark 7c423bc85STomi Valkeinen #include <drm/drm_atomic.h> 869a12263SLaurent Pinchart #include <drm/drm_atomic_helper.h> 9942d8344SDaniel Vetter #include <drm/drm_gem_atomic_helper.h> 10de8e4100SLaurent Pinchart #include <drm/drm_plane_helper.h> 1169a12263SLaurent Pinchart 128bb0daffSRob Clark #include "omap_dmm_tiler.h" 132d278f54SLaurent Pinchart #include "omap_drv.h" 148bb0daffSRob Clark 158bb0daffSRob Clark /* 168bb0daffSRob Clark * plane funcs 178bb0daffSRob Clark */ 188bb0daffSRob Clark 198bb0daffSRob Clark #define to_omap_plane(x) container_of(x, struct omap_plane, base) 208bb0daffSRob Clark 218bb0daffSRob Clark struct omap_plane { 228bb0daffSRob Clark struct drm_plane base; 23694c99cfSJyri Sarha enum omap_plane_id id; 24*c8fa1e73SBenoit Parrot 25*c8fa1e73SBenoit Parrot struct omap_hw_overlay *overlay; 268bb0daffSRob Clark }; 278bb0daffSRob Clark 2811ffd031STomi Valkeinen static int omap_plane_prepare_fb(struct drm_plane *plane, 291832040dSChris Wilson struct drm_plane_state *new_state) 3011ffd031STomi Valkeinen { 31844f9111SMaarten Lankhorst if (!new_state->fb) 32844f9111SMaarten Lankhorst return 0; 33844f9111SMaarten Lankhorst 34942d8344SDaniel Vetter drm_gem_plane_helper_prepare_fb(plane, new_state); 35942d8344SDaniel Vetter 36844f9111SMaarten Lankhorst return omap_framebuffer_pin(new_state->fb); 3711ffd031STomi Valkeinen } 3811ffd031STomi Valkeinen 3911ffd031STomi Valkeinen static void omap_plane_cleanup_fb(struct drm_plane *plane, 401832040dSChris Wilson struct drm_plane_state *old_state) 4111ffd031STomi Valkeinen { 42844f9111SMaarten Lankhorst if (old_state->fb) 43844f9111SMaarten Lankhorst omap_framebuffer_unpin(old_state->fb); 4411ffd031STomi Valkeinen } 4511ffd031STomi Valkeinen 4611ffd031STomi Valkeinen static void omap_plane_atomic_update(struct drm_plane *plane, 47977697e2SMaxime Ripard struct drm_atomic_state *state) 48afc34932SLaurent Pinchart { 499f759225STomi Valkeinen struct omap_drm_private *priv = plane->dev->dev_private; 50edc72557SLaurent Pinchart struct omap_plane *omap_plane = to_omap_plane(plane); 5137418bf1SMaxime Ripard struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 5237418bf1SMaxime Ripard plane); 53*c8fa1e73SBenoit Parrot enum omap_plane_id ovl_id = omap_plane->overlay->id; 54fb730c9bSLaurent Pinchart struct omap_overlay_info info; 558bb0daffSRob Clark int ret; 568bb0daffSRob Clark 57*c8fa1e73SBenoit Parrot DBG("%s, crtc=%p fb=%p", plane->name, new_state->crtc, 5841016fe1SMaxime Ripard new_state->fb); 598bb0daffSRob Clark 60fb730c9bSLaurent Pinchart memset(&info, 0, sizeof(info)); 61517a8a95STomi Valkeinen info.rotation_type = OMAP_DSS_ROT_NONE; 620bd97c42STomi Valkeinen info.rotation = DRM_MODE_ROTATE_0; 6341016fe1SMaxime Ripard info.global_alpha = new_state->alpha >> 8; 6441016fe1SMaxime Ripard info.zorder = new_state->normalized_zpos; 6541016fe1SMaxime Ripard if (new_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) 663037e0c5SJean-Jacques Hiblot info.pre_mult_alpha = 1; 673037e0c5SJean-Jacques Hiblot else 683037e0c5SJean-Jacques Hiblot info.pre_mult_alpha = 0; 6941016fe1SMaxime Ripard info.color_encoding = new_state->color_encoding; 7041016fe1SMaxime Ripard info.color_range = new_state->color_range; 71fb730c9bSLaurent Pinchart 728bb0daffSRob Clark /* update scanout: */ 7341016fe1SMaxime Ripard omap_framebuffer_update_scanout(new_state->fb, new_state, &info); 748bb0daffSRob Clark 75fb730c9bSLaurent Pinchart DBG("%dx%d -> %dx%d (%d)", info.width, info.height, 76fb730c9bSLaurent Pinchart info.out_width, info.out_height, 77fb730c9bSLaurent Pinchart info.screen_width); 78fb730c9bSLaurent Pinchart DBG("%d,%d %pad %pad", info.pos_x, info.pos_y, 79fb730c9bSLaurent Pinchart &info.paddr, &info.p_uv_addr); 808bb0daffSRob Clark 818bb0daffSRob Clark /* and finally, update omapdss: */ 82*c8fa1e73SBenoit Parrot ret = dispc_ovl_setup(priv->dispc, ovl_id, &info, 8341016fe1SMaxime Ripard omap_crtc_timings(new_state->crtc), false, 8441016fe1SMaxime Ripard omap_crtc_channel(new_state->crtc)); 85cfb73f20STomi Valkeinen if (ret) { 86cfb73f20STomi Valkeinen dev_err(plane->dev->dev, "Failed to setup plane %s\n", 87*c8fa1e73SBenoit Parrot plane->name); 88*c8fa1e73SBenoit Parrot dispc_ovl_enable(priv->dispc, ovl_id, false); 89d9157dfdSTomi Valkeinen return; 90794a65ffSTomi Valkeinen } 918bb0daffSRob Clark 92*c8fa1e73SBenoit Parrot dispc_ovl_enable(priv->dispc, ovl_id, true); 93de8e4100SLaurent Pinchart } 94de8e4100SLaurent Pinchart 95de8e4100SLaurent Pinchart static void omap_plane_atomic_disable(struct drm_plane *plane, 96977697e2SMaxime Ripard struct drm_atomic_state *state) 978bb0daffSRob Clark { 9837418bf1SMaxime Ripard struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 9937418bf1SMaxime Ripard plane); 1009f759225STomi Valkeinen struct omap_drm_private *priv = plane->dev->dev_private; 1018bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 102*c8fa1e73SBenoit Parrot enum omap_plane_id ovl_id = omap_plane->overlay->id; 1032debab97SLaurent Pinchart 104e05162c0SMaxime Ripard new_state->rotation = DRM_MODE_ROTATE_0; 105e05162c0SMaxime Ripard new_state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : omap_plane->id; 10682e58855SLaurent Pinchart 107*c8fa1e73SBenoit Parrot dispc_ovl_enable(priv->dispc, ovl_id, false); 1088bb0daffSRob Clark } 1098bb0daffSRob Clark 110c21134b0SNeil Armstrong #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) 111c21134b0SNeil Armstrong 112c423bc85STomi Valkeinen static int omap_plane_atomic_check(struct drm_plane *plane, 1137c11b99aSMaxime Ripard struct drm_atomic_state *state) 114c423bc85STomi Valkeinen { 1157c11b99aSMaxime Ripard struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 1167c11b99aSMaxime Ripard plane); 117d484c20dSBenoit Parrot struct omap_drm_private *priv = plane->dev->dev_private; 118c423bc85STomi Valkeinen struct drm_crtc_state *crtc_state; 119d484c20dSBenoit Parrot u32 max_width, max_height; 120d484c20dSBenoit Parrot u16 width, height; 121c21134b0SNeil Armstrong int ret; 122c423bc85STomi Valkeinen 123ba5c1649SMaxime Ripard if (!new_plane_state->fb) 124c423bc85STomi Valkeinen return 0; 125c423bc85STomi Valkeinen 126d484c20dSBenoit Parrot dispc_ovl_get_max_size(priv->dispc, &width, &height); 127d484c20dSBenoit Parrot max_width = width << 16; 128d484c20dSBenoit Parrot max_height = height << 16; 129d484c20dSBenoit Parrot 130ba5c1649SMaxime Ripard /* crtc should only be NULL when disabling (i.e., !new_plane_state->fb) */ 131ba5c1649SMaxime Ripard if (WARN_ON(!new_plane_state->crtc)) 13270dd2a62STomi Valkeinen return 0; 13370dd2a62STomi Valkeinen 134dec92020SMaxime Ripard crtc_state = drm_atomic_get_existing_crtc_state(state, 135ba5c1649SMaxime Ripard new_plane_state->crtc); 13670dd2a62STomi Valkeinen /* we should have a crtc state if the plane is attached to a crtc */ 13770dd2a62STomi Valkeinen if (WARN_ON(!crtc_state)) 13870dd2a62STomi Valkeinen return 0; 139c423bc85STomi Valkeinen 140aaf7642eSTomi Valkeinen if (!crtc_state->enable) 141aaf7642eSTomi Valkeinen return 0; 142aaf7642eSTomi Valkeinen 143c21134b0SNeil Armstrong /* 144c21134b0SNeil Armstrong * Note: these are just sanity checks to filter out totally bad scaling 145c21134b0SNeil Armstrong * factors. The real limits must be calculated case by case, and 146c21134b0SNeil Armstrong * unfortunately we currently do those checks only at the commit 147c21134b0SNeil Armstrong * phase in dispc. 148c21134b0SNeil Armstrong */ 149c21134b0SNeil Armstrong ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 150c21134b0SNeil Armstrong FRAC_16_16(1, 8), FRAC_16_16(8, 1), 151c21134b0SNeil Armstrong true, true); 152c21134b0SNeil Armstrong if (ret) 153c21134b0SNeil Armstrong return ret; 154c21134b0SNeil Armstrong 155ba5c1649SMaxime Ripard if (new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0) 156c423bc85STomi Valkeinen return -EINVAL; 157c423bc85STomi Valkeinen 158ba5c1649SMaxime Ripard if (new_plane_state->crtc_x + new_plane_state->crtc_w > crtc_state->adjusted_mode.hdisplay) 159c423bc85STomi Valkeinen return -EINVAL; 160c423bc85STomi Valkeinen 161ba5c1649SMaxime Ripard if (new_plane_state->crtc_y + new_plane_state->crtc_h > crtc_state->adjusted_mode.vdisplay) 162c423bc85STomi Valkeinen return -EINVAL; 163c423bc85STomi Valkeinen 164d484c20dSBenoit Parrot /* Make sure dimensions are within bounds. */ 165d484c20dSBenoit Parrot if (new_plane_state->src_h > max_height || new_plane_state->crtc_h > height) 166d484c20dSBenoit Parrot return -EINVAL; 167d484c20dSBenoit Parrot 168d484c20dSBenoit Parrot if (new_plane_state->src_w > max_width || new_plane_state->crtc_w > width) 169d484c20dSBenoit Parrot return -EINVAL; 170d484c20dSBenoit Parrot 171ba5c1649SMaxime Ripard if (new_plane_state->rotation != DRM_MODE_ROTATE_0 && 172ba5c1649SMaxime Ripard !omap_framebuffer_supports_rotation(new_plane_state->fb)) 173bfeece55STomi Valkeinen return -EINVAL; 174bfeece55STomi Valkeinen 175c423bc85STomi Valkeinen return 0; 176c423bc85STomi Valkeinen } 177c423bc85STomi Valkeinen 178de8e4100SLaurent Pinchart static const struct drm_plane_helper_funcs omap_plane_helper_funcs = { 179de8e4100SLaurent Pinchart .prepare_fb = omap_plane_prepare_fb, 180de8e4100SLaurent Pinchart .cleanup_fb = omap_plane_cleanup_fb, 181c423bc85STomi Valkeinen .atomic_check = omap_plane_atomic_check, 182de8e4100SLaurent Pinchart .atomic_update = omap_plane_atomic_update, 183de8e4100SLaurent Pinchart .atomic_disable = omap_plane_atomic_disable, 184de8e4100SLaurent Pinchart }; 185de8e4100SLaurent Pinchart 1868bb0daffSRob Clark static void omap_plane_destroy(struct drm_plane *plane) 1878bb0daffSRob Clark { 1888bb0daffSRob Clark struct omap_plane *omap_plane = to_omap_plane(plane); 1898bb0daffSRob Clark 190*c8fa1e73SBenoit Parrot DBG("%s", plane->name); 1918bb0daffSRob Clark 1928bb0daffSRob Clark drm_plane_cleanup(plane); 1938bb0daffSRob Clark 1948bb0daffSRob Clark kfree(omap_plane); 1958bb0daffSRob Clark } 1968bb0daffSRob Clark 1978bb0daffSRob Clark /* helper to install properties which are common to planes and crtcs */ 1988bb0daffSRob Clark void omap_plane_install_properties(struct drm_plane *plane, 1998bb0daffSRob Clark struct drm_mode_object *obj) 2008bb0daffSRob Clark { 2018bb0daffSRob Clark struct drm_device *dev = plane->dev; 2028bb0daffSRob Clark struct omap_drm_private *priv = dev->dev_private; 2038bb0daffSRob Clark 2048bb0daffSRob Clark if (priv->has_dmm) { 2050da88db1SVille Syrjälä if (!plane->rotation_property) 2060da88db1SVille Syrjälä drm_plane_create_rotation_property(plane, 207c2c446adSRobert Foss DRM_MODE_ROTATE_0, 208c2c446adSRobert Foss DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | 209c2c446adSRobert Foss DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270 | 210c2c446adSRobert Foss DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y); 211e2cd09b2SLaurent Pinchart 2120da88db1SVille Syrjälä /* Attach the rotation property also to the crtc object */ 2130da88db1SVille Syrjälä if (plane->rotation_property && obj != &plane->base) 2140da88db1SVille Syrjälä drm_object_attach_property(obj, plane->rotation_property, 215c2c446adSRobert Foss DRM_MODE_ROTATE_0); 2168bb0daffSRob Clark } 2178bb0daffSRob Clark 218e2cd09b2SLaurent Pinchart drm_object_attach_property(obj, priv->zorder_prop, 0); 2198bb0daffSRob Clark } 2208bb0daffSRob Clark 221e07323cfSTomi Valkeinen static void omap_plane_reset(struct drm_plane *plane) 222e07323cfSTomi Valkeinen { 223e07323cfSTomi Valkeinen struct omap_plane *omap_plane = to_omap_plane(plane); 224e07323cfSTomi Valkeinen 225d980278bSLaurent Pinchart drm_atomic_helper_plane_reset(plane); 226d980278bSLaurent Pinchart if (!plane->state) 227e07323cfSTomi Valkeinen return; 228e07323cfSTomi Valkeinen 229e07323cfSTomi Valkeinen /* 230ba527c13SLaurent Pinchart * Set the zpos default depending on whether we are a primary or overlay 231e07323cfSTomi Valkeinen * plane. 232e07323cfSTomi Valkeinen */ 233d980278bSLaurent Pinchart plane->state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY 234e07323cfSTomi Valkeinen ? 0 : omap_plane->id; 23564ff1891SJyri Sarha plane->state->color_encoding = DRM_COLOR_YCBCR_BT601; 23664ff1891SJyri Sarha plane->state->color_range = DRM_COLOR_YCBCR_FULL_RANGE; 237e07323cfSTomi Valkeinen } 238e07323cfSTomi Valkeinen 239afc34932SLaurent Pinchart static int omap_plane_atomic_set_property(struct drm_plane *plane, 240afc34932SLaurent Pinchart struct drm_plane_state *state, 241afc34932SLaurent Pinchart struct drm_property *property, 242dfe9cfccSLaurent Pinchart u64 val) 243afc34932SLaurent Pinchart { 244afc34932SLaurent Pinchart struct omap_drm_private *priv = plane->dev->dev_private; 245afc34932SLaurent Pinchart 246afc34932SLaurent Pinchart if (property == priv->zorder_prop) 247ba527c13SLaurent Pinchart state->zpos = val; 248afc34932SLaurent Pinchart else 249afc34932SLaurent Pinchart return -EINVAL; 250afc34932SLaurent Pinchart 251a42133a7SLaurent Pinchart return 0; 252afc34932SLaurent Pinchart } 253a42133a7SLaurent Pinchart 254afc34932SLaurent Pinchart static int omap_plane_atomic_get_property(struct drm_plane *plane, 255afc34932SLaurent Pinchart const struct drm_plane_state *state, 256afc34932SLaurent Pinchart struct drm_property *property, 257dfe9cfccSLaurent Pinchart u64 *val) 258afc34932SLaurent Pinchart { 259afc34932SLaurent Pinchart struct omap_drm_private *priv = plane->dev->dev_private; 260a42133a7SLaurent Pinchart 261afc34932SLaurent Pinchart if (property == priv->zorder_prop) 262ba527c13SLaurent Pinchart *val = state->zpos; 263afc34932SLaurent Pinchart else 264afc34932SLaurent Pinchart return -EINVAL; 265afc34932SLaurent Pinchart 266afc34932SLaurent Pinchart return 0; 2678bb0daffSRob Clark } 2688bb0daffSRob Clark 2698bb0daffSRob Clark static const struct drm_plane_funcs omap_plane_funcs = { 270cef77d40SLaurent Pinchart .update_plane = drm_atomic_helper_update_plane, 271cef77d40SLaurent Pinchart .disable_plane = drm_atomic_helper_disable_plane, 272afc34932SLaurent Pinchart .reset = omap_plane_reset, 2738bb0daffSRob Clark .destroy = omap_plane_destroy, 274d980278bSLaurent Pinchart .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 275d980278bSLaurent Pinchart .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 276afc34932SLaurent Pinchart .atomic_set_property = omap_plane_atomic_set_property, 277afc34932SLaurent Pinchart .atomic_get_property = omap_plane_atomic_get_property, 2788bb0daffSRob Clark }; 2798bb0daffSRob Clark 28064ff1891SJyri Sarha static bool omap_plane_supports_yuv(struct drm_plane *plane) 28164ff1891SJyri Sarha { 28264ff1891SJyri Sarha struct omap_drm_private *priv = plane->dev->dev_private; 28364ff1891SJyri Sarha struct omap_plane *omap_plane = to_omap_plane(plane); 284dac62bcaSTomi Valkeinen const u32 *formats = dispc_ovl_get_color_modes(priv->dispc, omap_plane->id); 28564ff1891SJyri Sarha u32 i; 28664ff1891SJyri Sarha 28764ff1891SJyri Sarha for (i = 0; formats[i]; i++) 28864ff1891SJyri Sarha if (formats[i] == DRM_FORMAT_YUYV || 28964ff1891SJyri Sarha formats[i] == DRM_FORMAT_UYVY || 29064ff1891SJyri Sarha formats[i] == DRM_FORMAT_NV12) 29164ff1891SJyri Sarha return true; 29264ff1891SJyri Sarha 29364ff1891SJyri Sarha return false; 29464ff1891SJyri Sarha } 29564ff1891SJyri Sarha 2968bb0daffSRob Clark /* initialize plane */ 2978bb0daffSRob Clark struct drm_plane *omap_plane_init(struct drm_device *dev, 298e8e13b15SJyri Sarha int idx, enum drm_plane_type type, 299e43f2c33STomi Valkeinen u32 possible_crtcs) 3008bb0daffSRob Clark { 3019f759225STomi Valkeinen struct omap_drm_private *priv = dev->dev_private; 302dac62bcaSTomi Valkeinen unsigned int num_planes = dispc_get_num_ovls(priv->dispc); 303ef6b0e02SLaurent Pinchart struct drm_plane *plane; 3048bb0daffSRob Clark struct omap_plane *omap_plane; 305ef6b0e02SLaurent Pinchart int ret; 306eecad437STomi Valkeinen u32 nformats; 307eecad437STomi Valkeinen const u32 *formats; 3088bb0daffSRob Clark 309*c8fa1e73SBenoit Parrot if (WARN_ON(idx >= num_planes)) 310e8e13b15SJyri Sarha return ERR_PTR(-EINVAL); 311e8e13b15SJyri Sarha 3128bb0daffSRob Clark omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); 313fffddfd6SLinus Torvalds if (!omap_plane) 314fb9a35f8SLaurent Pinchart return ERR_PTR(-ENOMEM); 3158bb0daffSRob Clark 316*c8fa1e73SBenoit Parrot omap_plane->id = idx; 317*c8fa1e73SBenoit Parrot omap_plane->overlay = priv->overlays[idx]; 318*c8fa1e73SBenoit Parrot 319*c8fa1e73SBenoit Parrot DBG("%d: type=%d", omap_plane->id, type); 320*c8fa1e73SBenoit Parrot DBG(" crtc_mask: 0x%04x", possible_crtcs); 321*c8fa1e73SBenoit Parrot 322*c8fa1e73SBenoit Parrot formats = dispc_ovl_get_color_modes(priv->dispc, omap_plane->overlay->id); 323eecad437STomi Valkeinen for (nformats = 0; formats[nformats]; ++nformats) 324eecad437STomi Valkeinen ; 3258bb0daffSRob Clark 3268bb0daffSRob Clark plane = &omap_plane->base; 3278bb0daffSRob Clark 328e43f2c33STomi Valkeinen ret = drm_universal_plane_init(dev, plane, possible_crtcs, 329eecad437STomi Valkeinen &omap_plane_funcs, formats, 330e6fc3b68SBen Widawsky nformats, NULL, type, NULL); 331ef6b0e02SLaurent Pinchart if (ret < 0) 332ef6b0e02SLaurent Pinchart goto error; 3338bb0daffSRob Clark 334de8e4100SLaurent Pinchart drm_plane_helper_add(plane, &omap_plane_helper_funcs); 335de8e4100SLaurent Pinchart 3368bb0daffSRob Clark omap_plane_install_properties(plane, &plane->base); 337dff6c246SLaurent Pinchart drm_plane_create_zpos_property(plane, 0, 0, num_planes - 1); 3383037e0c5SJean-Jacques Hiblot drm_plane_create_alpha_property(plane); 3393037e0c5SJean-Jacques Hiblot drm_plane_create_blend_mode_property(plane, BIT(DRM_MODE_BLEND_PREMULTI) | 3403037e0c5SJean-Jacques Hiblot BIT(DRM_MODE_BLEND_COVERAGE)); 3418bb0daffSRob Clark 34264ff1891SJyri Sarha if (omap_plane_supports_yuv(plane)) 34364ff1891SJyri Sarha drm_plane_create_color_properties(plane, 34464ff1891SJyri Sarha BIT(DRM_COLOR_YCBCR_BT601) | 34564ff1891SJyri Sarha BIT(DRM_COLOR_YCBCR_BT709), 34664ff1891SJyri Sarha BIT(DRM_COLOR_YCBCR_FULL_RANGE) | 34764ff1891SJyri Sarha BIT(DRM_COLOR_YCBCR_LIMITED_RANGE), 34864ff1891SJyri Sarha DRM_COLOR_YCBCR_BT601, 34964ff1891SJyri Sarha DRM_COLOR_YCBCR_FULL_RANGE); 35064ff1891SJyri Sarha 3518bb0daffSRob Clark return plane; 352ef6b0e02SLaurent Pinchart 353ef6b0e02SLaurent Pinchart error: 354*c8fa1e73SBenoit Parrot dev_err(dev->dev, "%s(): could not create plane: %d\n", 355*c8fa1e73SBenoit Parrot __func__, omap_plane->id); 356e8e13b15SJyri Sarha 357ef6b0e02SLaurent Pinchart kfree(omap_plane); 358ef6b0e02SLaurent Pinchart return NULL; 3598bb0daffSRob Clark } 360