static int rcar_du_probe(struct platform_device *pdev) { struct rcar_du_device *rcdu; struct drm_device *ddev; struct resource *mem; int ret; /* Allocate and initialize the R-Car device structure. */ rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL); if (rcdu == NULL) return -ENOMEM; rcdu->dev = &pdev->dev; rcdu->info = of_device_get_match_data(rcdu->dev); 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)) return PTR_ERR(rcdu->mmio); /* DRM/KMS objects */ ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); if (IS_ERR(ddev)) return PTR_ERR(ddev); rcdu->ddev = ddev; ddev->dev_private = rcdu; ret = rcar_du_modeset_init(rcdu); if (ret < 0) { if (ret != -EPROBE_DEFER) 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; DRM_INFO("Device %s probed\n", dev_name(&pdev->dev)); drm_fbdev_generic_setup(ddev, 32); return 0; error: rcar_du_remove(pdev); return ret; }
static int kirin_drm_bind(struct device *dev) { struct drm_driver *driver = &kirin_drm_driver; struct drm_device *drm_dev; int ret; drm_dev = drm_dev_alloc(driver, dev); if (IS_ERR(drm_dev)) return PTR_ERR(drm_dev); ret = kirin_drm_kms_init(drm_dev); if (ret) goto err_drm_dev_unref; ret = drm_dev_register(drm_dev, 0); if (ret) goto err_kms_cleanup; return 0; err_kms_cleanup: kirin_drm_kms_cleanup(drm_dev); err_drm_dev_unref: drm_dev_unref(drm_dev); return ret; }
static int drm_get_platform_dev(struct platform_device *platdev, struct drm_driver *driver) { struct drm_device *dev; int ret; DRM_DEBUG("\n"); dev = drm_dev_alloc(driver, &platdev->dev); if (!dev) return -ENOMEM; dev->platformdev = platdev; ret = drm_dev_register(dev, 0); if (ret) goto err_free; DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->primary->index); return 0; err_free: drm_dev_unref(dev); return ret; }
static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev, const struct drm_framebuffer_funcs *fb_funcs, struct drm_driver *driver) { struct drm_device *drm; mutex_init(&tdev->dirty_lock); tdev->fb_funcs = fb_funcs; /* * We don't embed drm_device, because that prevent us from using * devm_kzalloc() to allocate tinydrm_device in the driver since * drm_dev_unref() frees the structure. The devm_ functions provide * for easy error handling. */ drm = drm_dev_alloc(driver, parent); if (IS_ERR(drm)) return PTR_ERR(drm); tdev->drm = drm; drm->dev_private = tdev; drm_mode_config_init(drm); drm->mode_config.funcs = &tinydrm_mode_config_funcs; return 0; }
static int stm_drm_platform_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct drm_device *ddev; int ret; DRM_DEBUG("%s\n", __func__); dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); ddev = drm_dev_alloc(&drv_driver, dev); if (IS_ERR(ddev)) return PTR_ERR(ddev); ret = drv_load(ddev); if (ret) goto err_put; ret = drm_dev_register(ddev, 0); if (ret) goto err_put; drm_fbdev_generic_setup(ddev, 16); return 0; err_put: drm_dev_put(ddev); return ret; }
static int atmel_hlcdc_dc_drm_probe(struct platform_device *pdev) { struct drm_device *ddev; int ret; ddev = drm_dev_alloc(&atmel_hlcdc_dc_driver, &pdev->dev); if (!ddev) return -ENOMEM; ret = atmel_hlcdc_dc_load(ddev); if (ret) goto err_unref; ret = drm_dev_register(ddev, 0); if (ret) goto err_unload; return 0; err_unload: atmel_hlcdc_dc_unload(ddev); err_unref: drm_dev_unref(ddev); return ret; }
static int arcpgu_probe(struct platform_device *pdev) { struct drm_device *drm; int ret; drm = drm_dev_alloc(&arcpgu_drm_driver, &pdev->dev); if (!drm) return -ENOMEM; ret = arcpgu_load(drm); if (ret) goto err_unref; ret = drm_dev_register(drm, 0); if (ret) goto err_unload; return 0; err_unload: arcpgu_unload(drm); err_unref: drm_dev_unref(drm); return ret; }
int drm_get_usb_dev(struct usb_interface *interface, const struct usb_device_id *id, struct drm_driver *driver) { struct drm_device *dev; int ret; DRM_DEBUG("\n"); dev = drm_dev_alloc(driver, &interface->dev); if (!dev) return -ENOMEM; dev->usbdev = interface_to_usbdev(interface); usb_set_intfdata(interface, dev); ret = drm_dev_register(dev, 0); if (ret) goto err_free; DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->primary->index); return 0; err_free: drm_dev_unref(dev); return ret; }
static int mxsfb_probe(struct platform_device *pdev) { struct drm_device *drm; const struct of_device_id *of_id = of_match_device(mxsfb_dt_ids, &pdev->dev); int ret; if (!pdev->dev.of_node) return -ENODEV; if (of_id) pdev->id_entry = of_id->data; drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev); if (!drm) return -ENOMEM; ret = mxsfb_load(drm, 0); if (ret) goto err_free; ret = drm_dev_register(drm, 0); if (ret) goto err_unload; return 0; err_unload: mxsfb_unload(drm); err_free: drm_dev_unref(drm); return ret; }
/* * Platform driver: */ static int etnaviv_bind(struct device *dev) { struct etnaviv_drm_private *priv; struct drm_device *drm; int ret; drm = drm_dev_alloc(&etnaviv_drm_driver, dev); if (!drm) return -ENOMEM; drm->platformdev = to_platform_device(dev); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(dev, "failed to allocate private data\n"); ret = -ENOMEM; goto out_unref; } drm->dev_private = priv; priv->wq = alloc_ordered_workqueue("etnaviv", 0); if (!priv->wq) { ret = -ENOMEM; goto out_wq; } mutex_init(&priv->gem_lock); INIT_LIST_HEAD(&priv->gem_list); priv->num_gpus = 0; dev_set_drvdata(dev, drm); ret = component_bind_all(dev, drm); if (ret < 0) goto out_bind; load_gpu(drm); ret = drm_dev_register(drm, 0); if (ret) goto out_register; return 0; out_register: component_unbind_all(dev, drm); out_bind: flush_workqueue(priv->wq); destroy_workqueue(priv->wq); out_wq: kfree(priv); out_unref: drm_dev_unref(drm); return ret; }
static int exynos_drm_bind(struct device *dev) { struct exynos_drm_private *private; struct drm_encoder *encoder; struct drm_device *drm; unsigned int clone_mask; int cnt, ret; drm = drm_dev_alloc(&exynos_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
static int vc4_drm_bind(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm; struct vc4_dev *vc4; int ret = 0; dev->coherent_dma_mask = DMA_BIT_MASK(32); vc4 = devm_kzalloc(dev, sizeof(*vc4), GFP_KERNEL); if (!vc4) return -ENOMEM; drm = drm_dev_alloc(&vc4_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); platform_set_drvdata(pdev, drm); vc4->dev = drm; drm->dev_private = vc4; ret = vc4_bo_cache_init(drm); if (ret) goto dev_unref; drm_mode_config_init(drm); vc4_gem_init(drm); ret = component_bind_all(dev, drm); if (ret) goto gem_destroy; vc4_kick_out_firmware_fb(); ret = drm_dev_register(drm, 0); if (ret < 0) goto unbind_all; vc4_kms_load(drm); return 0; unbind_all: component_unbind_all(dev, drm); gem_destroy: vc4_gem_destroy(drm); vc4_bo_cache_destroy(drm); dev_unref: drm_dev_unref(drm); return ret; }
static int pl111_amba_probe(struct amba_device *amba_dev, const struct amba_id *id) { struct device *dev = &amba_dev->dev; struct pl111_drm_dev_private *priv; struct drm_device *drm; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; drm = drm_dev_alloc(&pl111_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); amba_set_drvdata(amba_dev, drm); priv->drm = drm; drm->dev_private = priv; priv->regs = devm_ioremap_resource(dev, &amba_dev->res); if (IS_ERR(priv->regs)) { dev_err(dev, "%s failed mmio\n", __func__); return PTR_ERR(priv->regs); } /* turn off interrupts before requesting the irq */ writel(0, priv->regs + CLCD_PL111_IENB); ret = devm_request_irq(dev, amba_dev->irq[0], pl111_irq, 0, "pl111", priv); if (ret != 0) { dev_err(dev, "%s failed irq %d\n", __func__, ret); return ret; } ret = pl111_modeset_init(drm); if (ret != 0) goto dev_unref; ret = drm_dev_register(drm, 0); if (ret < 0) goto dev_unref; return 0; dev_unref: drm_dev_unref(drm); return ret; }
/* * Platform driver: */ static int etnaviv_bind(struct device *dev) { struct etnaviv_drm_private *priv; struct drm_device *drm; int ret; drm = drm_dev_alloc(&etnaviv_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(dev, "failed to allocate private data\n"); ret = -ENOMEM; goto out_unref; } drm->dev_private = priv; mutex_init(&priv->gem_lock); INIT_LIST_HEAD(&priv->gem_list); priv->num_gpus = 0; dev_set_drvdata(dev, drm); ret = component_bind_all(dev, drm); if (ret < 0) goto out_bind; load_gpu(drm); ret = drm_dev_register(drm, 0); if (ret) goto out_register; return 0; out_register: component_unbind_all(dev, drm); out_bind: kfree(priv); out_unref: drm_dev_unref(drm); return ret; }
static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct drm_device *dev; unsigned long fbsize; int ret; fbsize = pci_resource_len(pdev, 0); if (fbsize < 4 * 1024 * 1024) { DRM_ERROR("less than 4 MB video memory, ignoring device\n"); return -ENOMEM; } ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "bochsdrmfb"); if (ret) return ret; dev = drm_dev_alloc(&bochs_driver, &pdev->dev); if (IS_ERR(dev)) return PTR_ERR(dev); ret = pci_enable_device(pdev); if (ret) goto err_free_dev; dev->pdev = pdev; pci_set_drvdata(pdev, dev); ret = bochs_load(dev); if (ret) goto err_free_dev; ret = drm_dev_register(dev, 0); if (ret) goto err_unload; return ret; err_unload: bochs_unload(dev); err_free_dev: drm_dev_put(dev); return ret; }
static int virtio_gpu_probe(struct virtio_device *vdev) { struct drm_device *dev; int ret; if (vgacon_text_force() && virtio_gpu_modeset == -1) return -EINVAL; if (virtio_gpu_modeset == 0) return -EINVAL; dev = drm_dev_alloc(&driver, &vdev->dev); if (IS_ERR(dev)) return PTR_ERR(dev); vdev->priv = dev; if (!strcmp(vdev->dev.parent->bus->name, "pci")) { ret = virtio_gpu_pci_quirk(dev, vdev); if (ret) goto err_free; } ret = virtio_gpu_init(dev); if (ret) goto err_free; ret = drm_dev_register(dev, 0); if (ret) goto err_free; drm_fbdev_generic_setup(vdev->priv, 32); return 0; err_free: drm_dev_put(dev); return ret; }
int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev) { struct drm_device *dev; int ret; dev = drm_dev_alloc(driver, &vdev->dev); if (IS_ERR(dev)) return PTR_ERR(dev); dev->virtdev = vdev; vdev->priv = dev; if (strcmp(vdev->dev.parent->bus->name, "pci") == 0) { struct pci_dev *pdev = to_pci_dev(vdev->dev.parent); bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA; DRM_INFO("pci: %s detected\n", vga ? "virtio-vga" : "virtio-gpu-pci"); dev->pdev = pdev; if (vga) virtio_pci_kick_out_firmware_fb(pdev); } ret = drm_dev_register(dev, 0); if (ret) goto err_free; DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->primary->index); return 0; err_free: drm_dev_unref(dev); return ret; }
static int udl_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(interface); struct drm_device *dev; int r; dev = drm_dev_alloc(&driver, &interface->dev); if (!dev) return -ENOMEM; r = drm_dev_register(dev, (unsigned long)udev); if (r) goto err_free; usb_set_intfdata(interface, dev); DRM_INFO("Initialized udl on minor %d\n", dev->primary->index); return 0; err_free: drm_dev_unref(dev); return r; }
static int imx_drm_bind(struct device *dev) { struct drm_device *drm; int ret; drm = drm_dev_alloc(&imx_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); /* * enable drm irq mode. * - with irq_enabled = true, we can use the vblank feature. * * P.S. note that we wouldn't use drm irq handler but * just specific driver own one instead because * drm framework supports only one irq handler and * drivers can well take care of their interrupts */ drm->irq_enabled = true; /* * set max width and height as default value(4096x4096). * this value would be used to check framebuffer size limitation * at drm_mode_addfb(). */ drm->mode_config.min_width = 1; drm->mode_config.min_height = 1; drm->mode_config.max_width = 4096; drm->mode_config.max_height = 4096; drm->mode_config.funcs = &imx_drm_mode_config_funcs; drm->mode_config.helper_private = &imx_drm_mode_config_helpers; drm->mode_config.allow_fb_modifiers = true; drm_mode_config_init(drm); ret = drm_vblank_init(drm, MAX_CRTC); if (ret) goto err_kms; dev_set_drvdata(dev, drm); /* Now try and bind all our sub-components */ ret = component_bind_all(dev, drm); if (ret) goto err_kms; drm_mode_config_reset(drm); /* * All components are now initialised, so setup the fb helper. * The fb helper takes copies of key hardware information, so the * crtcs/connectors/encoders must not change after this point. */ if (legacyfb_depth != 16 && legacyfb_depth != 32) { dev_warn(dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); legacyfb_depth = 16; } drm_kms_helper_poll_init(drm); ret = drm_dev_register(drm, 0); if (ret) goto err_poll_fini; drm_fbdev_generic_setup(drm, legacyfb_depth); return 0; err_poll_fini: drm_kms_helper_poll_fini(drm); component_unbind_all(drm->dev, drm); err_kms: drm_mode_config_cleanup(drm); drm_dev_put(drm); return ret; }
static int fsl_dcu_drm_probe(struct platform_device *pdev) { struct fsl_dcu_drm_device *fsl_dev; struct drm_device *drm; struct device *dev = &pdev->dev; struct resource *res; void __iomem *base; struct drm_driver *driver = &fsl_dcu_drm_driver; struct clk *pix_clk_in; char pix_clk_name[32]; const char *pix_clk_in_name; const struct of_device_id *id; int ret; u8 div_ratio_shift = 0; fsl_dev = devm_kzalloc(dev, sizeof(*fsl_dev), GFP_KERNEL); if (!fsl_dev) return -ENOMEM; id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node); if (!id) return -ENODEV; fsl_dev->soc = id->data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) { ret = PTR_ERR(base); return ret; } fsl_dev->irq = platform_get_irq(pdev, 0); if (fsl_dev->irq < 0) { dev_err(dev, "failed to get irq\n"); return fsl_dev->irq; } fsl_dev->regmap = devm_regmap_init_mmio(dev, base, &fsl_dcu_regmap_config); if (IS_ERR(fsl_dev->regmap)) { dev_err(dev, "regmap init failed\n"); return PTR_ERR(fsl_dev->regmap); } fsl_dev->clk = devm_clk_get(dev, "dcu"); if (IS_ERR(fsl_dev->clk)) { dev_err(dev, "failed to get dcu clock\n"); return PTR_ERR(fsl_dev->clk); } ret = clk_prepare_enable(fsl_dev->clk); if (ret < 0) { dev_err(dev, "failed to enable dcu clk\n"); return ret; } pix_clk_in = devm_clk_get(dev, "pix"); if (IS_ERR(pix_clk_in)) { /* legancy binding, use dcu clock as pixel clock input */ pix_clk_in = fsl_dev->clk; } if (of_property_read_bool(dev->of_node, "big-endian")) div_ratio_shift = 24; pix_clk_in_name = __clk_get_name(pix_clk_in); snprintf(pix_clk_name, sizeof(pix_clk_name), "%s_pix", pix_clk_in_name); fsl_dev->pix_clk = clk_register_divider(dev, pix_clk_name, pix_clk_in_name, 0, base + DCU_DIV_RATIO, div_ratio_shift, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL); if (IS_ERR(fsl_dev->pix_clk)) { dev_err(dev, "failed to register pix clk\n"); ret = PTR_ERR(fsl_dev->pix_clk); goto disable_clk; } fsl_dev->tcon = fsl_tcon_init(dev); drm = drm_dev_alloc(driver, dev); if (IS_ERR(drm)) { ret = PTR_ERR(drm); goto unregister_pix_clk; } fsl_dev->dev = dev; fsl_dev->drm = drm; fsl_dev->np = dev->of_node; drm->dev_private = fsl_dev; dev_set_drvdata(dev, fsl_dev); ret = drm_dev_register(drm, 0); if (ret < 0) goto unref; return 0; unref: drm_dev_unref(drm); unregister_pix_clk: clk_unregister(fsl_dev->pix_clk); disable_clk: clk_disable_unprepare(fsl_dev->clk); return ret; }
static int sun4i_drv_bind(struct device *dev) { struct drm_device *drm; struct sun4i_drv *drv; int ret; drm = drm_dev_alloc(&sun4i_drv_driver, dev); if (!drm) return -ENOMEM; drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); if (!drv) { ret = -ENOMEM; goto free_drm; } drm->dev_private = drv; drm_vblank_init(drm, 1); drm_mode_config_init(drm); ret = component_bind_all(drm->dev, drm); if (ret) { dev_err(drm->dev, "Couldn't bind all pipelines components\n"); goto free_drm; } /* Create our layers */ drv->layers = sun4i_layers_init(drm); if (!drv->layers) { dev_err(drm->dev, "Couldn't create the planes\n"); ret = -EINVAL; goto free_drm; } /* Create our CRTC */ drv->crtc = sun4i_crtc_init(drm); if (!drv->crtc) { dev_err(drm->dev, "Couldn't create the CRTC\n"); ret = -EINVAL; goto free_drm; } drm->irq_enabled = true; /* Remove early framebuffers (ie. simplefb) */ sun4i_remove_framebuffers(); /* Create our framebuffer */ drv->fbdev = sun4i_framebuffer_init(drm); if (IS_ERR(drv->fbdev)) { dev_err(drm->dev, "Couldn't create our framebuffer\n"); ret = PTR_ERR(drv->fbdev); goto free_drm; } /* Enable connectors polling */ drm_kms_helper_poll_init(drm); ret = drm_dev_register(drm, 0); if (ret) goto free_drm; return 0; free_drm: drm_dev_unref(drm); return ret; }
static int sun4i_drv_bind(struct device *dev) { struct drm_device *drm; struct sun4i_drv *drv; int ret; drm = drm_dev_alloc(&sun4i_drv_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); if (!drv) { ret = -ENOMEM; goto free_drm; } dev_set_drvdata(dev, drm); drm->dev_private = drv; INIT_LIST_HEAD(&drv->frontend_list); INIT_LIST_HEAD(&drv->engine_list); INIT_LIST_HEAD(&drv->tcon_list); ret = of_reserved_mem_device_init(dev); if (ret && ret != -ENODEV) { dev_err(drm->dev, "Couldn't claim our memory region\n"); goto free_drm; } drm_mode_config_init(drm); drm->mode_config.allow_fb_modifiers = true; ret = component_bind_all(drm->dev, drm); if (ret) { dev_err(drm->dev, "Couldn't bind all pipelines components\n"); goto cleanup_mode_config; } /* drm_vblank_init calls kcalloc, which can fail */ ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret) goto cleanup_mode_config; drm->irq_enabled = true; /* Remove early framebuffers (ie. simplefb) */ drm_fb_helper_remove_conflicting_framebuffers(NULL, "sun4i-drm-fb", false); sun4i_framebuffer_init(drm); /* Enable connectors polling */ drm_kms_helper_poll_init(drm); ret = drm_dev_register(drm, 0); if (ret) goto finish_poll; drm_fbdev_generic_setup(drm, 32); return 0; finish_poll: drm_kms_helper_poll_fini(drm); cleanup_mode_config: drm_mode_config_cleanup(drm); of_reserved_mem_device_release(dev); free_drm: drm_dev_put(drm); return ret; }
static int hdlcd_drm_bind(struct device *dev) { struct drm_device *drm; struct hdlcd_drm_private *hdlcd; int ret; hdlcd = devm_kzalloc(dev, sizeof(*hdlcd), GFP_KERNEL); if (!hdlcd) return -ENOMEM; drm = drm_dev_alloc(&hdlcd_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); drm->dev_private = hdlcd; dev_set_drvdata(dev, drm); hdlcd_setup_mode_config(drm); ret = hdlcd_load(drm, 0); if (ret) goto err_free; ret = drm_dev_register(drm, 0); if (ret) goto err_unload; ret = component_bind_all(dev, drm); if (ret) { DRM_ERROR("Failed to bind all components\n"); goto err_unregister; } ret = pm_runtime_set_active(dev); if (ret) goto err_pm_active; pm_runtime_enable(dev); ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret < 0) { DRM_ERROR("failed to initialise vblank\n"); goto err_vblank; } drm_mode_config_reset(drm); drm_kms_helper_poll_init(drm); hdlcd->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, drm->mode_config.num_connector); if (IS_ERR(hdlcd->fbdev)) { ret = PTR_ERR(hdlcd->fbdev); hdlcd->fbdev = NULL; goto err_fbdev; } return 0; err_fbdev: drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); drm_vblank_cleanup(drm); err_vblank: pm_runtime_disable(drm->dev); err_pm_active: component_unbind_all(dev, drm); err_unregister: drm_dev_unregister(drm); err_unload: drm_irq_uninstall(drm); of_reserved_mem_device_release(drm->dev); err_free: dev_set_drvdata(dev, NULL); drm_dev_unref(drm); return ret; }
static int sun4i_drv_bind(struct device *dev) { struct drm_device *drm; struct sun4i_drv *drv; int ret; drm = drm_dev_alloc(&sun4i_drv_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); if (!drv) { ret = -ENOMEM; goto free_drm; } drm->dev_private = drv; ret = of_reserved_mem_device_init(dev); if (ret && ret != -ENODEV) { dev_err(drm->dev, "Couldn't claim our memory region\n"); goto free_drm; } /* drm_vblank_init calls kcalloc, which can fail */ ret = drm_vblank_init(drm, 1); if (ret) goto free_mem_region; drm_mode_config_init(drm); ret = component_bind_all(drm->dev, drm); if (ret) { dev_err(drm->dev, "Couldn't bind all pipelines components\n"); goto cleanup_mode_config; } drm->irq_enabled = true; /* Remove early framebuffers (ie. simplefb) */ sun4i_remove_framebuffers(); /* Create our framebuffer */ drv->fbdev = sun4i_framebuffer_init(drm); if (IS_ERR(drv->fbdev)) { dev_err(drm->dev, "Couldn't create our framebuffer\n"); ret = PTR_ERR(drv->fbdev); goto cleanup_mode_config; } /* Enable connectors polling */ drm_kms_helper_poll_init(drm); ret = drm_dev_register(drm, 0); if (ret) goto finish_poll; return 0; finish_poll: drm_kms_helper_poll_fini(drm); sun4i_framebuffer_free(drm); cleanup_mode_config: drm_mode_config_cleanup(drm); drm_vblank_cleanup(drm); free_mem_region: of_reserved_mem_device_release(dev); free_drm: drm_dev_unref(drm); return ret; }
static int fsl_dcu_drm_probe(struct platform_device *pdev) { struct fsl_dcu_drm_device *fsl_dev; struct drm_device *drm; struct device *dev = &pdev->dev; struct resource *res; void __iomem *base; struct drm_driver *driver = &fsl_dcu_drm_driver; struct clk *pix_clk_in; char pix_clk_name[32]; const char *pix_clk_in_name; const struct of_device_id *id; int ret; fsl_dev = devm_kzalloc(dev, sizeof(*fsl_dev), GFP_KERNEL); if (!fsl_dev) return -ENOMEM; id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node); if (!id) return -ENODEV; fsl_dev->soc = id->data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "could not get memory IO resource\n"); return -ENODEV; } base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) { ret = PTR_ERR(base); return ret; } fsl_dev->irq = platform_get_irq(pdev, 0); if (fsl_dev->irq < 0) { dev_err(dev, "failed to get irq\n"); return -ENXIO; } fsl_dev->regmap = devm_regmap_init_mmio(dev, base, &fsl_dcu_regmap_config); if (IS_ERR(fsl_dev->regmap)) { dev_err(dev, "regmap init failed\n"); return PTR_ERR(fsl_dev->regmap); } fsl_dev->clk = devm_clk_get(dev, "dcu"); if (IS_ERR(fsl_dev->clk)) { dev_err(dev, "failed to get dcu clock\n"); return PTR_ERR(fsl_dev->clk); } ret = clk_prepare_enable(fsl_dev->clk); if (ret < 0) { dev_err(dev, "failed to enable dcu clk\n"); return ret; } pix_clk_in = devm_clk_get(dev, "pix"); if (IS_ERR(pix_clk_in)) { /* legancy binding, use dcu clock as pixel clock input */ pix_clk_in = fsl_dev->clk; } pix_clk_in_name = __clk_get_name(pix_clk_in); snprintf(pix_clk_name, sizeof(pix_clk_name), "%s_pix", pix_clk_in_name); fsl_dev->pix_clk = clk_register_divider(dev, pix_clk_name, pix_clk_in_name, 0, base + DCU_DIV_RATIO, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL); if (IS_ERR(fsl_dev->pix_clk)) { dev_err(dev, "failed to register pix clk\n"); ret = PTR_ERR(fsl_dev->pix_clk); goto disable_clk; } ret = clk_prepare_enable(fsl_dev->pix_clk); if (ret < 0) { dev_err(dev, "failed to enable pix clk\n"); goto unregister_pix_clk; } fsl_dev->tcon = fsl_tcon_init(dev); drm = drm_dev_alloc(driver, dev); if (!drm) { ret = -ENOMEM; goto disable_pix_clk; } fsl_dev->dev = dev; fsl_dev->drm = drm; fsl_dev->np = dev->of_node; drm->dev_private = fsl_dev; dev_set_drvdata(dev, fsl_dev); ret = drm_dev_register(drm, 0); if (ret < 0) goto unref; DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, drm->primary->index); return 0; unref: drm_dev_unref(drm); disable_pix_clk: clk_disable_unprepare(fsl_dev->pix_clk); unregister_pix_clk: clk_unregister(fsl_dev->pix_clk); disable_clk: clk_disable_unprepare(fsl_dev->clk); return ret; }
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; }
static int pl111_amba_probe(struct amba_device *amba_dev, const struct amba_id *id) { struct device *dev = &amba_dev->dev; struct pl111_drm_dev_private *priv; struct pl111_variant_data *variant = id->data; struct drm_device *drm; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; drm = drm_dev_alloc(&pl111_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); amba_set_drvdata(amba_dev, drm); priv->drm = drm; drm->dev_private = priv; priv->variant = variant; /* * The PL110 and PL111 variants have two registers * swapped: interrupt enable and control. For this reason * we use offsets that we can change per variant. */ if (variant->is_pl110) { /* * The ARM Versatile boards are even more special: * their PrimeCell ID say they are PL110 but the * control and interrupt enable registers are anyway * swapped to the PL111 order so they are not following * the PL110 datasheet. */ if (of_machine_is_compatible("arm,versatile-ab") || of_machine_is_compatible("arm,versatile-pb")) { priv->ienb = CLCD_PL111_IENB; priv->ctrl = CLCD_PL111_CNTL; } else { priv->ienb = CLCD_PL110_IENB; priv->ctrl = CLCD_PL110_CNTL; } } else { priv->ienb = CLCD_PL111_IENB; priv->ctrl = CLCD_PL111_CNTL; } priv->regs = devm_ioremap_resource(dev, &amba_dev->res); if (IS_ERR(priv->regs)) { dev_err(dev, "%s failed mmio\n", __func__); return PTR_ERR(priv->regs); } /* turn off interrupts before requesting the irq */ writel(0, priv->regs + priv->ienb); ret = devm_request_irq(dev, amba_dev->irq[0], pl111_irq, 0, variant->name, priv); if (ret != 0) { dev_err(dev, "%s failed irq %d\n", __func__, ret); return ret; } ret = pl111_versatile_init(dev, priv); if (ret) goto dev_unref; ret = pl111_modeset_init(drm); if (ret != 0) goto dev_unref; ret = drm_dev_register(drm, 0); if (ret < 0) goto dev_unref; return 0; dev_unref: drm_dev_unref(drm); return ret; }
static int pdev_probe(struct platform_device *pdev) { const struct soc_device_attribute *soc; struct omap_drm_private *priv; struct drm_device *ddev; unsigned int i; int ret; DBG("%s", pdev->name); if (omapdss_is_initialized() == false) return -EPROBE_DEFER; ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) { dev_err(&pdev->dev, "Failed to set the DMA mask\n"); return ret; } omap_crtc_pre_init(); ret = omap_connect_dssdevs(); if (ret) goto err_crtc_uninit; /* Allocate and initialize the driver private structure. */ priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; goto err_disconnect_dssdevs; } priv->dispc_ops = dispc_get_ops(); soc = soc_device_match(omapdrm_soc_devices); priv->omaprev = soc ? (unsigned int)soc->data : 0; priv->wq = alloc_ordered_workqueue("omapdrm", 0); spin_lock_init(&priv->list_lock); INIT_LIST_HEAD(&priv->obj_list); /* Allocate and initialize the DRM device. */ ddev = drm_dev_alloc(&omap_drm_driver, &pdev->dev); if (IS_ERR(ddev)) { ret = PTR_ERR(ddev); goto err_free_priv; } ddev->dev_private = priv; platform_set_drvdata(pdev, ddev); /* Get memory bandwidth limits */ if (priv->dispc_ops->get_memory_bandwidth_limit) priv->max_bandwidth = priv->dispc_ops->get_memory_bandwidth_limit(); omap_gem_init(ddev); ret = omap_modeset_init(ddev); if (ret) { dev_err(&pdev->dev, "omap_modeset_init failed: ret=%d\n", ret); goto err_free_drm_dev; } /* Initialize vblank handling, start with all CRTCs disabled. */ ret = drm_vblank_init(ddev, priv->num_crtcs); if (ret) { dev_err(&pdev->dev, "could not init vblank\n"); goto err_cleanup_modeset; } for (i = 0; i < priv->num_crtcs; i++) drm_crtc_vblank_off(priv->crtcs[i]); priv->fbdev = omap_fbdev_init(ddev); drm_kms_helper_poll_init(ddev); omap_modeset_enable_external_hpd(); /* * Register the DRM device with the core and the connectors with * sysfs. */ ret = drm_dev_register(ddev, 0); if (ret) goto err_cleanup_helpers; return 0; err_cleanup_helpers: omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev); if (priv->fbdev) omap_fbdev_free(ddev); err_cleanup_modeset: drm_mode_config_cleanup(ddev); omap_drm_irq_uninstall(ddev); err_free_drm_dev: omap_gem_deinit(ddev); drm_dev_unref(ddev); err_free_priv: destroy_workqueue(priv->wq); kfree(priv); err_disconnect_dssdevs: omap_disconnect_dssdevs(); err_crtc_uninit: omap_crtc_pre_uninit(); return ret; }
static int fsl_dcu_drm_probe(struct platform_device *pdev) { struct fsl_dcu_drm_device *fsl_dev; struct drm_device *drm; struct device *dev = &pdev->dev; struct resource *res; void __iomem *base; struct drm_driver *driver = &fsl_dcu_drm_driver; const struct of_device_id *id; int ret; fsl_dev = devm_kzalloc(dev, sizeof(*fsl_dev), GFP_KERNEL); if (!fsl_dev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "could not get memory IO resource\n"); return -ENODEV; } base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) { ret = PTR_ERR(base); return ret; } fsl_dev->irq = platform_get_irq(pdev, 0); if (fsl_dev->irq < 0) { dev_err(dev, "failed to get irq\n"); return -ENXIO; } fsl_dev->clk = devm_clk_get(dev, "dcu"); if (IS_ERR(fsl_dev->clk)) { ret = PTR_ERR(fsl_dev->clk); dev_err(dev, "failed to get dcu clock\n"); return ret; } ret = clk_prepare(fsl_dev->clk); if (ret < 0) { dev_err(dev, "failed to prepare dcu clk\n"); return ret; } ret = clk_enable(fsl_dev->clk); if (ret < 0) { dev_err(dev, "failed to enable dcu clk\n"); clk_unprepare(fsl_dev->clk); return ret; } fsl_dev->regmap = devm_regmap_init_mmio(dev, base, &fsl_dcu_regmap_config); if (IS_ERR(fsl_dev->regmap)) { dev_err(dev, "regmap init failed\n"); return PTR_ERR(fsl_dev->regmap); } id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node); if (!id) return -ENODEV; fsl_dev->soc = id->data; drm = drm_dev_alloc(driver, dev); if (!drm) return -ENOMEM; fsl_dev->dev = dev; fsl_dev->drm = drm; fsl_dev->np = dev->of_node; drm->dev_private = fsl_dev; dev_set_drvdata(dev, fsl_dev); ret = drm_dev_register(drm, 0); if (ret < 0) goto unref; DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, drm->primary->index); return 0; unref: drm_dev_unref(drm); return ret; }
static int malidp_bind(struct device *dev) { struct resource *res; struct drm_device *drm; struct device_node *ep; struct malidp_drm *malidp; struct malidp_hw_device *hwdev; struct platform_device *pdev = to_platform_device(dev); /* number of lines for the R, G and B output */ u8 output_width[MAX_OUTPUT_CHANNELS]; int ret = 0, i; u32 version, out_depth = 0; malidp = devm_kzalloc(dev, sizeof(*malidp), GFP_KERNEL); if (!malidp) return -ENOMEM; hwdev = devm_kzalloc(dev, sizeof(*hwdev), GFP_KERNEL); if (!hwdev) return -ENOMEM; /* * copy the associated data from malidp_drm_of_match to avoid * having to keep a reference to the OF node after binding */ memcpy(hwdev, of_device_get_match_data(dev), sizeof(*hwdev)); malidp->dev = hwdev; INIT_LIST_HEAD(&malidp->event_list); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hwdev->regs = devm_ioremap_resource(dev, res); if (IS_ERR(hwdev->regs)) return PTR_ERR(hwdev->regs); hwdev->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(hwdev->pclk)) return PTR_ERR(hwdev->pclk); hwdev->aclk = devm_clk_get(dev, "aclk"); if (IS_ERR(hwdev->aclk)) return PTR_ERR(hwdev->aclk); hwdev->mclk = devm_clk_get(dev, "mclk"); if (IS_ERR(hwdev->mclk)) return PTR_ERR(hwdev->mclk); hwdev->pxlclk = devm_clk_get(dev, "pxlclk"); if (IS_ERR(hwdev->pxlclk)) return PTR_ERR(hwdev->pxlclk); /* Get the optional framebuffer memory resource */ ret = of_reserved_mem_device_init(dev); if (ret && ret != -ENODEV) return ret; drm = drm_dev_alloc(&malidp_driver, dev); if (IS_ERR(drm)) { ret = PTR_ERR(drm); goto alloc_fail; } /* Enable APB clock in order to get access to the registers */ clk_prepare_enable(hwdev->pclk); /* * Enable AXI clock and main clock so that prefetch can start once * the registers are set */ clk_prepare_enable(hwdev->aclk); clk_prepare_enable(hwdev->mclk); ret = hwdev->query_hw(hwdev); if (ret) { DRM_ERROR("Invalid HW configuration\n"); goto query_hw_fail; } version = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_DE_CORE_ID); DRM_INFO("found ARM Mali-DP%3x version r%dp%d\n", version >> 16, (version >> 12) & 0xf, (version >> 8) & 0xf); /* set the number of lines used for output of RGB data */ ret = of_property_read_u8_array(dev->of_node, "arm,malidp-output-port-lines", output_width, MAX_OUTPUT_CHANNELS); if (ret) goto query_hw_fail; for (i = 0; i < MAX_OUTPUT_CHANNELS; i++) out_depth = (out_depth << 8) | (output_width[i] & 0xf); malidp_hw_write(hwdev, out_depth, hwdev->map.out_depth_base); drm->dev_private = malidp; dev_set_drvdata(dev, drm); atomic_set(&malidp->config_valid, 0); init_waitqueue_head(&malidp->wq); ret = malidp_init(drm); if (ret < 0) goto init_fail; ret = drm_dev_register(drm, 0); if (ret) goto register_fail; /* Set the CRTC's port so that the encoder component can find it */ ep = of_graph_get_next_endpoint(dev->of_node, NULL); if (!ep) { ret = -EINVAL; goto port_fail; } malidp->crtc.port = of_get_next_parent(ep); ret = component_bind_all(dev, drm); if (ret) { DRM_ERROR("Failed to bind all components\n"); goto bind_fail; } ret = malidp_irq_init(pdev); if (ret < 0) goto irq_init_fail; ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret < 0) { DRM_ERROR("failed to initialise vblank\n"); goto vblank_fail; } drm_mode_config_reset(drm); malidp->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, drm->mode_config.num_connector); if (IS_ERR(malidp->fbdev)) { ret = PTR_ERR(malidp->fbdev); malidp->fbdev = NULL; goto fbdev_fail; } drm_kms_helper_poll_init(drm); return 0; fbdev_fail: drm_vblank_cleanup(drm); vblank_fail: malidp_se_irq_fini(drm); malidp_de_irq_fini(drm); irq_init_fail: component_unbind_all(dev, drm); bind_fail: of_node_put(malidp->crtc.port); malidp->crtc.port = NULL; port_fail: drm_dev_unregister(drm); register_fail: malidp_de_planes_destroy(drm); drm_mode_config_cleanup(drm); init_fail: drm->dev_private = NULL; dev_set_drvdata(dev, NULL); query_hw_fail: clk_disable_unprepare(hwdev->mclk); clk_disable_unprepare(hwdev->aclk); clk_disable_unprepare(hwdev->pclk); drm_dev_unref(drm); alloc_fail: of_reserved_mem_device_release(dev); return ret; }