1dc5698e8SDave Airlie /* 2dc5698e8SDave Airlie * Copyright (C) 2015 Red Hat, Inc. 3dc5698e8SDave Airlie * All Rights Reserved. 4dc5698e8SDave Airlie * 5dc5698e8SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining 6dc5698e8SDave Airlie * a copy of this software and associated documentation files (the 7dc5698e8SDave Airlie * "Software"), to deal in the Software without restriction, including 8dc5698e8SDave Airlie * without limitation the rights to use, copy, modify, merge, publish, 9dc5698e8SDave Airlie * distribute, sublicense, and/or sell copies of the Software, and to 10dc5698e8SDave Airlie * permit persons to whom the Software is furnished to do so, subject to 11dc5698e8SDave Airlie * the following conditions: 12dc5698e8SDave Airlie * 13dc5698e8SDave Airlie * The above copyright notice and this permission notice (including the 14dc5698e8SDave Airlie * next paragraph) shall be included in all copies or substantial 15dc5698e8SDave Airlie * portions of the Software. 16dc5698e8SDave Airlie * 17dc5698e8SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18dc5698e8SDave Airlie * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19dc5698e8SDave Airlie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20dc5698e8SDave Airlie * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21dc5698e8SDave Airlie * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22dc5698e8SDave Airlie * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23dc5698e8SDave Airlie * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24dc5698e8SDave Airlie */ 25dc5698e8SDave Airlie 26dc5698e8SDave Airlie #include <drm/drm_atomic_helper.h> 27c0967617SGerd Hoffmann #include <drm/drm_damage_helper.h> 28a3d63977SSam Ravnborg #include <drm/drm_fourcc.h> 29a3d63977SSam Ravnborg #include <drm/drm_plane_helper.h> 30a3d63977SSam Ravnborg 31a3d63977SSam Ravnborg #include "virtgpu_drv.h" 32dc5698e8SDave Airlie 33dc5698e8SDave Airlie static const uint32_t virtio_gpu_formats[] = { 3442fd9e6cSGerd Hoffmann DRM_FORMAT_HOST_XRGB8888, 35dc5698e8SDave Airlie }; 36dc5698e8SDave Airlie 37bbbed888SGerd Hoffmann static const uint32_t virtio_gpu_cursor_formats[] = { 3842fd9e6cSGerd Hoffmann DRM_FORMAT_HOST_ARGB8888, 39bbbed888SGerd Hoffmann }; 40bbbed888SGerd Hoffmann 41d519cb76SGerd Hoffmann uint32_t virtio_gpu_translate_format(uint32_t drm_fourcc) 42d519cb76SGerd Hoffmann { 43d519cb76SGerd Hoffmann uint32_t format; 44d519cb76SGerd Hoffmann 45d519cb76SGerd Hoffmann switch (drm_fourcc) { 46d519cb76SGerd Hoffmann case DRM_FORMAT_XRGB8888: 47d519cb76SGerd Hoffmann format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; 48d519cb76SGerd Hoffmann break; 49d519cb76SGerd Hoffmann case DRM_FORMAT_ARGB8888: 50d519cb76SGerd Hoffmann format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM; 51d519cb76SGerd Hoffmann break; 52d519cb76SGerd Hoffmann case DRM_FORMAT_BGRX8888: 53d519cb76SGerd Hoffmann format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM; 54d519cb76SGerd Hoffmann break; 55d519cb76SGerd Hoffmann case DRM_FORMAT_BGRA8888: 56d519cb76SGerd Hoffmann format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM; 57d519cb76SGerd Hoffmann break; 58d519cb76SGerd Hoffmann default: 59d519cb76SGerd Hoffmann /* 60d519cb76SGerd Hoffmann * This should not happen, we handle everything listed 61d519cb76SGerd Hoffmann * in virtio_gpu_formats[]. 62d519cb76SGerd Hoffmann */ 63d519cb76SGerd Hoffmann format = 0; 64d519cb76SGerd Hoffmann break; 65d519cb76SGerd Hoffmann } 66d519cb76SGerd Hoffmann WARN_ON(format == 0); 67d519cb76SGerd Hoffmann return format; 68d519cb76SGerd Hoffmann } 69d519cb76SGerd Hoffmann 70dc5698e8SDave Airlie static void virtio_gpu_plane_destroy(struct drm_plane *plane) 71dc5698e8SDave Airlie { 72fb70046cSGustavo Padovan drm_plane_cleanup(plane); 73dc5698e8SDave Airlie kfree(plane); 74dc5698e8SDave Airlie } 75dc5698e8SDave Airlie 76dc5698e8SDave Airlie static const struct drm_plane_funcs virtio_gpu_plane_funcs = { 77dc5698e8SDave Airlie .update_plane = drm_atomic_helper_update_plane, 78dc5698e8SDave Airlie .disable_plane = drm_atomic_helper_disable_plane, 79dc5698e8SDave Airlie .destroy = virtio_gpu_plane_destroy, 80dc5698e8SDave Airlie .reset = drm_atomic_helper_plane_reset, 81dc5698e8SDave Airlie .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 82dc5698e8SDave Airlie .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 83dc5698e8SDave Airlie }; 84dc5698e8SDave Airlie 85dc5698e8SDave Airlie static int virtio_gpu_plane_atomic_check(struct drm_plane *plane, 867c11b99aSMaxime Ripard struct drm_atomic_state *state) 87dc5698e8SDave Airlie { 887c11b99aSMaxime Ripard struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 897c11b99aSMaxime Ripard plane); 90a02c4c25SGerd Hoffmann bool is_cursor = plane->type == DRM_PLANE_TYPE_CURSOR; 91a02c4c25SGerd Hoffmann struct drm_crtc_state *crtc_state; 92a02c4c25SGerd Hoffmann int ret; 93a02c4c25SGerd Hoffmann 94ba5c1649SMaxime Ripard if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc)) 95dc5698e8SDave Airlie return 0; 96a02c4c25SGerd Hoffmann 97dec92020SMaxime Ripard crtc_state = drm_atomic_get_crtc_state(state, 98ba5c1649SMaxime Ripard new_plane_state->crtc); 99a02c4c25SGerd Hoffmann if (IS_ERR(crtc_state)) 100a02c4c25SGerd Hoffmann return PTR_ERR(crtc_state); 101a02c4c25SGerd Hoffmann 102ba5c1649SMaxime Ripard ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 103a02c4c25SGerd Hoffmann DRM_PLANE_HELPER_NO_SCALING, 104a02c4c25SGerd Hoffmann DRM_PLANE_HELPER_NO_SCALING, 105a02c4c25SGerd Hoffmann is_cursor, true); 106a02c4c25SGerd Hoffmann return ret; 107dc5698e8SDave Airlie } 108dc5698e8SDave Airlie 109544c521dSGerd Hoffmann static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev, 110c0967617SGerd Hoffmann struct drm_plane_state *state, 111c0967617SGerd Hoffmann struct drm_rect *rect) 112544c521dSGerd Hoffmann { 113c0967617SGerd Hoffmann struct virtio_gpu_object *bo = 114c0967617SGerd Hoffmann gem_to_virtio_gpu_obj(state->fb->obj[0]); 115544c521dSGerd Hoffmann struct virtio_gpu_object_array *objs; 116c0967617SGerd Hoffmann uint32_t w = rect->x2 - rect->x1; 117c0967617SGerd Hoffmann uint32_t h = rect->y2 - rect->y1; 118c0967617SGerd Hoffmann uint32_t x = rect->x1; 119c0967617SGerd Hoffmann uint32_t y = rect->y1; 120c0967617SGerd Hoffmann uint32_t off = x * state->fb->format->cpp[0] + 121c0967617SGerd Hoffmann y * state->fb->pitches[0]; 122544c521dSGerd Hoffmann 123544c521dSGerd Hoffmann objs = virtio_gpu_array_alloc(1); 124544c521dSGerd Hoffmann if (!objs) 125544c521dSGerd Hoffmann return; 126544c521dSGerd Hoffmann virtio_gpu_array_add_obj(objs, &bo->base.base); 127c0967617SGerd Hoffmann 128c0967617SGerd Hoffmann virtio_gpu_cmd_transfer_to_host_2d(vgdev, off, w, h, x, y, 129544c521dSGerd Hoffmann objs, NULL); 130544c521dSGerd Hoffmann } 131544c521dSGerd Hoffmann 132bbbed888SGerd Hoffmann static void virtio_gpu_primary_plane_update(struct drm_plane *plane, 133*977697e2SMaxime Ripard struct drm_atomic_state *state) 134dc5698e8SDave Airlie { 135*977697e2SMaxime Ripard struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 136*977697e2SMaxime Ripard plane); 137dc5698e8SDave Airlie struct drm_device *dev = plane->dev; 138dc5698e8SDave Airlie struct virtio_gpu_device *vgdev = dev->dev_private; 139d3767d49SGerd Hoffmann struct virtio_gpu_output *output = NULL; 140dc5698e8SDave Airlie struct virtio_gpu_object *bo; 141c0967617SGerd Hoffmann struct drm_rect rect; 142dc5698e8SDave Airlie 143d3767d49SGerd Hoffmann if (plane->state->crtc) 144d3767d49SGerd Hoffmann output = drm_crtc_to_virtio_gpu_output(plane->state->crtc); 145d3767d49SGerd Hoffmann if (old_state->crtc) 146d3767d49SGerd Hoffmann output = drm_crtc_to_virtio_gpu_output(old_state->crtc); 147b28c69ddSHeinrich Schuchardt if (WARN_ON(!output)) 148b28c69ddSHeinrich Schuchardt return; 149d3767d49SGerd Hoffmann 1501174c8a0SGerd Hoffmann if (!plane->state->fb || !output->crtc.state->active) { 15164440ef6SGerd Hoffmann DRM_DEBUG("nofb\n"); 15264440ef6SGerd Hoffmann virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 15364440ef6SGerd Hoffmann plane->state->src_w >> 16, 15464440ef6SGerd Hoffmann plane->state->src_h >> 16, 15564440ef6SGerd Hoffmann 0, 0); 156790bcd79SGerd Hoffmann virtio_gpu_notify(vgdev); 15764440ef6SGerd Hoffmann return; 15864440ef6SGerd Hoffmann } 15964440ef6SGerd Hoffmann 160c0967617SGerd Hoffmann if (!drm_atomic_helper_damage_merged(old_state, plane->state, &rect)) 161c0967617SGerd Hoffmann return; 162c0967617SGerd Hoffmann 163c0967617SGerd Hoffmann bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]); 164544c521dSGerd Hoffmann if (bo->dumb) 165c0967617SGerd Hoffmann virtio_gpu_update_dumb_bo(vgdev, plane->state, &rect); 166dc5698e8SDave Airlie 1673954ff10SGerd Hoffmann if (plane->state->fb != old_state->fb || 1683954ff10SGerd Hoffmann plane->state->src_w != old_state->src_w || 1693954ff10SGerd Hoffmann plane->state->src_h != old_state->src_h || 1703954ff10SGerd Hoffmann plane->state->src_x != old_state->src_x || 1711bc371cdSGerd Hoffmann plane->state->src_y != old_state->src_y || 1721bc371cdSGerd Hoffmann output->needs_modeset) { 1731bc371cdSGerd Hoffmann output->needs_modeset = false; 17464440ef6SGerd Hoffmann DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", 17564440ef6SGerd Hoffmann bo->hw_res_handle, 176dc5698e8SDave Airlie plane->state->crtc_w, plane->state->crtc_h, 1770062795eSGerd Hoffmann plane->state->crtc_x, plane->state->crtc_y, 1780062795eSGerd Hoffmann plane->state->src_w >> 16, 1790062795eSGerd Hoffmann plane->state->src_h >> 16, 1800062795eSGerd Hoffmann plane->state->src_x >> 16, 1810062795eSGerd Hoffmann plane->state->src_y >> 16); 1820b0f1afeSGurchetan Singh 1830b0f1afeSGurchetan Singh if (bo->host3d_blob || bo->guest_blob) { 1840b0f1afeSGurchetan Singh virtio_gpu_cmd_set_scanout_blob 1850b0f1afeSGurchetan Singh (vgdev, output->index, bo, 1860b0f1afeSGurchetan Singh plane->state->fb, 1870b0f1afeSGurchetan Singh plane->state->src_w >> 16, 1880b0f1afeSGurchetan Singh plane->state->src_h >> 16, 1890b0f1afeSGurchetan Singh plane->state->src_x >> 16, 1900b0f1afeSGurchetan Singh plane->state->src_y >> 16); 1910b0f1afeSGurchetan Singh } else { 19264440ef6SGerd Hoffmann virtio_gpu_cmd_set_scanout(vgdev, output->index, 19364440ef6SGerd Hoffmann bo->hw_res_handle, 1940062795eSGerd Hoffmann plane->state->src_w >> 16, 1950062795eSGerd Hoffmann plane->state->src_h >> 16, 1960062795eSGerd Hoffmann plane->state->src_x >> 16, 1970062795eSGerd Hoffmann plane->state->src_y >> 16); 1983954ff10SGerd Hoffmann } 1990b0f1afeSGurchetan Singh } 2003954ff10SGerd Hoffmann 20164440ef6SGerd Hoffmann virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, 202c0967617SGerd Hoffmann rect.x1, 203c0967617SGerd Hoffmann rect.y1, 204c0967617SGerd Hoffmann rect.x2 - rect.x1, 205c0967617SGerd Hoffmann rect.y2 - rect.y1); 206790bcd79SGerd Hoffmann virtio_gpu_notify(vgdev); 207dc5698e8SDave Airlie } 208dc5698e8SDave Airlie 2099fdd90c0SRobert Foss static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane, 2109fdd90c0SRobert Foss struct drm_plane_state *new_state) 2119fdd90c0SRobert Foss { 2129fdd90c0SRobert Foss struct drm_device *dev = plane->dev; 2139fdd90c0SRobert Foss struct virtio_gpu_device *vgdev = dev->dev_private; 2149fdd90c0SRobert Foss struct virtio_gpu_framebuffer *vgfb; 2159fdd90c0SRobert Foss struct virtio_gpu_object *bo; 2169fdd90c0SRobert Foss 2179fdd90c0SRobert Foss if (!new_state->fb) 2189fdd90c0SRobert Foss return 0; 2199fdd90c0SRobert Foss 2209fdd90c0SRobert Foss vgfb = to_virtio_gpu_framebuffer(new_state->fb); 2219fdd90c0SRobert Foss bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); 2229fdd90c0SRobert Foss if (bo && bo->dumb && (plane->state->fb != new_state->fb)) { 2239fdd90c0SRobert Foss vgfb->fence = virtio_gpu_fence_alloc(vgdev); 2249fdd90c0SRobert Foss if (!vgfb->fence) 2259fdd90c0SRobert Foss return -ENOMEM; 2269fdd90c0SRobert Foss } 2279fdd90c0SRobert Foss 2289fdd90c0SRobert Foss return 0; 2299fdd90c0SRobert Foss } 2309fdd90c0SRobert Foss 2319fdd90c0SRobert Foss static void virtio_gpu_cursor_cleanup_fb(struct drm_plane *plane, 2329fdd90c0SRobert Foss struct drm_plane_state *old_state) 2339fdd90c0SRobert Foss { 2349fdd90c0SRobert Foss struct virtio_gpu_framebuffer *vgfb; 2359fdd90c0SRobert Foss 2369fdd90c0SRobert Foss if (!plane->state->fb) 2379fdd90c0SRobert Foss return; 2389fdd90c0SRobert Foss 2399fdd90c0SRobert Foss vgfb = to_virtio_gpu_framebuffer(plane->state->fb); 240cb66c6daSGerd Hoffmann if (vgfb->fence) { 241cb66c6daSGerd Hoffmann dma_fence_put(&vgfb->fence->f); 242cb66c6daSGerd Hoffmann vgfb->fence = NULL; 243cb66c6daSGerd Hoffmann } 2449fdd90c0SRobert Foss } 2459fdd90c0SRobert Foss 246bbbed888SGerd Hoffmann static void virtio_gpu_cursor_plane_update(struct drm_plane *plane, 247*977697e2SMaxime Ripard struct drm_atomic_state *state) 248bbbed888SGerd Hoffmann { 249*977697e2SMaxime Ripard struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 250*977697e2SMaxime Ripard plane); 251bbbed888SGerd Hoffmann struct drm_device *dev = plane->dev; 252bbbed888SGerd Hoffmann struct virtio_gpu_device *vgdev = dev->dev_private; 253bbbed888SGerd Hoffmann struct virtio_gpu_output *output = NULL; 254bbbed888SGerd Hoffmann struct virtio_gpu_framebuffer *vgfb; 255bbbed888SGerd Hoffmann struct virtio_gpu_object *bo = NULL; 256bbbed888SGerd Hoffmann uint32_t handle; 257dc5698e8SDave Airlie 258bbbed888SGerd Hoffmann if (plane->state->crtc) 259bbbed888SGerd Hoffmann output = drm_crtc_to_virtio_gpu_output(plane->state->crtc); 260bbbed888SGerd Hoffmann if (old_state->crtc) 261bbbed888SGerd Hoffmann output = drm_crtc_to_virtio_gpu_output(old_state->crtc); 262b28c69ddSHeinrich Schuchardt if (WARN_ON(!output)) 263b28c69ddSHeinrich Schuchardt return; 264bbbed888SGerd Hoffmann 265bbbed888SGerd Hoffmann if (plane->state->fb) { 266bbbed888SGerd Hoffmann vgfb = to_virtio_gpu_framebuffer(plane->state->fb); 2673823da3aSDaniel Stone bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); 268bbbed888SGerd Hoffmann handle = bo->hw_res_handle; 269bbbed888SGerd Hoffmann } else { 270bbbed888SGerd Hoffmann handle = 0; 271bbbed888SGerd Hoffmann } 272bbbed888SGerd Hoffmann 273bbbed888SGerd Hoffmann if (bo && bo->dumb && (plane->state->fb != old_state->fb)) { 274bbbed888SGerd Hoffmann /* new cursor -- update & wait */ 2753d3bdbc0SGerd Hoffmann struct virtio_gpu_object_array *objs; 2763d3bdbc0SGerd Hoffmann 2773d3bdbc0SGerd Hoffmann objs = virtio_gpu_array_alloc(1); 2783d3bdbc0SGerd Hoffmann if (!objs) 2793d3bdbc0SGerd Hoffmann return; 2803d3bdbc0SGerd Hoffmann virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]); 2815cfd31c5SGerd Hoffmann virtio_gpu_array_lock_resv(objs); 282bbbed888SGerd Hoffmann virtio_gpu_cmd_transfer_to_host_2d 2833d3bdbc0SGerd Hoffmann (vgdev, 0, 28464f1cc99SGerd Hoffmann plane->state->crtc_w, 28564f1cc99SGerd Hoffmann plane->state->crtc_h, 2863d3bdbc0SGerd Hoffmann 0, 0, objs, vgfb->fence); 287790bcd79SGerd Hoffmann virtio_gpu_notify(vgdev); 288620f9c5eSGerd Hoffmann dma_fence_wait(&vgfb->fence->f, true); 2899fdd90c0SRobert Foss dma_fence_put(&vgfb->fence->f); 2909fdd90c0SRobert Foss vgfb->fence = NULL; 291bbbed888SGerd Hoffmann } 292bbbed888SGerd Hoffmann 293bbbed888SGerd Hoffmann if (plane->state->fb != old_state->fb) { 29486f752d2SGerd Hoffmann DRM_DEBUG("update, handle %d, pos +%d+%d, hot %d,%d\n", handle, 295bbbed888SGerd Hoffmann plane->state->crtc_x, 29686f752d2SGerd Hoffmann plane->state->crtc_y, 29786f752d2SGerd Hoffmann plane->state->fb ? plane->state->fb->hot_x : 0, 29886f752d2SGerd Hoffmann plane->state->fb ? plane->state->fb->hot_y : 0); 299bbbed888SGerd Hoffmann output->cursor.hdr.type = 300bbbed888SGerd Hoffmann cpu_to_le32(VIRTIO_GPU_CMD_UPDATE_CURSOR); 301bbbed888SGerd Hoffmann output->cursor.resource_id = cpu_to_le32(handle); 30286f752d2SGerd Hoffmann if (plane->state->fb) { 30386f752d2SGerd Hoffmann output->cursor.hot_x = 30486f752d2SGerd Hoffmann cpu_to_le32(plane->state->fb->hot_x); 30586f752d2SGerd Hoffmann output->cursor.hot_y = 30686f752d2SGerd Hoffmann cpu_to_le32(plane->state->fb->hot_y); 30786f752d2SGerd Hoffmann } else { 30886f752d2SGerd Hoffmann output->cursor.hot_x = cpu_to_le32(0); 30986f752d2SGerd Hoffmann output->cursor.hot_y = cpu_to_le32(0); 31086f752d2SGerd Hoffmann } 311bbbed888SGerd Hoffmann } else { 312bbbed888SGerd Hoffmann DRM_DEBUG("move +%d+%d\n", 313bbbed888SGerd Hoffmann plane->state->crtc_x, 314bbbed888SGerd Hoffmann plane->state->crtc_y); 315bbbed888SGerd Hoffmann output->cursor.hdr.type = 316bbbed888SGerd Hoffmann cpu_to_le32(VIRTIO_GPU_CMD_MOVE_CURSOR); 317bbbed888SGerd Hoffmann } 318bbbed888SGerd Hoffmann output->cursor.pos.x = cpu_to_le32(plane->state->crtc_x); 319bbbed888SGerd Hoffmann output->cursor.pos.y = cpu_to_le32(plane->state->crtc_y); 320bbbed888SGerd Hoffmann virtio_gpu_cursor_ping(vgdev, output); 321bbbed888SGerd Hoffmann } 322bbbed888SGerd Hoffmann 323bbbed888SGerd Hoffmann static const struct drm_plane_helper_funcs virtio_gpu_primary_helper_funcs = { 324dc5698e8SDave Airlie .atomic_check = virtio_gpu_plane_atomic_check, 325bbbed888SGerd Hoffmann .atomic_update = virtio_gpu_primary_plane_update, 326bbbed888SGerd Hoffmann }; 327bbbed888SGerd Hoffmann 328bbbed888SGerd Hoffmann static const struct drm_plane_helper_funcs virtio_gpu_cursor_helper_funcs = { 3299fdd90c0SRobert Foss .prepare_fb = virtio_gpu_cursor_prepare_fb, 3309fdd90c0SRobert Foss .cleanup_fb = virtio_gpu_cursor_cleanup_fb, 331bbbed888SGerd Hoffmann .atomic_check = virtio_gpu_plane_atomic_check, 332bbbed888SGerd Hoffmann .atomic_update = virtio_gpu_cursor_plane_update, 333dc5698e8SDave Airlie }; 334dc5698e8SDave Airlie 335dc5698e8SDave Airlie struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev, 336bbbed888SGerd Hoffmann enum drm_plane_type type, 337dc5698e8SDave Airlie int index) 338dc5698e8SDave Airlie { 339dc5698e8SDave Airlie struct drm_device *dev = vgdev->ddev; 340bbbed888SGerd Hoffmann const struct drm_plane_helper_funcs *funcs; 341dc5698e8SDave Airlie struct drm_plane *plane; 342bbbed888SGerd Hoffmann const uint32_t *formats; 343bbbed888SGerd Hoffmann int ret, nformats; 344dc5698e8SDave Airlie 345dc5698e8SDave Airlie plane = kzalloc(sizeof(*plane), GFP_KERNEL); 346dc5698e8SDave Airlie if (!plane) 347dc5698e8SDave Airlie return ERR_PTR(-ENOMEM); 348dc5698e8SDave Airlie 349bbbed888SGerd Hoffmann if (type == DRM_PLANE_TYPE_CURSOR) { 350bbbed888SGerd Hoffmann formats = virtio_gpu_cursor_formats; 351bbbed888SGerd Hoffmann nformats = ARRAY_SIZE(virtio_gpu_cursor_formats); 352bbbed888SGerd Hoffmann funcs = &virtio_gpu_cursor_helper_funcs; 353bbbed888SGerd Hoffmann } else { 354bbbed888SGerd Hoffmann formats = virtio_gpu_formats; 355bbbed888SGerd Hoffmann nformats = ARRAY_SIZE(virtio_gpu_formats); 356bbbed888SGerd Hoffmann funcs = &virtio_gpu_primary_helper_funcs; 357bbbed888SGerd Hoffmann } 358dc5698e8SDave Airlie ret = drm_universal_plane_init(dev, plane, 1 << index, 359dc5698e8SDave Airlie &virtio_gpu_plane_funcs, 360bbbed888SGerd Hoffmann formats, nformats, 361e6fc3b68SBen Widawsky NULL, type, NULL); 362dc5698e8SDave Airlie if (ret) 363dc5698e8SDave Airlie goto err_plane_init; 364dc5698e8SDave Airlie 365bbbed888SGerd Hoffmann drm_plane_helper_add(plane, funcs); 366dc5698e8SDave Airlie return plane; 367dc5698e8SDave Airlie 368dc5698e8SDave Airlie err_plane_init: 369dc5698e8SDave Airlie kfree(plane); 370dc5698e8SDave Airlie return ERR_PTR(ret); 371dc5698e8SDave Airlie } 372