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 <linux/device.h> 12 13 #include <drm/drm_print.h> 14 15 #include <xen/interface/io/displif.h> 16 #include <xen/xenbus.h> 17 18 #include "xen_drm_front.h" 19 #include "xen_drm_front_cfg.h" 20 21 static int cfg_connector(struct xen_drm_front_info *front_info, 22 struct xen_drm_front_cfg_connector *connector, 23 const char *path, int index) 24 { 25 char *connector_path; 26 27 connector_path = devm_kasprintf(&front_info->xb_dev->dev, 28 GFP_KERNEL, "%s/%d", path, index); 29 if (!connector_path) 30 return -ENOMEM; 31 32 if (xenbus_scanf(XBT_NIL, connector_path, XENDISPL_FIELD_RESOLUTION, 33 "%d" XENDISPL_RESOLUTION_SEPARATOR "%d", 34 &connector->width, &connector->height) < 0) { 35 /* either no entry configured or wrong resolution set */ 36 connector->width = 0; 37 connector->height = 0; 38 return -EINVAL; 39 } 40 41 connector->xenstore_path = connector_path; 42 43 DRM_INFO("Connector %s: resolution %dx%d\n", 44 connector_path, connector->width, connector->height); 45 return 0; 46 } 47 48 int xen_drm_front_cfg_card(struct xen_drm_front_info *front_info, 49 struct xen_drm_front_cfg *cfg) 50 { 51 struct xenbus_device *xb_dev = front_info->xb_dev; 52 int ret, i; 53 54 if (xenbus_read_unsigned(front_info->xb_dev->nodename, 55 XENDISPL_FIELD_BE_ALLOC, 0)) { 56 DRM_INFO("Backend can provide display buffers\n"); 57 cfg->be_alloc = true; 58 } 59 60 cfg->num_connectors = 0; 61 for (i = 0; i < ARRAY_SIZE(cfg->connectors); i++) { 62 ret = cfg_connector(front_info, &cfg->connectors[i], 63 xb_dev->nodename, i); 64 if (ret < 0) 65 break; 66 cfg->num_connectors++; 67 } 68 69 if (!cfg->num_connectors) { 70 DRM_ERROR("No connector(s) configured at %s\n", 71 xb_dev->nodename); 72 return -ENODEV; 73 } 74 75 return 0; 76 } 77 78