Commit 29cbf24a authored by Andrzej Hajda's avatar Andrzej Hajda Committed by Inki Dae
Browse files

drm/exynos: simplify DMA mapping



Moving DMA mapping creation to drm_iommu_attach_device allows to avoid
looping through all components and maintaining DMA device flags.

v2: take care of configurations without IOMMU

Signed-off-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent 167bfe53
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -569,7 +569,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)

	decon_clear_channels(ctx->crtc);

	return drm_iommu_attach_device(drm_dev, dev);
	return exynos_drm_register_dma(drm_dev, dev);
}

static void decon_unbind(struct device *dev, struct device *master, void *data)
+1 −1
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ static int decon_ctx_initialize(struct decon_context *ctx,

	decon_clear_channels(ctx->crtc);

	return drm_iommu_attach_device(drm_dev, ctx->dev);
	return exynos_drm_register_dma(drm_dev, ctx->dev);
}

static void decon_ctx_remove(struct decon_context *ctx)
+26 −45
Original line number Diff line number Diff line
@@ -45,6 +45,27 @@
#define DRIVER_MAJOR	1
#define DRIVER_MINOR	1

int exynos_drm_register_dma(struct drm_device *drm, struct device *dev)
{
	struct exynos_drm_private *priv = drm->dev_private;
	int ret;

	if (!priv->dma_dev) {
		priv->dma_dev = dev;
		DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
			 dev_name(dev));
		/* create common IOMMU mapping for all Exynos DRM devices */
		ret = drm_create_iommu_mapping(drm);
		if (ret < 0) {
			priv->dma_dev = NULL;
			DRM_ERROR("failed to create iommu mapping.\n");
			return -EINVAL;
		}
	}

	return drm_iommu_attach_device(drm, dev);
}

static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
{
	struct drm_exynos_file_private *file_priv;
@@ -175,8 +196,7 @@ struct exynos_drm_driver_info {

#define DRM_COMPONENT_DRIVER	BIT(0)	/* supports component framework */
#define DRM_VIRTUAL_DEVICE	BIT(1)	/* create virtual platform device */
#define DRM_DMA_DEVICE		BIT(2)	/* can be used for dma allocations */
#define DRM_FIMC_DEVICE		BIT(3)	/* devices shared with V4L2 subsystem */
#define DRM_FIMC_DEVICE		BIT(2)	/* devices shared with V4L2 subsystem */

#define DRV_PTR(drv, cond) (IS_ENABLED(cond) ? &drv : NULL)

@@ -187,16 +207,16 @@ struct exynos_drm_driver_info {
static struct exynos_drm_driver_info exynos_drm_drivers[] = {
	{
		DRV_PTR(fimd_driver, CONFIG_DRM_EXYNOS_FIMD),
		DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
		DRM_COMPONENT_DRIVER
	}, {
		DRV_PTR(exynos5433_decon_driver, CONFIG_DRM_EXYNOS5433_DECON),
		DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
		DRM_COMPONENT_DRIVER
	}, {
		DRV_PTR(decon_driver, CONFIG_DRM_EXYNOS7_DECON),
		DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
		DRM_COMPONENT_DRIVER
	}, {
		DRV_PTR(mixer_driver, CONFIG_DRM_EXYNOS_MIXER),
		DRM_COMPONENT_DRIVER | DRM_DMA_DEVICE
		DRM_COMPONENT_DRIVER
	}, {
		DRV_PTR(mic_driver, CONFIG_DRM_EXYNOS_MIC),
		DRM_COMPONENT_DRIVER
@@ -267,27 +287,6 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
	return match ?: ERR_PTR(-ENODEV);
}

static struct device *exynos_drm_get_dma_device(void)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
		struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
		struct device *dev;

		if (!info->driver || !(info->flags & DRM_DMA_DEVICE))
			continue;

		while ((dev = bus_find_device(&platform_bus_type, NULL,
					    &info->driver->driver,
					    (void *)platform_bus_type.match))) {
			put_device(dev);
			return dev;
		}
	}
	return NULL;
}

static int exynos_drm_bind(struct device *dev)
{
	struct exynos_drm_private *private;
@@ -312,23 +311,6 @@ static int exynos_drm_bind(struct device *dev)
	dev_set_drvdata(dev, drm);
	drm->dev_private = (void *)private;

	/* the first real CRTC device is used for all dma mapping operations */
	private->dma_dev = exynos_drm_get_dma_device();
	if (!private->dma_dev) {
		DRM_ERROR("no device found for DMA mapping operations.\n");
		ret = -ENODEV;
		goto err_free_private;
	}
	DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
		 dev_name(private->dma_dev));

	/* create common IOMMU mapping for all devices attached to Exynos DRM */
	ret = drm_create_iommu_mapping(drm);
	if (ret < 0) {
		DRM_ERROR("failed to create iommu mapping.\n");
		goto err_free_private;
	}

	drm_mode_config_init(drm);

	exynos_drm_mode_config_init(drm);
@@ -386,7 +368,6 @@ err_unbind_all:
err_mode_config_cleanup:
	drm_mode_config_cleanup(drm);
	drm_release_iommu_mapping(drm);
err_free_private:
	kfree(private);
err_free_drm:
	drm_dev_put(drm);
+2 −0
Original line number Diff line number Diff line
@@ -214,6 +214,8 @@ static inline struct device *to_dma_dev(struct drm_device *dev)
	return priv->dma_dev;
}

int exynos_drm_register_dma(struct drm_device *drm, struct device *dev);

#ifdef CONFIG_DRM_EXYNOS_DPI
struct drm_encoder *exynos_dpi_probe(struct device *dev);
int exynos_dpi_remove(struct drm_encoder *encoder);
+1 −1
Original line number Diff line number Diff line
@@ -1129,7 +1129,7 @@ static int fimc_bind(struct device *dev, struct device *master, void *data)
	struct exynos_drm_ipp *ipp = &ctx->ipp;

	ctx->drm_dev = drm_dev;
	drm_iommu_attach_device(drm_dev, dev);
	exynos_drm_register_dma(drm_dev, dev);

	exynos_drm_ipp_register(drm_dev, ipp, &ipp_funcs,
			DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE |
Loading