示例#1
0
static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device *vdev)
{
	struct pci_dev *pdev = to_pci_dev(vdev->dev.parent);
	const char *pname = dev_name(&pdev->dev);
	bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
	char unique[20];

	DRM_INFO("pci: %s detected at %s\n",
		 vga ? "virtio-vga" : "virtio-gpu-pci",
		 pname);
	dev->pdev = pdev;
	if (vga)
		drm_fb_helper_remove_conflicting_pci_framebuffers(pdev,
								  0,
								  "virtiodrmfb");

	/*
	 * Normally the drm_dev_set_unique() call is done by core DRM.
	 * The following comment covers, why virtio cannot rely on it.
	 *
	 * Unlike the other virtual GPU drivers, virtio abstracts the
	 * underlying bus type by using struct virtio_device.
	 *
	 * Hence the dev_is_pci() check, used in core DRM, will fail
	 * and the unique returned will be the virtio_device "virtio0",
	 * while a "pci:..." one is required.
	 *
	 * A few other ideas were considered:
	 * - Extend the dev_is_pci() check [in drm_set_busid] to
	 *   consider virtio.
	 *   Seems like a bigger hack than what we have already.
	 *
	 * - Point drm_device::dev to the parent of the virtio_device
	 *   Semantic changes:
	 *   * Using the wrong device for i2c, framebuffer_alloc and
	 *     prime import.
	 *   Visual changes:
	 *   * Helpers such as DRM_DEV_ERROR, dev_info, drm_printer,
	 *     will print the wrong information.
	 *
	 * We could address the latter issues, by introducing
	 * drm_device::bus_dev, ... which would be used solely for this.
	 *
	 * So for the moment keep things as-is, with a bulky comment
	 * for the next person who feels like removing this
	 * drm_dev_set_unique() quirk.
	 */
	snprintf(unique, sizeof(unique), "pci:%s", pname);
	return drm_dev_set_unique(dev, unique);
}
示例#2
0
static int rcar_du_probe(struct platform_device *pdev)
{
    struct device_node *np = pdev->dev.of_node;
    struct rcar_du_device *rcdu;
    struct drm_connector *connector;
    struct drm_device *ddev;
    struct resource *mem;
    int ret;

    if (np == NULL) {
        dev_err(&pdev->dev, "no device tree node\n");
        return -ENODEV;
    }

    /* Allocate and initialize the DRM and R-Car device structures. */
    rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
    if (rcdu == NULL)
        return -ENOMEM;

    init_waitqueue_head(&rcdu->commit.wait);

    rcdu->dev = &pdev->dev;
    rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;

    ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
    if (!ddev)
        return -ENOMEM;

    drm_dev_set_unique(ddev, dev_name(&pdev->dev));

    rcdu->ddev = ddev;
    ddev->dev_private = rcdu;

    platform_set_drvdata(pdev, rcdu);

    /* I/O resources */
    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
    if (IS_ERR(rcdu->mmio)) {
        ret = PTR_ERR(rcdu->mmio);
        goto error;
    }

    /* Initialize vertical blanking interrupts handling. Start with vblank
     * disabled for all CRTCs.
     */
    ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1);
    if (ret < 0) {
        dev_err(&pdev->dev, "failed to initialize vblank\n");
        goto error;
    }

    /* DRM/KMS objects */
    ret = rcar_du_modeset_init(rcdu);
    if (ret < 0) {
        dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
        goto error;
    }

    ddev->irq_enabled = 1;

    /* Register the DRM device with the core and the connectors with
     * sysfs.
     */
    ret = drm_dev_register(ddev, 0);
    if (ret)
        goto error;

    mutex_lock(&ddev->mode_config.mutex);
    drm_for_each_connector(connector, ddev) {
        ret = drm_connector_register(connector);
        if (ret < 0)
            break;
    }
示例#3
0
/**
 * drm_dev_init - Initialise new DRM device
 * @dev: DRM device
 * @driver: DRM driver
 * @parent: Parent device object
 *
 * Initialize a new DRM device. No device registration is done.
 * Call drm_dev_register() to advertice the device to user space and register it
 * with other core subsystems. This should be done last in the device
 * initialization sequence to make sure userspace can't access an inconsistent
 * state.
 *
 * The initial ref-count of the object is 1. Use drm_dev_ref() and
 * drm_dev_unref() to take and drop further ref-counts.
 *
 * Note that for purely virtual devices @parent can be NULL.
 *
 * Drivers that do not want to allocate their own device struct
 * embedding struct &drm_device can call drm_dev_alloc() instead.
 *
 * RETURNS:
 * 0 on success, or error code on failure.
 */
int drm_dev_init(struct drm_device *dev,
		 struct drm_driver *driver,
		 struct device *parent)
{
	int ret;

	kref_init(&dev->ref);
	dev->dev = parent;
	dev->driver = driver;

	INIT_LIST_HEAD(&dev->filelist);
	INIT_LIST_HEAD(&dev->ctxlist);
	INIT_LIST_HEAD(&dev->vmalist);
	INIT_LIST_HEAD(&dev->maplist);
	INIT_LIST_HEAD(&dev->vblank_event_list);

	spin_lock_init(&dev->buf_lock);
	spin_lock_init(&dev->event_lock);
	mutex_init(&dev->struct_mutex);
	mutex_init(&dev->filelist_mutex);
	mutex_init(&dev->ctxlist_mutex);
	mutex_init(&dev->master_mutex);

	dev->anon_inode = drm_fs_inode_new();
	if (IS_ERR(dev->anon_inode)) {
		ret = PTR_ERR(dev->anon_inode);
		DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
		goto err_free;
	}

	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
		if (ret)
			goto err_minors;
	}

	if (drm_core_check_feature(dev, DRIVER_RENDER)) {
		ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
		if (ret)
			goto err_minors;
	}

	ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY);
	if (ret)
		goto err_minors;

	ret = drm_ht_create(&dev->map_hash, 12);
	if (ret)
		goto err_minors;

	drm_legacy_ctxbitmap_init(dev);

	if (drm_core_check_feature(dev, DRIVER_GEM)) {
		ret = drm_gem_init(dev);
		if (ret) {
			DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
			goto err_ctxbitmap;
		}
	}

	/* Use the parent device name as DRM device unique identifier, but fall
	 * back to the driver name for virtual devices like vgem. */
	ret = drm_dev_set_unique(dev, parent ? dev_name(parent) : driver->name);
	if (ret)
		goto err_setunique;

	return 0;

err_setunique:
	if (drm_core_check_feature(dev, DRIVER_GEM))
		drm_gem_destroy(dev);
err_ctxbitmap:
	drm_legacy_ctxbitmap_cleanup(dev);
	drm_ht_remove(&dev->map_hash);
err_minors:
	drm_minor_free(dev, DRM_MINOR_PRIMARY);
	drm_minor_free(dev, DRM_MINOR_RENDER);
	drm_minor_free(dev, DRM_MINOR_CONTROL);
	drm_fs_inode_free(dev->anon_inode);
err_free:
	mutex_destroy(&dev->master_mutex);
	return ret;
}