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 30a3d63977SSam Ravnborg #include "virtgpu_drv.h" 31dc5698e8SDave Airlie 32dc5698e8SDave Airlie static const uint32_t virtio_gpu_formats[] = { 3342fd9e6cSGerd Hoffmann DRM_FORMAT_HOST_XRGB8888, 34dc5698e8SDave Airlie }; 35dc5698e8SDave Airlie 36bbbed888SGerd Hoffmann static const uint32_t virtio_gpu_cursor_formats[] = { 3742fd9e6cSGerd Hoffmann DRM_FORMAT_HOST_ARGB8888, 38bbbed888SGerd Hoffmann }; 39bbbed888SGerd Hoffmann 40d519cb76SGerd Hoffmann uint32_t virtio_gpu_translate_format(uint32_t drm_fourcc) 41d519cb76SGerd Hoffmann { 42d519cb76SGerd Hoffmann uint32_t format; 43d519cb76SGerd Hoffmann 44d519cb76SGerd Hoffmann switch (drm_fourcc) { 45d519cb76SGerd Hoffmann case DRM_FORMAT_XRGB8888: 46d519cb76SGerd Hoffmann format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; 47d519cb76SGerd Hoffmann break; 48d519cb76SGerd Hoffmann case DRM_FORMAT_ARGB8888: 49d519cb76SGerd Hoffmann format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM; 50d519cb76SGerd Hoffmann break; 51d519cb76SGerd Hoffmann case DRM_FORMAT_BGRX8888: 52d519cb76SGerd Hoffmann format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM; 53d519cb76SGerd Hoffmann break; 54d519cb76SGerd Hoffmann case DRM_FORMAT_BGRA8888: 55d519cb76SGerd Hoffmann format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM; 56d519cb76SGerd Hoffmann break; 57d519cb76SGerd Hoffmann default: 58d519cb76SGerd Hoffmann /* 59d519cb76SGerd Hoffmann * This should not happen, we handle everything listed 60d519cb76SGerd Hoffmann * in virtio_gpu_formats[]. 61d519cb76SGerd Hoffmann */ 62d519cb76SGerd Hoffmann format = 0; 63d519cb76SGerd Hoffmann break; 64d519cb76SGerd Hoffmann } 65d519cb76SGerd Hoffmann WARN_ON(format == 0); 66d519cb76SGerd Hoffmann return format; 67d519cb76SGerd Hoffmann } 68d519cb76SGerd Hoffmann 69dc5698e8SDave Airlie static const struct drm_plane_funcs virtio_gpu_plane_funcs = { 70dc5698e8SDave Airlie .update_plane = drm_atomic_helper_update_plane, 71dc5698e8SDave Airlie .disable_plane = drm_atomic_helper_disable_plane, 7278476288SDanilo Krummrich .destroy = drm_plane_cleanup, 73dc5698e8SDave Airlie .reset = drm_atomic_helper_plane_reset, 74dc5698e8SDave Airlie .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 75dc5698e8SDave Airlie .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 76dc5698e8SDave Airlie }; 77dc5698e8SDave Airlie 78dc5698e8SDave Airlie static int virtio_gpu_plane_atomic_check(struct drm_plane *plane, 797c11b99aSMaxime Ripard struct drm_atomic_state *state) 80dc5698e8SDave Airlie { 817c11b99aSMaxime Ripard struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 827c11b99aSMaxime Ripard plane); 83a02c4c25SGerd Hoffmann bool is_cursor = plane->type == DRM_PLANE_TYPE_CURSOR; 84a02c4c25SGerd Hoffmann struct drm_crtc_state *crtc_state; 85a02c4c25SGerd Hoffmann int ret; 86a02c4c25SGerd Hoffmann 87ba5c1649SMaxime Ripard if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc)) 88dc5698e8SDave Airlie return 0; 89a02c4c25SGerd Hoffmann 90dec92020SMaxime Ripard crtc_state = drm_atomic_get_crtc_state(state, 91ba5c1649SMaxime Ripard new_plane_state->crtc); 92a02c4c25SGerd Hoffmann if (IS_ERR(crtc_state)) 93a02c4c25SGerd Hoffmann return PTR_ERR(crtc_state); 94a02c4c25SGerd Hoffmann 95ba5c1649SMaxime Ripard ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 96*cce32e4eSThomas Zimmermann DRM_PLANE_NO_SCALING, 97*cce32e4eSThomas Zimmermann DRM_PLANE_NO_SCALING, 98a02c4c25SGerd Hoffmann is_cursor, true); 99a02c4c25SGerd Hoffmann return ret; 100dc5698e8SDave Airlie } 101dc5698e8SDave Airlie 102544c521dSGerd Hoffmann static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev, 103c0967617SGerd Hoffmann struct drm_plane_state *state, 104c0967617SGerd Hoffmann struct drm_rect *rect) 105544c521dSGerd Hoffmann { 106c0967617SGerd Hoffmann struct virtio_gpu_object *bo = 107c0967617SGerd Hoffmann gem_to_virtio_gpu_obj(state->fb->obj[0]); 108544c521dSGerd Hoffmann struct virtio_gpu_object_array *objs; 109c0967617SGerd Hoffmann uint32_t w = rect->x2 - rect->x1; 110c0967617SGerd Hoffmann uint32_t h = rect->y2 - rect->y1; 111c0967617SGerd Hoffmann uint32_t x = rect->x1; 112c0967617SGerd Hoffmann uint32_t y = rect->y1; 113c0967617SGerd Hoffmann uint32_t off = x * state->fb->format->cpp[0] + 114c0967617SGerd Hoffmann y * state->fb->pitches[0]; 115544c521dSGerd Hoffmann 116544c521dSGerd Hoffmann objs = virtio_gpu_array_alloc(1); 117544c521dSGerd Hoffmann if (!objs) 118544c521dSGerd Hoffmann return; 119544c521dSGerd Hoffmann virtio_gpu_array_add_obj(objs, &bo->base.base); 120c0967617SGerd Hoffmann 121c0967617SGerd Hoffmann virtio_gpu_cmd_transfer_to_host_2d(vgdev, off, w, h, x, y, 122544c521dSGerd Hoffmann objs, NULL); 123544c521dSGerd Hoffmann } 124544c521dSGerd Hoffmann 1255c68ab92SVivek Kasireddy static void virtio_gpu_resource_flush(struct drm_plane *plane, 1265c68ab92SVivek Kasireddy uint32_t x, uint32_t y, 1275c68ab92SVivek Kasireddy uint32_t width, uint32_t height) 1285c68ab92SVivek Kasireddy { 1295c68ab92SVivek Kasireddy struct drm_device *dev = plane->dev; 1305c68ab92SVivek Kasireddy struct virtio_gpu_device *vgdev = dev->dev_private; 1315c68ab92SVivek Kasireddy struct virtio_gpu_framebuffer *vgfb; 1325c68ab92SVivek Kasireddy struct virtio_gpu_object *bo; 1335c68ab92SVivek Kasireddy 1345c68ab92SVivek Kasireddy vgfb = to_virtio_gpu_framebuffer(plane->state->fb); 1355c68ab92SVivek Kasireddy bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); 1365c68ab92SVivek Kasireddy if (vgfb->fence) { 1375c68ab92SVivek Kasireddy struct virtio_gpu_object_array *objs; 1385c68ab92SVivek Kasireddy 1395c68ab92SVivek Kasireddy objs = virtio_gpu_array_alloc(1); 1405c68ab92SVivek Kasireddy if (!objs) 1415c68ab92SVivek Kasireddy return; 1425c68ab92SVivek Kasireddy virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]); 1435c68ab92SVivek Kasireddy virtio_gpu_array_lock_resv(objs); 1445c68ab92SVivek Kasireddy virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, x, y, 1455c68ab92SVivek Kasireddy width, height, objs, vgfb->fence); 1465c68ab92SVivek Kasireddy virtio_gpu_notify(vgdev); 1475c68ab92SVivek Kasireddy 1485c68ab92SVivek Kasireddy dma_fence_wait_timeout(&vgfb->fence->f, true, 1495c68ab92SVivek Kasireddy msecs_to_jiffies(50)); 1505c68ab92SVivek Kasireddy dma_fence_put(&vgfb->fence->f); 1515c68ab92SVivek Kasireddy vgfb->fence = NULL; 1525c68ab92SVivek Kasireddy } else { 1535c68ab92SVivek Kasireddy virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, x, y, 1545c68ab92SVivek Kasireddy width, height, NULL, NULL); 1555c68ab92SVivek Kasireddy virtio_gpu_notify(vgdev); 1565c68ab92SVivek Kasireddy } 1575c68ab92SVivek Kasireddy } 1585c68ab92SVivek Kasireddy 159bbbed888SGerd Hoffmann static void virtio_gpu_primary_plane_update(struct drm_plane *plane, 160977697e2SMaxime Ripard struct drm_atomic_state *state) 161dc5698e8SDave Airlie { 162977697e2SMaxime Ripard struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 163977697e2SMaxime Ripard plane); 164dc5698e8SDave Airlie struct drm_device *dev = plane->dev; 165dc5698e8SDave Airlie struct virtio_gpu_device *vgdev = dev->dev_private; 166d3767d49SGerd Hoffmann struct virtio_gpu_output *output = NULL; 167dc5698e8SDave Airlie struct virtio_gpu_object *bo; 168c0967617SGerd Hoffmann struct drm_rect rect; 169dc5698e8SDave Airlie 170d3767d49SGerd Hoffmann if (plane->state->crtc) 171d3767d49SGerd Hoffmann output = drm_crtc_to_virtio_gpu_output(plane->state->crtc); 172d3767d49SGerd Hoffmann if (old_state->crtc) 173d3767d49SGerd Hoffmann output = drm_crtc_to_virtio_gpu_output(old_state->crtc); 174b28c69ddSHeinrich Schuchardt if (WARN_ON(!output)) 175b28c69ddSHeinrich Schuchardt return; 176d3767d49SGerd Hoffmann 1771174c8a0SGerd Hoffmann if (!plane->state->fb || !output->crtc.state->active) { 17864440ef6SGerd Hoffmann DRM_DEBUG("nofb\n"); 17964440ef6SGerd Hoffmann virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 18064440ef6SGerd Hoffmann plane->state->src_w >> 16, 18164440ef6SGerd Hoffmann plane->state->src_h >> 16, 18264440ef6SGerd Hoffmann 0, 0); 183790bcd79SGerd Hoffmann virtio_gpu_notify(vgdev); 18464440ef6SGerd Hoffmann return; 18564440ef6SGerd Hoffmann } 18664440ef6SGerd Hoffmann 187c0967617SGerd Hoffmann if (!drm_atomic_helper_damage_merged(old_state, plane->state, &rect)) 188c0967617SGerd Hoffmann return; 189c0967617SGerd Hoffmann 190c0967617SGerd Hoffmann bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]); 191544c521dSGerd Hoffmann if (bo->dumb) 192c0967617SGerd Hoffmann virtio_gpu_update_dumb_bo(vgdev, plane->state, &rect); 193dc5698e8SDave Airlie 1943954ff10SGerd Hoffmann if (plane->state->fb != old_state->fb || 1953954ff10SGerd Hoffmann plane->state->src_w != old_state->src_w || 1963954ff10SGerd Hoffmann plane->state->src_h != old_state->src_h || 1973954ff10SGerd Hoffmann plane->state->src_x != old_state->src_x || 1981bc371cdSGerd Hoffmann plane->state->src_y != old_state->src_y || 1991bc371cdSGerd Hoffmann output->needs_modeset) { 2001bc371cdSGerd Hoffmann output->needs_modeset = false; 20164440ef6SGerd Hoffmann DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", 20264440ef6SGerd Hoffmann bo->hw_res_handle, 203dc5698e8SDave Airlie plane->state->crtc_w, plane->state->crtc_h, 2040062795eSGerd Hoffmann plane->state->crtc_x, plane->state->crtc_y, 2050062795eSGerd Hoffmann plane->state->src_w >> 16, 2060062795eSGerd Hoffmann plane->state->src_h >> 16, 2070062795eSGerd Hoffmann plane->state->src_x >> 16, 2080062795eSGerd Hoffmann plane->state->src_y >> 16); 2090b0f1afeSGurchetan Singh 2100b0f1afeSGurchetan Singh if (bo->host3d_blob || bo->guest_blob) { 2110b0f1afeSGurchetan Singh virtio_gpu_cmd_set_scanout_blob 2120b0f1afeSGurchetan Singh (vgdev, output->index, bo, 2130b0f1afeSGurchetan Singh plane->state->fb, 2140b0f1afeSGurchetan Singh plane->state->src_w >> 16, 2150b0f1afeSGurchetan Singh plane->state->src_h >> 16, 2160b0f1afeSGurchetan Singh plane->state->src_x >> 16, 2170b0f1afeSGurchetan Singh plane->state->src_y >> 16); 2180b0f1afeSGurchetan Singh } else { 21964440ef6SGerd Hoffmann virtio_gpu_cmd_set_scanout(vgdev, output->index, 22064440ef6SGerd Hoffmann bo->hw_res_handle, 2210062795eSGerd Hoffmann plane->state->src_w >> 16, 2220062795eSGerd Hoffmann plane->state->src_h >> 16, 2230062795eSGerd Hoffmann plane->state->src_x >> 16, 2240062795eSGerd Hoffmann plane->state->src_y >> 16); 2253954ff10SGerd Hoffmann } 2260b0f1afeSGurchetan Singh } 2273954ff10SGerd Hoffmann 2285c68ab92SVivek Kasireddy virtio_gpu_resource_flush(plane, 229c0967617SGerd Hoffmann rect.x1, 230c0967617SGerd Hoffmann rect.y1, 231c0967617SGerd Hoffmann rect.x2 - rect.x1, 232c0967617SGerd Hoffmann rect.y2 - rect.y1); 233dc5698e8SDave Airlie } 234dc5698e8SDave Airlie 2353a1fde58SVivek Kasireddy static int virtio_gpu_plane_prepare_fb(struct drm_plane *plane, 2369fdd90c0SRobert Foss struct drm_plane_state *new_state) 2379fdd90c0SRobert Foss { 2389fdd90c0SRobert Foss struct drm_device *dev = plane->dev; 2399fdd90c0SRobert Foss struct virtio_gpu_device *vgdev = dev->dev_private; 2409fdd90c0SRobert Foss struct virtio_gpu_framebuffer *vgfb; 2419fdd90c0SRobert Foss struct virtio_gpu_object *bo; 2429fdd90c0SRobert Foss 2439fdd90c0SRobert Foss if (!new_state->fb) 2449fdd90c0SRobert Foss return 0; 2459fdd90c0SRobert Foss 2469fdd90c0SRobert Foss vgfb = to_virtio_gpu_framebuffer(new_state->fb); 2479fdd90c0SRobert Foss bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); 2483a1fde58SVivek Kasireddy if (!bo || (plane->type == DRM_PLANE_TYPE_PRIMARY && !bo->guest_blob)) 2493a1fde58SVivek Kasireddy return 0; 2503a1fde58SVivek Kasireddy 2513a1fde58SVivek Kasireddy if (bo->dumb && (plane->state->fb != new_state->fb)) { 252e8b6e76fSGurchetan Singh vgfb->fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 253e8b6e76fSGurchetan Singh 0); 2549fdd90c0SRobert Foss if (!vgfb->fence) 2559fdd90c0SRobert Foss return -ENOMEM; 2569fdd90c0SRobert Foss } 2579fdd90c0SRobert Foss 2589fdd90c0SRobert Foss return 0; 2599fdd90c0SRobert Foss } 2609fdd90c0SRobert Foss 2613a1fde58SVivek Kasireddy static void virtio_gpu_plane_cleanup_fb(struct drm_plane *plane, 2624656b3a2SDmitry Osipenko struct drm_plane_state *state) 2639fdd90c0SRobert Foss { 2649fdd90c0SRobert Foss struct virtio_gpu_framebuffer *vgfb; 2659fdd90c0SRobert Foss 2664656b3a2SDmitry Osipenko if (!state->fb) 2679fdd90c0SRobert Foss return; 2689fdd90c0SRobert Foss 2694656b3a2SDmitry Osipenko vgfb = to_virtio_gpu_framebuffer(state->fb); 270cb66c6daSGerd Hoffmann if (vgfb->fence) { 271cb66c6daSGerd Hoffmann dma_fence_put(&vgfb->fence->f); 272cb66c6daSGerd Hoffmann vgfb->fence = NULL; 273cb66c6daSGerd Hoffmann } 2749fdd90c0SRobert Foss } 2759fdd90c0SRobert Foss 276bbbed888SGerd Hoffmann static void virtio_gpu_cursor_plane_update(struct drm_plane *plane, 277977697e2SMaxime Ripard struct drm_atomic_state *state) 278bbbed888SGerd Hoffmann { 279977697e2SMaxime Ripard struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 280977697e2SMaxime Ripard plane); 281bbbed888SGerd Hoffmann struct drm_device *dev = plane->dev; 282bbbed888SGerd Hoffmann struct virtio_gpu_device *vgdev = dev->dev_private; 283bbbed888SGerd Hoffmann struct virtio_gpu_output *output = NULL; 284bbbed888SGerd Hoffmann struct virtio_gpu_framebuffer *vgfb; 285bbbed888SGerd Hoffmann struct virtio_gpu_object *bo = NULL; 286bbbed888SGerd Hoffmann uint32_t handle; 287dc5698e8SDave Airlie 288bbbed888SGerd Hoffmann if (plane->state->crtc) 289bbbed888SGerd Hoffmann output = drm_crtc_to_virtio_gpu_output(plane->state->crtc); 290bbbed888SGerd Hoffmann if (old_state->crtc) 291bbbed888SGerd Hoffmann output = drm_crtc_to_virtio_gpu_output(old_state->crtc); 292b28c69ddSHeinrich Schuchardt if (WARN_ON(!output)) 293b28c69ddSHeinrich Schuchardt return; 294bbbed888SGerd Hoffmann 295bbbed888SGerd Hoffmann if (plane->state->fb) { 296bbbed888SGerd Hoffmann vgfb = to_virtio_gpu_framebuffer(plane->state->fb); 2973823da3aSDaniel Stone bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); 298bbbed888SGerd Hoffmann handle = bo->hw_res_handle; 299bbbed888SGerd Hoffmann } else { 300bbbed888SGerd Hoffmann handle = 0; 301bbbed888SGerd Hoffmann } 302bbbed888SGerd Hoffmann 303bbbed888SGerd Hoffmann if (bo && bo->dumb && (plane->state->fb != old_state->fb)) { 304bbbed888SGerd Hoffmann /* new cursor -- update & wait */ 3053d3bdbc0SGerd Hoffmann struct virtio_gpu_object_array *objs; 3063d3bdbc0SGerd Hoffmann 3073d3bdbc0SGerd Hoffmann objs = virtio_gpu_array_alloc(1); 3083d3bdbc0SGerd Hoffmann if (!objs) 3093d3bdbc0SGerd Hoffmann return; 3103d3bdbc0SGerd Hoffmann virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]); 3115cfd31c5SGerd Hoffmann virtio_gpu_array_lock_resv(objs); 312bbbed888SGerd Hoffmann virtio_gpu_cmd_transfer_to_host_2d 3133d3bdbc0SGerd Hoffmann (vgdev, 0, 31464f1cc99SGerd Hoffmann plane->state->crtc_w, 31564f1cc99SGerd Hoffmann plane->state->crtc_h, 3163d3bdbc0SGerd Hoffmann 0, 0, objs, vgfb->fence); 317790bcd79SGerd Hoffmann virtio_gpu_notify(vgdev); 318620f9c5eSGerd Hoffmann dma_fence_wait(&vgfb->fence->f, true); 3199fdd90c0SRobert Foss dma_fence_put(&vgfb->fence->f); 3209fdd90c0SRobert Foss vgfb->fence = NULL; 321bbbed888SGerd Hoffmann } 322bbbed888SGerd Hoffmann 323bbbed888SGerd Hoffmann if (plane->state->fb != old_state->fb) { 32486f752d2SGerd Hoffmann DRM_DEBUG("update, handle %d, pos +%d+%d, hot %d,%d\n", handle, 325bbbed888SGerd Hoffmann plane->state->crtc_x, 32686f752d2SGerd Hoffmann plane->state->crtc_y, 32786f752d2SGerd Hoffmann plane->state->fb ? plane->state->fb->hot_x : 0, 32886f752d2SGerd Hoffmann plane->state->fb ? plane->state->fb->hot_y : 0); 329bbbed888SGerd Hoffmann output->cursor.hdr.type = 330bbbed888SGerd Hoffmann cpu_to_le32(VIRTIO_GPU_CMD_UPDATE_CURSOR); 331bbbed888SGerd Hoffmann output->cursor.resource_id = cpu_to_le32(handle); 33286f752d2SGerd Hoffmann if (plane->state->fb) { 33386f752d2SGerd Hoffmann output->cursor.hot_x = 33486f752d2SGerd Hoffmann cpu_to_le32(plane->state->fb->hot_x); 33586f752d2SGerd Hoffmann output->cursor.hot_y = 33686f752d2SGerd Hoffmann cpu_to_le32(plane->state->fb->hot_y); 33786f752d2SGerd Hoffmann } else { 33886f752d2SGerd Hoffmann output->cursor.hot_x = cpu_to_le32(0); 33986f752d2SGerd Hoffmann output->cursor.hot_y = cpu_to_le32(0); 34086f752d2SGerd Hoffmann } 341bbbed888SGerd Hoffmann } else { 342bbbed888SGerd Hoffmann DRM_DEBUG("move +%d+%d\n", 343bbbed888SGerd Hoffmann plane->state->crtc_x, 344bbbed888SGerd Hoffmann plane->state->crtc_y); 345bbbed888SGerd Hoffmann output->cursor.hdr.type = 346bbbed888SGerd Hoffmann cpu_to_le32(VIRTIO_GPU_CMD_MOVE_CURSOR); 347bbbed888SGerd Hoffmann } 348bbbed888SGerd Hoffmann output->cursor.pos.x = cpu_to_le32(plane->state->crtc_x); 349bbbed888SGerd Hoffmann output->cursor.pos.y = cpu_to_le32(plane->state->crtc_y); 350bbbed888SGerd Hoffmann virtio_gpu_cursor_ping(vgdev, output); 351bbbed888SGerd Hoffmann } 352bbbed888SGerd Hoffmann 353bbbed888SGerd Hoffmann static const struct drm_plane_helper_funcs virtio_gpu_primary_helper_funcs = { 3543a1fde58SVivek Kasireddy .prepare_fb = virtio_gpu_plane_prepare_fb, 3553a1fde58SVivek Kasireddy .cleanup_fb = virtio_gpu_plane_cleanup_fb, 356dc5698e8SDave Airlie .atomic_check = virtio_gpu_plane_atomic_check, 357bbbed888SGerd Hoffmann .atomic_update = virtio_gpu_primary_plane_update, 358bbbed888SGerd Hoffmann }; 359bbbed888SGerd Hoffmann 360bbbed888SGerd Hoffmann static const struct drm_plane_helper_funcs virtio_gpu_cursor_helper_funcs = { 3613a1fde58SVivek Kasireddy .prepare_fb = virtio_gpu_plane_prepare_fb, 3623a1fde58SVivek Kasireddy .cleanup_fb = virtio_gpu_plane_cleanup_fb, 363bbbed888SGerd Hoffmann .atomic_check = virtio_gpu_plane_atomic_check, 364bbbed888SGerd Hoffmann .atomic_update = virtio_gpu_cursor_plane_update, 365dc5698e8SDave Airlie }; 366dc5698e8SDave Airlie 367dc5698e8SDave Airlie struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev, 368bbbed888SGerd Hoffmann enum drm_plane_type type, 369dc5698e8SDave Airlie int index) 370dc5698e8SDave Airlie { 371dc5698e8SDave Airlie struct drm_device *dev = vgdev->ddev; 372bbbed888SGerd Hoffmann const struct drm_plane_helper_funcs *funcs; 373dc5698e8SDave Airlie struct drm_plane *plane; 374bbbed888SGerd Hoffmann const uint32_t *formats; 37578476288SDanilo Krummrich int nformats; 376dc5698e8SDave Airlie 377bbbed888SGerd Hoffmann if (type == DRM_PLANE_TYPE_CURSOR) { 378bbbed888SGerd Hoffmann formats = virtio_gpu_cursor_formats; 379bbbed888SGerd Hoffmann nformats = ARRAY_SIZE(virtio_gpu_cursor_formats); 380bbbed888SGerd Hoffmann funcs = &virtio_gpu_cursor_helper_funcs; 381bbbed888SGerd Hoffmann } else { 382bbbed888SGerd Hoffmann formats = virtio_gpu_formats; 383bbbed888SGerd Hoffmann nformats = ARRAY_SIZE(virtio_gpu_formats); 384bbbed888SGerd Hoffmann funcs = &virtio_gpu_primary_helper_funcs; 385bbbed888SGerd Hoffmann } 38678476288SDanilo Krummrich 38778476288SDanilo Krummrich plane = drmm_universal_plane_alloc(dev, struct drm_plane, dev, 38878476288SDanilo Krummrich 1 << index, &virtio_gpu_plane_funcs, 38978476288SDanilo Krummrich formats, nformats, NULL, type, NULL); 39078476288SDanilo Krummrich if (IS_ERR(plane)) 39178476288SDanilo Krummrich return plane; 392dc5698e8SDave Airlie 393bbbed888SGerd Hoffmann drm_plane_helper_add(plane, funcs); 394dc5698e8SDave Airlie return plane; 395dc5698e8SDave Airlie } 396