1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 3 /* 4 * Xen para-virtual DRM device 5 * 6 * Copyright (C) 2016-2018 EPAM Systems Inc. 7 * 8 * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> 9 */ 10 11 #include <drm/drm_atomic.h> 12 #include <drm/drm_atomic_helper.h> 13 #include <drm/drm_drv.h> 14 #include <drm/drm_fourcc.h> 15 #include <drm/drm_framebuffer.h> 16 #include <drm/drm_gem.h> 17 #include <drm/drm_gem_atomic_helper.h> 18 #include <drm/drm_gem_framebuffer_helper.h> 19 #include <drm/drm_probe_helper.h> 20 #include <drm/drm_vblank.h> 21 22 #include "xen_drm_front.h" 23 #include "xen_drm_front_conn.h" 24 #include "xen_drm_front_kms.h" 25 26 /* 27 * Timeout in ms to wait for frame done event from the backend: 28 * must be a bit more than IO time-out 29 */ 30 #define FRAME_DONE_TO_MS (XEN_DRM_FRONT_WAIT_BACK_MS + 100) 31 32 static struct xen_drm_front_drm_pipeline * 33 to_xen_drm_pipeline(struct drm_simple_display_pipe *pipe) 34 { 35 return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); 36 } 37 38 static void fb_destroy(struct drm_framebuffer *fb) 39 { 40 struct xen_drm_front_drm_info *drm_info = fb->dev->dev_private; 41 int idx; 42 43 if (drm_dev_enter(fb->dev, &idx)) { 44 xen_drm_front_fb_detach(drm_info->front_info, 45 xen_drm_front_fb_to_cookie(fb)); 46 drm_dev_exit(idx); 47 } 48 drm_gem_fb_destroy(fb); 49 } 50 51 static const struct drm_framebuffer_funcs fb_funcs = { 52 .destroy = fb_destroy, 53 }; 54 55 static struct drm_framebuffer * 56 fb_create(struct drm_device *dev, struct drm_file *filp, 57 const struct drm_format_info *info, 58 const struct drm_mode_fb_cmd2 *mode_cmd) 59 { 60 struct xen_drm_front_drm_info *drm_info = dev->dev_private; 61 struct drm_framebuffer *fb; 62 struct drm_gem_object *gem_obj; 63 int ret; 64 65 fb = drm_gem_fb_create_with_funcs(dev, filp, info, mode_cmd, &fb_funcs); 66 if (IS_ERR(fb)) 67 return fb; 68 69 gem_obj = fb->obj[0]; 70 71 ret = xen_drm_front_fb_attach(drm_info->front_info, 72 xen_drm_front_dbuf_to_cookie(gem_obj), 73 xen_drm_front_fb_to_cookie(fb), 74 fb->width, fb->height, 75 fb->format->format); 76 if (ret < 0) { 77 DRM_ERROR("Back failed to attach FB %p: %d\n", fb, ret); 78 goto fail; 79 } 80 81 return fb; 82 83 fail: 84 drm_gem_fb_destroy(fb); 85 return ERR_PTR(ret); 86 } 87 88 static const struct drm_mode_config_funcs mode_config_funcs = { 89 .fb_create = fb_create, 90 .atomic_check = drm_atomic_helper_check, 91 .atomic_commit = drm_atomic_helper_commit, 92 }; 93 94 static void send_pending_event(struct xen_drm_front_drm_pipeline *pipeline) 95 { 96 struct drm_crtc *crtc = &pipeline->pipe.crtc; 97 struct drm_device *dev = crtc->dev; 98 unsigned long flags; 99 100 spin_lock_irqsave(&dev->event_lock, flags); 101 if (pipeline->pending_event) 102 drm_crtc_send_vblank_event(crtc, pipeline->pending_event); 103 pipeline->pending_event = NULL; 104 spin_unlock_irqrestore(&dev->event_lock, flags); 105 } 106 107 static void display_enable(struct drm_simple_display_pipe *pipe, 108 struct drm_crtc_state *crtc_state, 109 struct drm_plane_state *plane_state) 110 { 111 struct xen_drm_front_drm_pipeline *pipeline = 112 to_xen_drm_pipeline(pipe); 113 struct drm_crtc *crtc = &pipe->crtc; 114 struct drm_framebuffer *fb = plane_state->fb; 115 int ret, idx; 116 117 if (!drm_dev_enter(pipe->crtc.dev, &idx)) 118 return; 119 120 ret = xen_drm_front_mode_set(pipeline, crtc->x, crtc->y, 121 fb->width, fb->height, 122 fb->format->cpp[0] * 8, 123 xen_drm_front_fb_to_cookie(fb)); 124 125 if (ret) { 126 DRM_ERROR("Failed to enable display: %d\n", ret); 127 pipeline->conn_connected = false; 128 } 129 130 drm_dev_exit(idx); 131 } 132 133 static void display_disable(struct drm_simple_display_pipe *pipe) 134 { 135 struct xen_drm_front_drm_pipeline *pipeline = 136 to_xen_drm_pipeline(pipe); 137 int ret = 0, idx; 138 139 if (drm_dev_enter(pipe->crtc.dev, &idx)) { 140 ret = xen_drm_front_mode_set(pipeline, 0, 0, 0, 0, 0, 141 xen_drm_front_fb_to_cookie(NULL)); 142 drm_dev_exit(idx); 143 } 144 if (ret) 145 DRM_ERROR("Failed to disable display: %d\n", ret); 146 147 /* Make sure we can restart with enabled connector next time */ 148 pipeline->conn_connected = true; 149 150 /* release stalled event if any */ 151 send_pending_event(pipeline); 152 } 153 154 void xen_drm_front_kms_on_frame_done(struct xen_drm_front_drm_pipeline *pipeline, 155 u64 fb_cookie) 156 { 157 /* 158 * This runs in interrupt context, e.g. under 159 * drm_info->front_info->io_lock, so we cannot call _sync version 160 * to cancel the work 161 */ 162 cancel_delayed_work(&pipeline->pflip_to_worker); 163 164 send_pending_event(pipeline); 165 } 166 167 static void pflip_to_worker(struct work_struct *work) 168 { 169 struct delayed_work *delayed_work = to_delayed_work(work); 170 struct xen_drm_front_drm_pipeline *pipeline = 171 container_of(delayed_work, 172 struct xen_drm_front_drm_pipeline, 173 pflip_to_worker); 174 175 DRM_ERROR("Frame done timed-out, releasing"); 176 send_pending_event(pipeline); 177 } 178 179 static bool display_send_page_flip(struct drm_simple_display_pipe *pipe, 180 struct drm_plane_state *old_plane_state) 181 { 182 struct drm_plane_state *plane_state = 183 drm_atomic_get_new_plane_state(old_plane_state->state, 184 &pipe->plane); 185 186 /* 187 * If old_plane_state->fb is NULL and plane_state->fb is not, 188 * then this is an atomic commit which will enable display. 189 * If old_plane_state->fb is not NULL and plane_state->fb is, 190 * then this is an atomic commit which will disable display. 191 * Ignore these and do not send page flip as this framebuffer will be 192 * sent to the backend as a part of display_set_config call. 193 */ 194 if (old_plane_state->fb && plane_state->fb) { 195 struct xen_drm_front_drm_pipeline *pipeline = 196 to_xen_drm_pipeline(pipe); 197 struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; 198 int ret; 199 200 schedule_delayed_work(&pipeline->pflip_to_worker, 201 msecs_to_jiffies(FRAME_DONE_TO_MS)); 202 203 ret = xen_drm_front_page_flip(drm_info->front_info, 204 pipeline->index, 205 xen_drm_front_fb_to_cookie(plane_state->fb)); 206 if (ret) { 207 DRM_ERROR("Failed to send page flip request to backend: %d\n", ret); 208 209 pipeline->conn_connected = false; 210 /* 211 * Report the flip not handled, so pending event is 212 * sent, unblocking user-space. 213 */ 214 return false; 215 } 216 /* 217 * Signal that page flip was handled, pending event will be sent 218 * on frame done event from the backend. 219 */ 220 return true; 221 } 222 223 return false; 224 } 225 226 static int display_check(struct drm_simple_display_pipe *pipe, 227 struct drm_plane_state *plane_state, 228 struct drm_crtc_state *crtc_state) 229 { 230 /* 231 * Xen doesn't initialize vblanking via drm_vblank_init(), so 232 * DRM helpers assume that it doesn't handle vblanking and start 233 * sending out fake VBLANK events automatically. 234 * 235 * As xen contains it's own logic for sending out VBLANK events 236 * in send_pending_event(), disable no_vblank (i.e., the xen 237 * driver has vblanking support). 238 */ 239 crtc_state->no_vblank = false; 240 241 return 0; 242 } 243 244 static void display_update(struct drm_simple_display_pipe *pipe, 245 struct drm_plane_state *old_plane_state) 246 { 247 struct xen_drm_front_drm_pipeline *pipeline = 248 to_xen_drm_pipeline(pipe); 249 struct drm_crtc *crtc = &pipe->crtc; 250 struct drm_pending_vblank_event *event; 251 int idx; 252 253 event = crtc->state->event; 254 if (event) { 255 struct drm_device *dev = crtc->dev; 256 unsigned long flags; 257 258 WARN_ON(pipeline->pending_event); 259 260 spin_lock_irqsave(&dev->event_lock, flags); 261 crtc->state->event = NULL; 262 263 pipeline->pending_event = event; 264 spin_unlock_irqrestore(&dev->event_lock, flags); 265 } 266 267 if (!drm_dev_enter(pipe->crtc.dev, &idx)) { 268 send_pending_event(pipeline); 269 return; 270 } 271 272 /* 273 * Send page flip request to the backend *after* we have event cached 274 * above, so on page flip done event from the backend we can 275 * deliver it and there is no race condition between this code and 276 * event from the backend. 277 * If this is not a page flip, e.g. no flip done event from the backend 278 * is expected, then send now. 279 */ 280 if (!display_send_page_flip(pipe, old_plane_state)) 281 send_pending_event(pipeline); 282 283 drm_dev_exit(idx); 284 } 285 286 static enum drm_mode_status 287 display_mode_valid(struct drm_simple_display_pipe *pipe, 288 const struct drm_display_mode *mode) 289 { 290 struct xen_drm_front_drm_pipeline *pipeline = 291 container_of(pipe, struct xen_drm_front_drm_pipeline, 292 pipe); 293 294 if (mode->hdisplay != pipeline->width) 295 return MODE_ERROR; 296 297 if (mode->vdisplay != pipeline->height) 298 return MODE_ERROR; 299 300 return MODE_OK; 301 } 302 303 static const struct drm_simple_display_pipe_funcs display_funcs = { 304 .mode_valid = display_mode_valid, 305 .enable = display_enable, 306 .disable = display_disable, 307 .check = display_check, 308 .update = display_update, 309 }; 310 311 static int display_pipe_init(struct xen_drm_front_drm_info *drm_info, 312 int index, struct xen_drm_front_cfg_connector *cfg, 313 struct xen_drm_front_drm_pipeline *pipeline) 314 { 315 struct drm_device *dev = drm_info->drm_dev; 316 const u32 *formats; 317 int format_count; 318 int ret; 319 320 pipeline->drm_info = drm_info; 321 pipeline->index = index; 322 pipeline->height = cfg->height; 323 pipeline->width = cfg->width; 324 325 INIT_DELAYED_WORK(&pipeline->pflip_to_worker, pflip_to_worker); 326 327 ret = xen_drm_front_conn_init(drm_info, &pipeline->conn); 328 if (ret) 329 return ret; 330 331 formats = xen_drm_front_conn_get_formats(&format_count); 332 333 return drm_simple_display_pipe_init(dev, &pipeline->pipe, 334 &display_funcs, formats, 335 format_count, NULL, 336 &pipeline->conn); 337 } 338 339 int xen_drm_front_kms_init(struct xen_drm_front_drm_info *drm_info) 340 { 341 struct drm_device *dev = drm_info->drm_dev; 342 int i, ret; 343 344 drm_mode_config_init(dev); 345 346 dev->mode_config.min_width = 0; 347 dev->mode_config.min_height = 0; 348 dev->mode_config.max_width = 4095; 349 dev->mode_config.max_height = 2047; 350 dev->mode_config.funcs = &mode_config_funcs; 351 352 for (i = 0; i < drm_info->front_info->cfg.num_connectors; i++) { 353 struct xen_drm_front_cfg_connector *cfg = 354 &drm_info->front_info->cfg.connectors[i]; 355 struct xen_drm_front_drm_pipeline *pipeline = 356 &drm_info->pipeline[i]; 357 358 ret = display_pipe_init(drm_info, i, cfg, pipeline); 359 if (ret) { 360 drm_mode_config_cleanup(dev); 361 return ret; 362 } 363 } 364 365 drm_mode_config_reset(dev); 366 drm_kms_helper_poll_init(dev); 367 return 0; 368 } 369 370 void xen_drm_front_kms_fini(struct xen_drm_front_drm_info *drm_info) 371 { 372 int i; 373 374 for (i = 0; i < drm_info->front_info->cfg.num_connectors; i++) { 375 struct xen_drm_front_drm_pipeline *pipeline = 376 &drm_info->pipeline[i]; 377 378 cancel_delayed_work_sync(&pipeline->pflip_to_worker); 379 380 send_pending_event(pipeline); 381 } 382 } 383