Пример #1
0
static int hdac_component_master_bind(struct device *dev)
{
	struct i915_audio_component *acomp = hdac_acomp;
	int ret;

	ret = component_bind_all(dev, acomp);
	if (ret < 0)
		return ret;

	if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power &&
		      acomp->ops->put_power && acomp->ops->get_cdclk_freq))) {
		ret = -EINVAL;
		goto out_unbind;
	}

	/*
	 * Atm, we don't support dynamic unbinding initiated by the child
	 * component, so pin its containing module until we unbind.
	 */
	if (!try_module_get(acomp->ops->owner)) {
		ret = -ENODEV;
		goto out_unbind;
	}

	return 0;

out_unbind:
	component_unbind_all(dev, acomp);

	return ret;
}
Пример #2
0
static void malidp_unbind(struct device *dev)
{
	struct drm_device *drm = dev_get_drvdata(dev);
	struct malidp_drm *malidp = drm->dev_private;
	struct malidp_hw_device *hwdev = malidp->dev;

	if (malidp->fbdev) {
		drm_fbdev_cma_fini(malidp->fbdev);
		malidp->fbdev = NULL;
	}
	drm_kms_helper_poll_fini(drm);
	malidp_se_irq_fini(drm);
	malidp_de_irq_fini(drm);
	drm_vblank_cleanup(drm);
	component_unbind_all(dev, drm);
	of_node_put(malidp->crtc.port);
	malidp->crtc.port = NULL;
	drm_dev_unregister(drm);
	malidp_de_planes_destroy(drm);
	drm_mode_config_cleanup(drm);
	drm->dev_private = NULL;
	dev_set_drvdata(dev, NULL);
	clk_disable_unprepare(hwdev->mclk);
	clk_disable_unprepare(hwdev->aclk);
	clk_disable_unprepare(hwdev->pclk);
	drm_dev_unref(drm);
	of_reserved_mem_device_release(dev);
}
Пример #3
0
static int kirin_drm_kms_init(struct drm_device *dev)
{
	struct kirin_drm_private *priv;
	int ret;

	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	dev->dev_private = priv;
	dev_set_drvdata(dev->dev, dev);

	/* dev->mode_config initialization */
	drm_mode_config_init(dev);
	kirin_drm_mode_config_init(dev);

	/* display controller init */
	ret = dc_ops->init(to_platform_device(dev->dev));
	if (ret)
		goto err_mode_config_cleanup;

	/* bind and init sub drivers */
	ret = component_bind_all(dev->dev, dev);
	if (ret) {
		DRM_ERROR("failed to bind all component.\n");
		goto err_dc_cleanup;
	}

	/* vblank init */
	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
	if (ret) {
		DRM_ERROR("failed to initialize vblank.\n");
		goto err_unbind_all;
	}
	/* with irq_enabled = true, we can use the vblank feature. */
	dev->irq_enabled = true;

	/* reset all the states of crtc/plane/encoder/connector */
	drm_mode_config_reset(dev);

	/* init kms poll for handling hpd */
	drm_kms_helper_poll_init(dev);

	/* force detection after connectors init */
	(void)drm_helper_hpd_irq_event(dev);

	return 0;

err_unbind_all:
	component_unbind_all(dev->dev, dev);
err_dc_cleanup:
	dc_ops->cleanup(to_platform_device(dev->dev));
err_mode_config_cleanup:
	drm_mode_config_cleanup(dev);
	devm_kfree(dev->dev, priv);
	dev->dev_private = NULL;

	return ret;
}
Пример #4
0
static void hdac_component_master_unbind(struct device *dev)
{
	struct i915_audio_component *acomp = hdac_acomp;

	module_put(acomp->ops->owner);
	component_unbind_all(dev, acomp);
	WARN_ON(acomp->ops || acomp->dev);
}
Пример #5
0
/*
 * 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;
}
Пример #6
0
static void hdac_component_master_unbind(struct device *dev)
{
	struct drm_audio_component *acomp = hdac_get_acomp(dev);

	if (acomp->audio_ops && acomp->audio_ops->master_unbind)
		acomp->audio_ops->master_unbind(dev, acomp);
	module_put(acomp->ops->owner);
	component_unbind_all(dev, acomp);
	WARN_ON(acomp->ops || acomp->dev);
}
Пример #7
0
void komeda_kms_detach(struct komeda_kms_dev *kms)
{
	struct drm_device *drm = &kms->base;
	struct komeda_dev *mdev = drm->dev_private;

	drm_dev_unregister(drm);
	component_unbind_all(mdev->dev, drm);
	komeda_kms_cleanup_private_objs(mdev);
	drm_mode_config_cleanup(drm);
	drm->dev_private = NULL;
	drm_dev_put(drm);
}
Пример #8
0
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;
}
Пример #9
0
static void etnaviv_unbind(struct device *dev)
{
	struct drm_device *drm = dev_get_drvdata(dev);
	struct etnaviv_drm_private *priv = drm->dev_private;

	drm_dev_unregister(drm);

	component_unbind_all(dev, drm);

	drm->dev_private = NULL;
	kfree(priv);

	drm_dev_unref(drm);
}
Пример #10
0
static void sun4i_drv_unbind(struct device *dev)
{
	struct drm_device *drm = dev_get_drvdata(dev);

	drm_dev_unregister(drm);
	drm_kms_helper_poll_fini(drm);
	drm_atomic_helper_shutdown(drm);
	drm_mode_config_cleanup(drm);

	component_unbind_all(dev, NULL);
	of_reserved_mem_device_release(dev);

	drm_dev_put(drm);
}
Пример #11
0
static void imx_drm_unbind(struct device *dev)
{
	struct drm_device *drm = dev_get_drvdata(dev);

	drm_dev_unregister(drm);

	drm_kms_helper_poll_fini(drm);

	drm_mode_config_cleanup(drm);

	component_unbind_all(drm->dev, drm);
	dev_set_drvdata(dev, NULL);

	drm_dev_put(drm);
}
Пример #12
0
static int armada_drm_unload(struct drm_device *dev)
{
	struct armada_private *priv = dev->dev_private;

	drm_kms_helper_poll_fini(dev);
	armada_fbdev_fini(dev);

	component_unbind_all(dev->dev, dev);

	drm_mode_config_cleanup(dev);
	drm_mm_takedown(&priv->linear);
	flush_work(&priv->fb_unref_work);
	dev->dev_private = NULL;

	return 0;
}
Пример #13
0
static void etnaviv_unbind(struct device *dev)
{
	struct drm_device *drm = dev_get_drvdata(dev);
	struct etnaviv_drm_private *priv = drm->dev_private;

	drm_dev_unregister(drm);

	flush_workqueue(priv->wq);
	destroy_workqueue(priv->wq);

	component_unbind_all(dev, drm);

	drm->dev_private = NULL;
	kfree(priv);

	drm_put_dev(drm);
}
Пример #14
0
/*
 * 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;
}
Пример #15
0
static int msm_unload(struct drm_device *dev)
{
	struct msm_drm_private *priv = dev->dev_private;
	struct msm_kms *kms = priv->kms;
	struct msm_gpu *gpu = priv->gpu;

	drm_kms_helper_poll_fini(dev);
	drm_mode_config_cleanup(dev);
	drm_vblank_cleanup(dev);

	pm_runtime_get_sync(dev->dev);
	drm_irq_uninstall(dev);
	pm_runtime_put_sync(dev->dev);

	flush_workqueue(priv->wq);
	destroy_workqueue(priv->wq);

	if (kms) {
		pm_runtime_disable(dev->dev);
		kms->funcs->destroy(kms);
	}

	if (gpu) {
		mutex_lock(&dev->struct_mutex);
		gpu->funcs->pm_suspend(gpu);
		gpu->funcs->destroy(gpu);
		mutex_unlock(&dev->struct_mutex);
	}

	if (priv->vram.paddr) {
		DEFINE_DMA_ATTRS(attrs);
		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
		drm_mm_takedown(&priv->vram.mm);
		dma_free_attrs(dev->dev, priv->vram.size, NULL,
				priv->vram.paddr, &attrs);
	}

	component_unbind_all(dev->dev, dev);

	dev->dev_private = NULL;

	kfree(priv);

	return 0;
}
Пример #16
0
static int hdac_component_master_bind(struct device *dev)
{
	struct drm_audio_component *acomp = hdac_get_acomp(dev);
	int ret;

	if (WARN_ON(!acomp))
		return -EINVAL;

	ret = component_bind_all(dev, acomp);
	if (ret < 0)
		return ret;

	if (WARN_ON(!(acomp->dev && acomp->ops))) {
		ret = -EINVAL;
		goto out_unbind;
	}

	/* pin the module to avoid dynamic unbinding, but only if given */
	if (!try_module_get(acomp->ops->owner)) {
		ret = -ENODEV;
		goto out_unbind;
	}

	if (acomp->audio_ops && acomp->audio_ops->master_bind) {
		ret = acomp->audio_ops->master_bind(dev, acomp);
		if (ret < 0)
			goto module_put;
	}

	return 0;

 module_put:
	module_put(acomp->ops->owner);
out_unbind:
	component_unbind_all(dev, acomp);

	return ret;
}
Пример #17
0
static void hdlcd_drm_unbind(struct device *dev)
{
	struct drm_device *drm = dev_get_drvdata(dev);
	struct hdlcd_drm_private *hdlcd = drm->dev_private;

	if (hdlcd->fbdev) {
		drm_fbdev_cma_fini(hdlcd->fbdev);
		hdlcd->fbdev = NULL;
	}
	drm_kms_helper_poll_fini(drm);
	component_unbind_all(dev, drm);
	drm_vblank_cleanup(drm);
	pm_runtime_get_sync(drm->dev);
	drm_irq_uninstall(drm);
	pm_runtime_put_sync(drm->dev);
	pm_runtime_disable(drm->dev);
	of_reserved_mem_device_release(drm->dev);
	drm_mode_config_cleanup(drm);
	drm_dev_unregister(drm);
	drm_dev_unref(drm);
	drm->dev_private = NULL;
	dev_set_drvdata(dev, NULL);
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
static int armada_drm_load(struct drm_device *dev, unsigned long flags)
{
	struct armada_private *priv;
	struct resource *mem = NULL;
	int ret, n;

	for (n = 0; ; n++) {
		struct resource *r = platform_get_resource(dev->platformdev,
							   IORESOURCE_MEM, n);
		if (!r)
			break;

		/* Resources above 64K are graphics memory */
		if (resource_size(r) > SZ_64K)
			mem = r;
		else
			return -EINVAL;
	}

	if (!mem)
		return -ENXIO;

	if (!devm_request_mem_region(dev->dev, mem->start,
			resource_size(mem), "armada-drm"))
		return -EBUSY;

	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		DRM_ERROR("failed to allocate private\n");
		return -ENOMEM;
	}

	platform_set_drvdata(dev->platformdev, dev);
	dev->dev_private = priv;

	INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
	INIT_KFIFO(priv->fb_unref);

	/* Mode setting support */
	drm_mode_config_init(dev);
	dev->mode_config.min_width = 320;
	dev->mode_config.min_height = 200;

	/*
	 * With vscale enabled, the maximum width is 1920 due to the
	 * 1920 by 3 lines RAM
	 */
	dev->mode_config.max_width = 1920;
	dev->mode_config.max_height = 2048;

	dev->mode_config.preferred_depth = 24;
	dev->mode_config.funcs = &armada_drm_mode_config_funcs;
	drm_mm_init(&priv->linear, mem->start, resource_size(mem));
	mutex_init(&priv->linear_lock);

	ret = component_bind_all(dev->dev, dev);
	if (ret)
		goto err_kms;

	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
	if (ret)
		goto err_comp;

	dev->irq_enabled = true;
	dev->vblank_disable_allowed = 1;

	ret = armada_fbdev_init(dev);
	if (ret)
		goto err_comp;

	drm_kms_helper_poll_init(dev);

	return 0;

 err_comp:
	component_unbind_all(dev->dev, dev);
 err_kms:
	drm_mode_config_cleanup(dev);
	drm_mm_takedown(&priv->linear);
	flush_work(&priv->fb_unref_work);

	return ret;
}
Пример #21
0
static int armada_drm_load(struct drm_device *dev, unsigned long flags)
{
    const struct platform_device_id *id;
    const struct armada_variant *variant;
    struct armada_private *priv;
    struct resource *res[ARRAY_SIZE(priv->dcrtc)];
    struct resource *mem = NULL;
    int ret, n, i;

    memset(res, 0, sizeof(res));

    for (n = i = 0; ; n++) {
        struct resource *r = platform_get_resource(dev->platformdev,
                             IORESOURCE_MEM, n);
        if (!r)
            break;

        /* Resources above 64K are graphics memory */
        if (resource_size(r) > SZ_64K)
            mem = r;
        else if (i < ARRAY_SIZE(priv->dcrtc))
            res[i++] = r;
        else
            return -EINVAL;
    }

    if (!mem)
        return -ENXIO;

    if (!devm_request_mem_region(dev->dev, mem->start,
                                 resource_size(mem), "armada-drm"))
        return -EBUSY;

    priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
    if (!priv) {
        DRM_ERROR("failed to allocate private\n");
        return -ENOMEM;
    }

    platform_set_drvdata(dev->platformdev, dev);
    dev->dev_private = priv;

    /* Get the implementation specific driver data. */
    id = platform_get_device_id(dev->platformdev);
    if (!id)
        return -ENXIO;

    variant = (const struct armada_variant *)id->driver_data;

    INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
    INIT_KFIFO(priv->fb_unref);

    /* Mode setting support */
    drm_mode_config_init(dev);
    dev->mode_config.min_width = 320;
    dev->mode_config.min_height = 200;

    /*
     * With vscale enabled, the maximum width is 1920 due to the
     * 1920 by 3 lines RAM
     */
    dev->mode_config.max_width = 1920;
    dev->mode_config.max_height = 2048;

    dev->mode_config.preferred_depth = 24;
    dev->mode_config.funcs = &armada_drm_mode_config_funcs;
    drm_mm_init(&priv->linear, mem->start, resource_size(mem));

    /* Create all LCD controllers */
    for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
        int irq;

        if (!res[n])
            break;

        irq = platform_get_irq(dev->platformdev, n);
        if (irq < 0)
            goto err_kms;

        ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq,
                                     variant, NULL);
        if (ret)
            goto err_kms;
    }

    if (is_componentized(dev->dev)) {
        ret = component_bind_all(dev->dev, dev);
        if (ret)
            goto err_kms;
    } else {
#ifdef CONFIG_DRM_ARMADA_TDA1998X
        ret = armada_drm_connector_slave_create(dev, &tda19988_config);
        if (ret)
            goto err_kms;
#endif
    }

    ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
    if (ret)
        goto err_comp;

    dev->irq_enabled = true;
    dev->vblank_disable_allowed = 1;

    ret = armada_fbdev_init(dev);
    if (ret)
        goto err_comp;

    drm_kms_helper_poll_init(dev);

    return 0;

err_comp:
    if (is_componentized(dev->dev))
        component_unbind_all(dev->dev, dev);
err_kms:
    drm_mode_config_cleanup(dev);
    drm_mm_takedown(&priv->linear);
    flush_work(&priv->fb_unref_work);

    return ret;
}
Пример #22
0
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;
}