Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1055b39f authored by Inki Dae's avatar Inki Dae
Browse files

drm/exynos: add iommu support for hdmi driver



Changelog v2:
move iommu support feature to mixer side.
And below is Prathyush's comment.

According to the new IOMMU framework for exynos sysmmus,
the owner of the sysmmu-tv is mixer (which is the actual
device that does DMA) and not hdmi.
The mmu-master in sysmmu-tv node is set as below in exynos5250.dtsi
	sysmmu-tv {
		-
		mmu-master = <&mixer>;
	};

Changelog v1:
The iommu will be enabled when hdmi sub driver is probed and
will be disabled when removed.

Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
parent bcc5cd1c
Loading
Loading
Loading
Loading
+15 −0
Original line number Original line Diff line number Diff line
@@ -346,9 +346,23 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev,
	ctx->hdmi_ctx->drm_dev = drm_dev;
	ctx->hdmi_ctx->drm_dev = drm_dev;
	ctx->mixer_ctx->drm_dev = drm_dev;
	ctx->mixer_ctx->drm_dev = drm_dev;


	if (mixer_ops->iommu_on)
		mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true);

	return 0;
	return 0;
}
}


static void hdmi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
{
	struct drm_hdmi_context *ctx;
	struct exynos_drm_subdrv *subdrv = to_subdrv(dev);

	ctx = get_ctx_from_subdrv(subdrv);

	if (mixer_ops->iommu_on)
		mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false);
}

static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
{
{
	struct device *dev = &pdev->dev;
	struct device *dev = &pdev->dev;
@@ -368,6 +382,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
	subdrv->dev = dev;
	subdrv->dev = dev;
	subdrv->manager = &hdmi_manager;
	subdrv->manager = &hdmi_manager;
	subdrv->probe = hdmi_subdrv_probe;
	subdrv->probe = hdmi_subdrv_probe;
	subdrv->remove = hdmi_subdrv_remove;


	platform_set_drvdata(pdev, subdrv);
	platform_set_drvdata(pdev, subdrv);


+1 −0
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ struct exynos_hdmi_ops {


struct exynos_mixer_ops {
struct exynos_mixer_ops {
	/* manager */
	/* manager */
	int (*iommu_on)(void *ctx, bool enable);
	int (*enable_vblank)(void *ctx, int pipe);
	int (*enable_vblank)(void *ctx, int pipe);
	void (*disable_vblank)(void *ctx);
	void (*disable_vblank)(void *ctx);
	void (*dpms)(void *ctx, int mode);
	void (*dpms)(void *ctx, int mode);
+1 −1
Original line number Original line Diff line number Diff line
@@ -74,6 +74,7 @@ struct hdmi_context {
	struct mutex			hdmi_mutex;
	struct mutex			hdmi_mutex;


	void __iomem			*regs;
	void __iomem			*regs;
	void				*parent_ctx;
	int				external_irq;
	int				external_irq;
	int				internal_irq;
	int				internal_irq;


@@ -84,7 +85,6 @@ struct hdmi_context {
	int cur_conf;
	int cur_conf;


	struct hdmi_resources		res;
	struct hdmi_resources		res;
	void				*parent_ctx;


	int				hpd_gpio;
	int				hpd_gpio;


+23 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@


#include "exynos_drm_drv.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_hdmi.h"
#include "exynos_drm_hdmi.h"
#include "exynos_drm_iommu.h"


#define get_mixer_context(dev)	platform_get_drvdata(to_platform_device(dev))
#define get_mixer_context(dev)	platform_get_drvdata(to_platform_device(dev))


@@ -80,6 +81,7 @@ enum mixer_version_id {


struct mixer_context {
struct mixer_context {
	struct device		*dev;
	struct device		*dev;
	struct drm_device	*drm_dev;
	int			pipe;
	int			pipe;
	bool			interlace;
	bool			interlace;
	bool			powered;
	bool			powered;
@@ -90,6 +92,7 @@ struct mixer_context {
	struct mixer_resources	mixer_res;
	struct mixer_resources	mixer_res;
	struct hdmi_win_data	win_data[MIXER_WIN_NR];
	struct hdmi_win_data	win_data[MIXER_WIN_NR];
	enum mixer_version_id	mxr_ver;
	enum mixer_version_id	mxr_ver;
	void			*parent_ctx;
};
};


struct mixer_drv_data {
struct mixer_drv_data {
@@ -665,6 +668,24 @@ static void mixer_win_reset(struct mixer_context *ctx)
	spin_unlock_irqrestore(&res->reg_slock, flags);
	spin_unlock_irqrestore(&res->reg_slock, flags);
}
}


static int mixer_iommu_on(void *ctx, bool enable)
{
	struct exynos_drm_hdmi_context *drm_hdmi_ctx;
	struct mixer_context *mdata = ctx;
	struct drm_device *drm_dev;

	drm_hdmi_ctx = mdata->parent_ctx;
	drm_dev = drm_hdmi_ctx->drm_dev;

	if (is_drm_iommu_supported(drm_dev)) {
		if (enable)
			return drm_iommu_attach_device(drm_dev, mdata->dev);

		drm_iommu_detach_device(drm_dev, mdata->dev);
	}
	return 0;
}

static void mixer_poweron(struct mixer_context *ctx)
static void mixer_poweron(struct mixer_context *ctx)
{
{
	struct mixer_resources *res = &ctx->mixer_res;
	struct mixer_resources *res = &ctx->mixer_res;
@@ -866,6 +887,7 @@ static void mixer_win_disable(void *ctx, int win)


static struct exynos_mixer_ops mixer_ops = {
static struct exynos_mixer_ops mixer_ops = {
	/* manager */
	/* manager */
	.iommu_on		= mixer_iommu_on,
	.enable_vblank		= mixer_enable_vblank,
	.enable_vblank		= mixer_enable_vblank,
	.disable_vblank		= mixer_disable_vblank,
	.disable_vblank		= mixer_disable_vblank,
	.dpms			= mixer_dpms,
	.dpms			= mixer_dpms,
@@ -1140,6 +1162,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
	}
	}


	ctx->dev = &pdev->dev;
	ctx->dev = &pdev->dev;
	ctx->parent_ctx = (void *)drm_hdmi_ctx;
	drm_hdmi_ctx->ctx = (void *)ctx;
	drm_hdmi_ctx->ctx = (void *)ctx;
	ctx->vp_enabled = drv->is_vp_enabled;
	ctx->vp_enabled = drv->is_vp_enabled;
	ctx->mxr_ver = drv->version;
	ctx->mxr_ver = drv->version;