Lines Matching +full:display +full:- +full:backend

1 // SPDX-License-Identifier: GPL-2.0 OR MIT
4 * Xen para-virtual DRM device
6 * Copyright (C) 2016-2018 EPAM Systems Inc.
12 #include <linux/dma-mapping.h>
26 #include <xen/xen-front-pgdir-shbuf.h>
46 dbuf->dbuf_cookie = dbuf_cookie; in dbuf_add_to_list()
47 list_add(&dbuf->list, &front_info->dbuf_list); in dbuf_add_to_list()
56 if (buf->dbuf_cookie == dbuf_cookie) in dbuf_get()
67 if (buf->dbuf_cookie == dbuf_cookie) { in dbuf_free()
68 list_del(&buf->list); in dbuf_free()
69 xen_front_pgdir_shbuf_unmap(&buf->shbuf); in dbuf_free()
70 xen_front_pgdir_shbuf_free(&buf->shbuf); in dbuf_free()
81 list_del(&buf->list); in dbuf_free_all()
82 xen_front_pgdir_shbuf_unmap(&buf->shbuf); in dbuf_free_all()
83 xen_front_pgdir_shbuf_free(&buf->shbuf); in dbuf_free_all()
93 req = RING_GET_REQUEST(&evtchnl->u.req.ring, in be_prepare_req()
94 evtchnl->u.req.ring.req_prod_pvt); in be_prepare_req()
95 req->operation = operation; in be_prepare_req()
96 req->id = evtchnl->evt_next_id++; in be_prepare_req()
97 evtchnl->evt_id = req->id; in be_prepare_req()
104 reinit_completion(&evtchnl->u.req.completion); in be_stream_do_io()
105 if (unlikely(evtchnl->state != EVTCHNL_STATE_CONNECTED)) in be_stream_do_io()
106 return -EIO; in be_stream_do_io()
114 if (wait_for_completion_timeout(&evtchnl->u.req.completion, in be_stream_wait_io()
116 return -ETIMEDOUT; in be_stream_wait_io()
118 return evtchnl->u.req.resp_status; in be_stream_wait_io()
131 front_info = pipeline->drm_info->front_info; in xen_drm_front_mode_set()
132 evtchnl = &front_info->evt_pairs[pipeline->index].req; in xen_drm_front_mode_set()
134 return -EIO; in xen_drm_front_mode_set()
136 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_mode_set()
138 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_mode_set()
140 req->op.set_config.x = x; in xen_drm_front_mode_set()
141 req->op.set_config.y = y; in xen_drm_front_mode_set()
142 req->op.set_config.width = width; in xen_drm_front_mode_set()
143 req->op.set_config.height = height; in xen_drm_front_mode_set()
144 req->op.set_config.bpp = bpp; in xen_drm_front_mode_set()
145 req->op.set_config.fb_cookie = fb_cookie; in xen_drm_front_mode_set()
148 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_mode_set()
153 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_mode_set()
169 evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; in xen_drm_front_dbuf_create()
171 return -EIO; in xen_drm_front_dbuf_create()
175 return -ENOMEM; in xen_drm_front_dbuf_create()
180 buf_cfg.xb_dev = front_info->xb_dev; in xen_drm_front_dbuf_create()
183 buf_cfg.pgdir = &dbuf->shbuf; in xen_drm_front_dbuf_create()
184 buf_cfg.be_alloc = front_info->cfg.be_alloc; in xen_drm_front_dbuf_create()
190 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_create()
192 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_dbuf_create()
194 req->op.dbuf_create.gref_directory = in xen_drm_front_dbuf_create()
195 xen_front_pgdir_shbuf_get_dir_start(&dbuf->shbuf); in xen_drm_front_dbuf_create()
196 req->op.dbuf_create.buffer_sz = size; in xen_drm_front_dbuf_create()
197 req->op.dbuf_create.data_ofs = offset; in xen_drm_front_dbuf_create()
198 req->op.dbuf_create.dbuf_cookie = dbuf_cookie; in xen_drm_front_dbuf_create()
199 req->op.dbuf_create.width = width; in xen_drm_front_dbuf_create()
200 req->op.dbuf_create.height = height; in xen_drm_front_dbuf_create()
201 req->op.dbuf_create.bpp = bpp; in xen_drm_front_dbuf_create()
203 req->op.dbuf_create.flags |= XENDISPL_DBUF_FLG_REQ_ALLOC; in xen_drm_front_dbuf_create()
206 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_dbuf_create()
215 ret = xen_front_pgdir_shbuf_map(&dbuf->shbuf); in xen_drm_front_dbuf_create()
219 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_create()
223 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_create()
225 dbuf_free(&front_info->dbuf_list, dbuf_cookie); in xen_drm_front_dbuf_create()
238 evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; in xen_drm_front_dbuf_destroy()
240 return -EIO; in xen_drm_front_dbuf_destroy()
242 be_alloc = front_info->cfg.be_alloc; in xen_drm_front_dbuf_destroy()
245 * For the backend allocated buffer release references now, so backend in xen_drm_front_dbuf_destroy()
249 dbuf_free(&front_info->dbuf_list, dbuf_cookie); in xen_drm_front_dbuf_destroy()
251 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_destroy()
253 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_dbuf_destroy()
255 req->op.dbuf_destroy.dbuf_cookie = dbuf_cookie; in xen_drm_front_dbuf_destroy()
258 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_dbuf_destroy()
264 * Do this regardless of communication status with the backend: in xen_drm_front_dbuf_destroy()
268 dbuf_free(&front_info->dbuf_list, dbuf_cookie); in xen_drm_front_dbuf_destroy()
270 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_destroy()
284 evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; in xen_drm_front_fb_attach()
286 return -EIO; in xen_drm_front_fb_attach()
288 buf = dbuf_get(&front_info->dbuf_list, dbuf_cookie); in xen_drm_front_fb_attach()
290 return -EINVAL; in xen_drm_front_fb_attach()
292 buf->fb_cookie = fb_cookie; in xen_drm_front_fb_attach()
294 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_fb_attach()
296 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_fb_attach()
298 req->op.fb_attach.dbuf_cookie = dbuf_cookie; in xen_drm_front_fb_attach()
299 req->op.fb_attach.fb_cookie = fb_cookie; in xen_drm_front_fb_attach()
300 req->op.fb_attach.width = width; in xen_drm_front_fb_attach()
301 req->op.fb_attach.height = height; in xen_drm_front_fb_attach()
302 req->op.fb_attach.pixel_format = pixel_format; in xen_drm_front_fb_attach()
305 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_fb_attach()
310 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_fb_attach()
322 evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; in xen_drm_front_fb_detach()
324 return -EIO; in xen_drm_front_fb_detach()
326 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_fb_detach()
328 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_fb_detach()
330 req->op.fb_detach.fb_cookie = fb_cookie; in xen_drm_front_fb_detach()
333 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_fb_detach()
338 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_fb_detach()
350 if (unlikely(conn_idx >= front_info->num_evt_pairs)) in xen_drm_front_page_flip()
351 return -EINVAL; in xen_drm_front_page_flip()
353 evtchnl = &front_info->evt_pairs[conn_idx].req; in xen_drm_front_page_flip()
355 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_page_flip()
357 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_page_flip()
359 req->op.pg_flip.fb_cookie = fb_cookie; in xen_drm_front_page_flip()
362 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_page_flip()
367 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_page_flip()
374 struct xen_drm_front_drm_info *drm_info = front_info->drm_info; in xen_drm_front_on_frame_done()
376 if (unlikely(conn_idx >= front_info->cfg.num_connectors)) in xen_drm_front_on_frame_done()
379 xen_drm_front_kms_on_frame_done(&drm_info->pipeline[conn_idx], in xen_drm_front_on_frame_done()
385 struct xen_drm_front_drm_info *drm_info = obj->dev->dev_private; in xen_drm_front_gem_object_free()
388 if (drm_dev_enter(obj->dev, &idx)) { in xen_drm_front_gem_object_free()
389 xen_drm_front_dbuf_destroy(drm_info->front_info, in xen_drm_front_gem_object_free()
393 dbuf_free(&drm_info->front_info->dbuf_list, in xen_drm_front_gem_object_free()
404 struct xen_drm_front_drm_info *drm_info = dev->dev_private; in xen_drm_drv_dumb_create()
410 * constructed GEM object which is communicated to the backend, and in xen_drm_drv_dumb_create()
413 * immediately visible to user-space, so the latter can try accessing in xen_drm_drv_dumb_create()
417 args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8); in xen_drm_drv_dumb_create()
418 args->size = args->pitch * args->height; in xen_drm_drv_dumb_create()
420 obj = xen_drm_front_gem_create(dev, args->size); in xen_drm_drv_dumb_create()
426 ret = xen_drm_front_dbuf_create(drm_info->front_info, in xen_drm_drv_dumb_create()
428 args->width, args->height, args->bpp, in xen_drm_drv_dumb_create()
429 args->size, 0, in xen_drm_drv_dumb_create()
435 ret = drm_gem_handle_create(filp, obj, &args->handle); in xen_drm_drv_dumb_create()
439 /* Drop reference from allocate - handle holds it now */ in xen_drm_drv_dumb_create()
444 xen_drm_front_dbuf_destroy(drm_info->front_info, in xen_drm_drv_dumb_create()
456 struct xen_drm_front_drm_info *drm_info = dev->dev_private; in xen_drm_drv_release()
457 struct xen_drm_front_info *front_info = drm_info->front_info; in xen_drm_drv_release()
464 if (front_info->cfg.be_alloc) in xen_drm_drv_release()
465 xenbus_switch_state(front_info->xb_dev, in xen_drm_drv_release()
479 .name = "xendrm-du",
480 .desc = "Xen PV DRM Display Unit",
489 struct device *dev = &front_info->xb_dev->dev; in xen_drm_drv_init()
495 return -ENODEV; in xen_drm_drv_init()
501 ret = -ENOMEM; in xen_drm_drv_init()
505 drm_info->front_info = front_info; in xen_drm_drv_init()
506 front_info->drm_info = drm_info; in xen_drm_drv_init()
514 drm_info->drm_dev = drm_dev; in xen_drm_drv_init()
516 drm_dev->dev_private = drm_info; in xen_drm_drv_init()
531 xen_drm_driver.date, drm_dev->primary->index); in xen_drm_drv_init()
543 front_info->drm_info = NULL; in xen_drm_drv_init()
550 struct xen_drm_front_drm_info *drm_info = front_info->drm_info; in xen_drm_drv_fini()
556 dev = drm_info->drm_dev; in xen_drm_drv_fini()
568 front_info->drm_info = NULL; in xen_drm_drv_fini()
571 dbuf_free_all(&front_info->dbuf_list); in xen_drm_drv_fini()
574 * If we are not using backend allocated buffers, then tell the in xen_drm_drv_fini()
575 * backend we are ready to (re)initialize. Otherwise, wait for in xen_drm_drv_fini()
578 if (!front_info->cfg.be_alloc) in xen_drm_drv_fini()
579 xenbus_switch_state(front_info->xb_dev, in xen_drm_drv_fini()
585 struct xen_drm_front_cfg *cfg = &front_info->cfg; in displback_initwait()
588 cfg->front_info = front_info; in displback_initwait()
593 DRM_INFO("Have %d connector(s)\n", cfg->num_connectors); in displback_initwait()
610 if (!front_info->drm_info) in displback_disconnect()
613 /* Tell the backend to wait until we release the DRM driver. */ in displback_disconnect()
614 xenbus_switch_state(front_info->xb_dev, XenbusStateReconfiguring); in displback_disconnect()
622 struct xen_drm_front_info *front_info = dev_get_drvdata(&xb_dev->dev); in displback_changed()
625 DRM_DEBUG("Backend state is %s, front is %s\n", in displback_changed()
627 xenbus_strstate(xb_dev->state)); in displback_changed()
636 if (xb_dev->state == XenbusStateReconfiguring) in displback_changed()
639 /* recovering after backend unexpected closure */ in displback_changed()
644 if (xb_dev->state == XenbusStateReconfiguring) in displback_changed()
647 /* recovering after backend unexpected closure */ in displback_changed()
649 if (xb_dev->state != XenbusStateInitialising) in displback_changed()
660 if (xb_dev->state != XenbusStateInitialised) in displback_changed()
666 xenbus_dev_fatal(xb_dev, ret, "connecting backend"); in displback_changed()
674 * in this state backend starts freeing resources, in displback_changed()
682 if (xb_dev->state == XenbusStateClosed) in displback_changed()
694 struct device *dev = &xb_dev->dev; in xen_drv_probe()
703 front_info = devm_kzalloc(&xb_dev->dev, in xen_drv_probe()
706 return -ENOMEM; in xen_drv_probe()
708 front_info->xb_dev = xb_dev; in xen_drv_probe()
709 spin_lock_init(&front_info->io_lock); in xen_drv_probe()
710 INIT_LIST_HEAD(&front_info->dbuf_list); in xen_drv_probe()
711 dev_set_drvdata(&xb_dev->dev, front_info); in xen_drv_probe()
718 struct xen_drm_front_info *front_info = dev_get_drvdata(&dev->dev); in xen_drv_remove()
725 * so no backend state change events come via .otherend_changed in xen_drv_remove()
727 * signaling the backend to free event channels, waiting for its in xen_drv_remove()
729 * Normally when front driver removed backend will finally go into in xen_drv_remove()
732 * Workaround: read backend's state manually and wait with time-out. in xen_drv_remove()
734 while ((xenbus_read_unsigned(front_info->xb_dev->otherend, "state", in xen_drv_remove()
736 --to) in xen_drv_remove()
742 state = xenbus_read_unsigned(front_info->xb_dev->otherend, in xen_drv_remove()
744 DRM_ERROR("Backend state is %s while removing driver\n", in xen_drv_remove()
771 return -ENODEV; in xen_drv_init()
775 return -ENODEV; in xen_drv_init()
778 return -ENODEV; in xen_drv_init()
793 MODULE_DESCRIPTION("Xen para-virtualized display device frontend");