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>
27 #include <xen/xen-front-pgdir-shbuf.h>
47 dbuf->dbuf_cookie = dbuf_cookie; in dbuf_add_to_list()
48 list_add(&dbuf->list, &front_info->dbuf_list); in dbuf_add_to_list()
57 if (buf->dbuf_cookie == dbuf_cookie) in dbuf_get()
68 if (buf->dbuf_cookie == dbuf_cookie) { in dbuf_free()
69 list_del(&buf->list); in dbuf_free()
70 xen_front_pgdir_shbuf_unmap(&buf->shbuf); in dbuf_free()
71 xen_front_pgdir_shbuf_free(&buf->shbuf); in dbuf_free()
82 list_del(&buf->list); in dbuf_free_all()
83 xen_front_pgdir_shbuf_unmap(&buf->shbuf); in dbuf_free_all()
84 xen_front_pgdir_shbuf_free(&buf->shbuf); in dbuf_free_all()
94 req = RING_GET_REQUEST(&evtchnl->u.req.ring, in be_prepare_req()
95 evtchnl->u.req.ring.req_prod_pvt); in be_prepare_req()
96 req->operation = operation; in be_prepare_req()
97 req->id = evtchnl->evt_next_id++; in be_prepare_req()
98 evtchnl->evt_id = req->id; in be_prepare_req()
105 reinit_completion(&evtchnl->u.req.completion); in be_stream_do_io()
106 if (unlikely(evtchnl->state != EVTCHNL_STATE_CONNECTED)) in be_stream_do_io()
107 return -EIO; in be_stream_do_io()
115 if (wait_for_completion_timeout(&evtchnl->u.req.completion, in be_stream_wait_io()
117 return -ETIMEDOUT; in be_stream_wait_io()
119 return evtchnl->u.req.resp_status; in be_stream_wait_io()
132 front_info = pipeline->drm_info->front_info; in xen_drm_front_mode_set()
133 evtchnl = &front_info->evt_pairs[pipeline->index].req; in xen_drm_front_mode_set()
135 return -EIO; in xen_drm_front_mode_set()
137 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_mode_set()
139 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_mode_set()
141 req->op.set_config.x = x; in xen_drm_front_mode_set()
142 req->op.set_config.y = y; in xen_drm_front_mode_set()
143 req->op.set_config.width = width; in xen_drm_front_mode_set()
144 req->op.set_config.height = height; in xen_drm_front_mode_set()
145 req->op.set_config.bpp = bpp; in xen_drm_front_mode_set()
146 req->op.set_config.fb_cookie = fb_cookie; in xen_drm_front_mode_set()
149 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_mode_set()
154 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_mode_set()
170 evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; in xen_drm_front_dbuf_create()
172 return -EIO; in xen_drm_front_dbuf_create()
176 return -ENOMEM; in xen_drm_front_dbuf_create()
181 buf_cfg.xb_dev = front_info->xb_dev; in xen_drm_front_dbuf_create()
184 buf_cfg.pgdir = &dbuf->shbuf; in xen_drm_front_dbuf_create()
185 buf_cfg.be_alloc = front_info->cfg.be_alloc; in xen_drm_front_dbuf_create()
191 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_create()
193 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_dbuf_create()
195 req->op.dbuf_create.gref_directory = in xen_drm_front_dbuf_create()
196 xen_front_pgdir_shbuf_get_dir_start(&dbuf->shbuf); in xen_drm_front_dbuf_create()
197 req->op.dbuf_create.buffer_sz = size; in xen_drm_front_dbuf_create()
198 req->op.dbuf_create.data_ofs = offset; in xen_drm_front_dbuf_create()
199 req->op.dbuf_create.dbuf_cookie = dbuf_cookie; in xen_drm_front_dbuf_create()
200 req->op.dbuf_create.width = width; in xen_drm_front_dbuf_create()
201 req->op.dbuf_create.height = height; in xen_drm_front_dbuf_create()
202 req->op.dbuf_create.bpp = bpp; in xen_drm_front_dbuf_create()
204 req->op.dbuf_create.flags |= XENDISPL_DBUF_FLG_REQ_ALLOC; in xen_drm_front_dbuf_create()
207 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_dbuf_create()
216 ret = xen_front_pgdir_shbuf_map(&dbuf->shbuf); in xen_drm_front_dbuf_create()
220 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_create()
224 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_create()
226 dbuf_free(&front_info->dbuf_list, dbuf_cookie); in xen_drm_front_dbuf_create()
239 evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; in xen_drm_front_dbuf_destroy()
241 return -EIO; in xen_drm_front_dbuf_destroy()
243 be_alloc = front_info->cfg.be_alloc; in xen_drm_front_dbuf_destroy()
246 * For the backend allocated buffer release references now, so backend in xen_drm_front_dbuf_destroy()
250 dbuf_free(&front_info->dbuf_list, dbuf_cookie); in xen_drm_front_dbuf_destroy()
252 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_destroy()
254 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_dbuf_destroy()
256 req->op.dbuf_destroy.dbuf_cookie = dbuf_cookie; in xen_drm_front_dbuf_destroy()
259 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_dbuf_destroy()
265 * Do this regardless of communication status with the backend: in xen_drm_front_dbuf_destroy()
269 dbuf_free(&front_info->dbuf_list, dbuf_cookie); in xen_drm_front_dbuf_destroy()
271 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_dbuf_destroy()
285 evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; in xen_drm_front_fb_attach()
287 return -EIO; in xen_drm_front_fb_attach()
289 buf = dbuf_get(&front_info->dbuf_list, dbuf_cookie); in xen_drm_front_fb_attach()
291 return -EINVAL; in xen_drm_front_fb_attach()
293 buf->fb_cookie = fb_cookie; in xen_drm_front_fb_attach()
295 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_fb_attach()
297 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_fb_attach()
299 req->op.fb_attach.dbuf_cookie = dbuf_cookie; in xen_drm_front_fb_attach()
300 req->op.fb_attach.fb_cookie = fb_cookie; in xen_drm_front_fb_attach()
301 req->op.fb_attach.width = width; in xen_drm_front_fb_attach()
302 req->op.fb_attach.height = height; in xen_drm_front_fb_attach()
303 req->op.fb_attach.pixel_format = pixel_format; in xen_drm_front_fb_attach()
306 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_fb_attach()
311 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_fb_attach()
323 evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; in xen_drm_front_fb_detach()
325 return -EIO; in xen_drm_front_fb_detach()
327 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_fb_detach()
329 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_fb_detach()
331 req->op.fb_detach.fb_cookie = fb_cookie; in xen_drm_front_fb_detach()
334 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_fb_detach()
339 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_fb_detach()
351 if (unlikely(conn_idx >= front_info->num_evt_pairs)) in xen_drm_front_page_flip()
352 return -EINVAL; in xen_drm_front_page_flip()
354 evtchnl = &front_info->evt_pairs[conn_idx].req; in xen_drm_front_page_flip()
356 mutex_lock(&evtchnl->u.req.req_io_lock); in xen_drm_front_page_flip()
358 spin_lock_irqsave(&front_info->io_lock, flags); in xen_drm_front_page_flip()
360 req->op.pg_flip.fb_cookie = fb_cookie; in xen_drm_front_page_flip()
363 spin_unlock_irqrestore(&front_info->io_lock, flags); in xen_drm_front_page_flip()
368 mutex_unlock(&evtchnl->u.req.req_io_lock); in xen_drm_front_page_flip()
375 struct xen_drm_front_drm_info *drm_info = front_info->drm_info; in xen_drm_front_on_frame_done()
377 if (unlikely(conn_idx >= front_info->cfg.num_connectors)) in xen_drm_front_on_frame_done()
380 xen_drm_front_kms_on_frame_done(&drm_info->pipeline[conn_idx], in xen_drm_front_on_frame_done()
388 struct xen_drm_front_drm_info *drm_info = dev->dev_private; in xen_drm_drv_dumb_create()
394 * constructed GEM object which is communicated to the backend, and in xen_drm_drv_dumb_create()
397 * immediately visible to user-space, so the latter can try accessing in xen_drm_drv_dumb_create()
401 args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8); in xen_drm_drv_dumb_create()
402 args->size = args->pitch * args->height; in xen_drm_drv_dumb_create()
404 obj = xen_drm_front_gem_create(dev, args->size); in xen_drm_drv_dumb_create()
410 ret = xen_drm_front_dbuf_create(drm_info->front_info, in xen_drm_drv_dumb_create()
412 args->width, args->height, args->bpp, in xen_drm_drv_dumb_create()
413 args->size, 0, in xen_drm_drv_dumb_create()
419 ret = drm_gem_handle_create(filp, obj, &args->handle); in xen_drm_drv_dumb_create()
423 /* Drop reference from allocate - handle holds it now */ in xen_drm_drv_dumb_create()
428 xen_drm_front_dbuf_destroy(drm_info->front_info, in xen_drm_drv_dumb_create()
440 struct xen_drm_front_drm_info *drm_info = obj->dev->dev_private; in xen_drm_drv_free_object_unlocked()
443 if (drm_dev_enter(obj->dev, &idx)) { in xen_drm_drv_free_object_unlocked()
444 xen_drm_front_dbuf_destroy(drm_info->front_info, in xen_drm_drv_free_object_unlocked()
448 dbuf_free(&drm_info->front_info->dbuf_list, in xen_drm_drv_free_object_unlocked()
457 struct xen_drm_front_drm_info *drm_info = dev->dev_private; in xen_drm_drv_release()
458 struct xen_drm_front_info *front_info = drm_info->front_info; in xen_drm_drv_release()
465 if (front_info->cfg.be_alloc) in xen_drm_drv_release()
466 xenbus_switch_state(front_info->xb_dev, in xen_drm_drv_release()
505 .name = "xendrm-du",
506 .desc = "Xen PV DRM Display Unit",
515 struct device *dev = &front_info->xb_dev->dev; in xen_drm_drv_init()
524 ret = -ENOMEM; in xen_drm_drv_init()
528 drm_info->front_info = front_info; in xen_drm_drv_init()
529 front_info->drm_info = drm_info; in xen_drm_drv_init()
537 drm_info->drm_dev = drm_dev; in xen_drm_drv_init()
539 drm_dev->dev_private = drm_info; in xen_drm_drv_init()
554 xen_drm_driver.date, drm_dev->primary->index); in xen_drm_drv_init()
571 struct xen_drm_front_drm_info *drm_info = front_info->drm_info; in xen_drm_drv_fini()
577 dev = drm_info->drm_dev; in xen_drm_drv_fini()
589 front_info->drm_info = NULL; in xen_drm_drv_fini()
592 dbuf_free_all(&front_info->dbuf_list); in xen_drm_drv_fini()
595 * If we are not using backend allocated buffers, then tell the in xen_drm_drv_fini()
596 * backend we are ready to (re)initialize. Otherwise, wait for in xen_drm_drv_fini()
599 if (!front_info->cfg.be_alloc) in xen_drm_drv_fini()
600 xenbus_switch_state(front_info->xb_dev, in xen_drm_drv_fini()
606 struct xen_drm_front_cfg *cfg = &front_info->cfg; in displback_initwait()
609 cfg->front_info = front_info; in displback_initwait()
614 DRM_INFO("Have %d connector(s)\n", cfg->num_connectors); in displback_initwait()
631 if (!front_info->drm_info) in displback_disconnect()
634 /* Tell the backend to wait until we release the DRM driver. */ in displback_disconnect()
635 xenbus_switch_state(front_info->xb_dev, XenbusStateReconfiguring); in displback_disconnect()
643 struct xen_drm_front_info *front_info = dev_get_drvdata(&xb_dev->dev); in displback_changed()
646 DRM_DEBUG("Backend state is %s, front is %s\n", in displback_changed()
648 xenbus_strstate(xb_dev->state)); in displback_changed()
657 if (xb_dev->state == XenbusStateReconfiguring) in displback_changed()
660 /* recovering after backend unexpected closure */ in displback_changed()
665 if (xb_dev->state == XenbusStateReconfiguring) in displback_changed()
668 /* recovering after backend unexpected closure */ in displback_changed()
670 if (xb_dev->state != XenbusStateInitialising) in displback_changed()
681 if (xb_dev->state != XenbusStateInitialised) in displback_changed()
687 xenbus_dev_fatal(xb_dev, ret, "connecting backend"); in displback_changed()
695 * in this state backend starts freeing resources, in displback_changed()
703 if (xb_dev->state == XenbusStateClosed) in displback_changed()
715 struct device *dev = &xb_dev->dev; in xen_drv_probe()
724 front_info = devm_kzalloc(&xb_dev->dev, in xen_drv_probe()
727 return -ENOMEM; in xen_drv_probe()
729 front_info->xb_dev = xb_dev; in xen_drv_probe()
730 spin_lock_init(&front_info->io_lock); in xen_drv_probe()
731 INIT_LIST_HEAD(&front_info->dbuf_list); in xen_drv_probe()
732 dev_set_drvdata(&xb_dev->dev, front_info); in xen_drv_probe()
739 struct xen_drm_front_info *front_info = dev_get_drvdata(&dev->dev); in xen_drv_remove()
746 * so no backend state change events come via .otherend_changed in xen_drv_remove()
748 * signaling the backend to free event channels, waiting for its in xen_drv_remove()
750 * Normally when front driver removed backend will finally go into in xen_drv_remove()
753 * Workaround: read backend's state manually and wait with time-out. in xen_drv_remove()
755 while ((xenbus_read_unsigned(front_info->xb_dev->otherend, "state", in xen_drv_remove()
757 --to) in xen_drv_remove()
763 state = xenbus_read_unsigned(front_info->xb_dev->otherend, in xen_drv_remove()
765 DRM_ERROR("Backend state is %s while removing driver\n", in xen_drv_remove()
792 return -ENODEV; in xen_drv_init()
796 return -ENODEV; in xen_drv_init()
799 return -ENODEV; in xen_drv_init()
814 MODULE_DESCRIPTION("Xen para-virtualized display device frontend");