Merge tag 'exynos-drm-next-for-v4.21' of git://git.kernel.org/pub/scm/linux/kernel...
authorDave Airlie <airlied@redhat.com>
Thu, 6 Dec 2018 03:29:34 +0000 (13:29 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 6 Dec 2018 03:30:03 +0000 (13:30 +1000)
- Refactoring of DMA and IOMMU code
  . This patch series simplifies DMA mapping creation by avoiding looping
    all components to get dma device object, reduces code size by merging
    IOMMU and DMA code.
- Enhance plane alpha and blend mode support
  . This patch series adds configurable plane and pixel blend mode support
    for Exynos5433 DECON device.
- Fix color format setting of Mixer driver
  . This patch series fixes color format and range setting by splitting
    range and format.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Inki Dae <inki.dae@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1544002853-11661-1-git-send-email-inki.dae@samsung.com
21 files changed:
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/Makefile
drivers/gpu/drm/exynos/exynos5433_drm_decon.c
drivers/gpu/drm/exynos/exynos7_drm_decon.c
drivers/gpu/drm/exynos/exynos_drm_dma.c [new file with mode: 0644]
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fb.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_drm_iommu.c [deleted file]
drivers/gpu/drm/exynos/exynos_drm_iommu.h [deleted file]
drivers/gpu/drm/exynos/exynos_drm_rotator.c
drivers/gpu/drm/exynos/exynos_drm_scaler.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/exynos/regs-decon5433.h
drivers/gpu/drm/exynos/regs-mixer.h

index 208bc27be3cc47a937625f110883c998be41ac7b..3691a140c9502e995d28454fbd52196ca599a5d7 100644 (file)
@@ -10,11 +10,6 @@ config DRM_EXYNOS
 
 if DRM_EXYNOS
 
-config DRM_EXYNOS_IOMMU
-       bool
-       depends on EXYNOS_IOMMU
-       default y
-
 comment "CRTCs"
 
 config DRM_EXYNOS_FIMD
index 2ad146bbf4f5488e8b6293dabc9238c03753c044..2fd2f3ee4fcf09244fdb399e4b1b684e1308b5a7 100644 (file)
@@ -4,10 +4,9 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fb.o \
-               exynos_drm_gem.o exynos_drm_plane.o
+               exynos_drm_gem.o exynos_drm_plane.o exynos_drm_dma.o
 
 exynosdrm-$(CONFIG_DRM_FBDEV_EMULATION) += exynos_drm_fbdev.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)    += exynos_drm_fimd.o
 exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON)       += exynos5433_drm_decon.o
 exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON)  += exynos7_drm_decon.o
index aef487dd873153d77fd602726ab6bd92256ab593..5b4e0e8b23bc4d86fbb13e1120c40ec78f99a029 100644 (file)
@@ -25,7 +25,6 @@
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_plane.h"
-#include "exynos_drm_iommu.h"
 #include "regs-decon5433.h"
 
 #define DSD_CFG_MUX 0x1004
@@ -84,6 +83,14 @@ static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
        [CURSON_WIN] = DRM_PLANE_TYPE_CURSOR,
 };
 
+static const unsigned int capabilities[WINDOWS_NR] = {
+       0,
+       EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+       EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+       EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+       EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
+};
+
 static inline void decon_set_bits(struct decon_context *ctx, u32 reg, u32 mask,
                                  u32 val)
 {
@@ -252,11 +259,76 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
        decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
 }
 
+static void decon_win_set_bldeq(struct decon_context *ctx, unsigned int win,
+                               unsigned int alpha, unsigned int pixel_alpha)
+{
+       u32 mask = BLENDERQ_A_FUNC_F(0xf) | BLENDERQ_B_FUNC_F(0xf);
+       u32 val = 0;
+
+       switch (pixel_alpha) {
+       case DRM_MODE_BLEND_PIXEL_NONE:
+       case DRM_MODE_BLEND_COVERAGE:
+               val |= BLENDERQ_A_FUNC_F(BLENDERQ_ALPHA_A);
+               val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A);
+               break;
+       case DRM_MODE_BLEND_PREMULTI:
+       default:
+               if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
+                       val |= BLENDERQ_A_FUNC_F(BLENDERQ_ALPHA0);
+                       val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A);
+               } else {
+                       val |= BLENDERQ_A_FUNC_F(BLENDERQ_ONE);
+                       val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A);
+               }
+               break;
+       }
+       decon_set_bits(ctx, DECON_BLENDERQx(win), mask, val);
+}
+
+static void decon_win_set_bldmod(struct decon_context *ctx, unsigned int win,
+                                unsigned int alpha, unsigned int pixel_alpha)
+{
+       u32 win_alpha = alpha >> 8;
+       u32 val = 0;
+
+       switch (pixel_alpha) {
+       case DRM_MODE_BLEND_PIXEL_NONE:
+               break;
+       case DRM_MODE_BLEND_COVERAGE:
+       case DRM_MODE_BLEND_PREMULTI:
+       default:
+               val |= WINCONx_ALPHA_SEL_F;
+               val |= WINCONx_BLD_PIX_F;
+               val |= WINCONx_ALPHA_MUL_F;
+               break;
+       }
+       decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_BLEND_MODE_MASK, val);
+
+       if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
+               val = VIDOSD_Wx_ALPHA_R_F(win_alpha) |
+                     VIDOSD_Wx_ALPHA_G_F(win_alpha) |
+                     VIDOSD_Wx_ALPHA_B_F(win_alpha);
+               decon_set_bits(ctx, DECON_VIDOSDxC(win),
+                              VIDOSDxC_ALPHA0_RGB_MASK, val);
+               decon_set_bits(ctx, DECON_BLENDCON, BLEND_NEW, BLEND_NEW);
+       }
+}
+
 static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
                                 struct drm_framebuffer *fb)
 {
+       struct exynos_drm_plane plane = ctx->planes[win];
+       struct exynos_drm_plane_state *state =
+               to_exynos_plane_state(plane.base.state);
+       unsigned int alpha = state->base.alpha;
+       unsigned int pixel_alpha;
        unsigned long val;
 
+       if (fb->format->has_alpha)
+               pixel_alpha = state->base.pixel_blend_mode;
+       else
+               pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE;
+
        val = readl(ctx->addr + DECON_WINCONx(win));
        val &= WINCONx_ENWIN_F;
 
@@ -279,7 +351,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
        case DRM_FORMAT_ARGB8888:
        default:
                val |= WINCONx_BPPMODE_32BPP_A8888;
-               val |= WINCONx_WSWP_F | WINCONx_BLD_PIX_F | WINCONx_ALPHA_SEL_F;
+               val |= WINCONx_WSWP_F;
                val |= WINCONx_BURSTLEN_16WORD;
                break;
        }
@@ -298,8 +370,12 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
                val &= ~WINCONx_BURSTLEN_MASK;
                val |= WINCONx_BURSTLEN_8WORD;
        }
+       decon_set_bits(ctx, DECON_WINCONx(win), ~WINCONx_BLEND_MODE_MASK, val);
 
-       writel(val, ctx->addr + DECON_WINCONx(win));
+       if (win > 0) {
+               decon_win_set_bldmod(ctx, win, alpha, pixel_alpha);
+               decon_win_set_bldeq(ctx, win, alpha, pixel_alpha);
+       }
 }
 
 static void decon_shadow_protect(struct decon_context *ctx, bool protect)
@@ -552,6 +628,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
                ctx->configs[win].num_pixel_formats = ARRAY_SIZE(decon_formats);
                ctx->configs[win].zpos = win - ctx->first_win;
                ctx->configs[win].type = decon_win_types[win];
+               ctx->configs[win].capabilities = capabilities[win];
 
                ret = exynos_plane_init(drm_dev, &ctx->planes[win], win,
                                        &ctx->configs[win]);
@@ -569,7 +646,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)
@@ -579,7 +656,7 @@ static void decon_unbind(struct device *dev, struct device *master, void *data)
        decon_disable(ctx->crtc);
 
        /* detach this sub driver from iommu mapping if supported. */
-       drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
+       exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
 }
 
 static const struct component_ops decon_component_ops = {
index 88cbd000eb094cb480d85d77a7cf40f664f1bd1f..381aa3d60e37a86d7bc0be1c4a8737ace9098498 100644 (file)
@@ -30,7 +30,6 @@
 #include "exynos_drm_plane.h"
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
-#include "exynos_drm_iommu.h"
 #include "regs-decon7.h"
 
 /*
@@ -133,13 +132,13 @@ 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)
 {
        /* detach this sub driver from iommu mapping if supported. */
-       drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
+       exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
 }
 
 static u32 decon_calc_clkdiv(struct decon_context *ctx,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dma.c b/drivers/gpu/drm/exynos/exynos_drm_dma.c
new file mode 100644 (file)
index 0000000..3432c5e
--- /dev/null
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+// Author: Inki Dae <inki.dae@samsung.com>
+// Author: Andrzej Hajda <a.hajda@samsung.com>
+
+#include <drm/drmP.h>
+#include <drm/exynos_drm.h>
+#include <linux/dma-iommu.h>
+#include <linux/dma-mapping.h>
+#include <linux/iommu.h>
+
+#include "exynos_drm_drv.h"
+
+#if defined(CONFIG_ARM_DMA_USE_IOMMU)
+#include <asm/dma-iommu.h>
+#else
+#define arm_iommu_create_mapping(...)  ({ NULL; })
+#define arm_iommu_attach_device(...)   ({ -ENODEV; })
+#define arm_iommu_release_mapping(...) ({ })
+#define arm_iommu_detach_device(...)   ({ })
+#define to_dma_iommu_mapping(dev) NULL
+#endif
+
+#if !defined(CONFIG_IOMMU_DMA)
+#define iommu_dma_init_domain(...) ({ -EINVAL; })
+#endif
+
+#define EXYNOS_DEV_ADDR_START  0x20000000
+#define EXYNOS_DEV_ADDR_SIZE   0x40000000
+
+static inline int configure_dma_max_seg_size(struct device *dev)
+{
+       if (!dev->dma_parms)
+               dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL);
+       if (!dev->dma_parms)
+               return -ENOMEM;
+
+       dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+       return 0;
+}
+
+static inline void clear_dma_max_seg_size(struct device *dev)
+{
+       kfree(dev->dma_parms);
+       dev->dma_parms = NULL;
+}
+
+/*
+ * drm_iommu_attach_device- attach device to iommu mapping
+ *
+ * @drm_dev: DRM device
+ * @subdrv_dev: device to be attach
+ *
+ * This function should be called by sub drivers to attach it to iommu
+ * mapping.
+ */
+static int drm_iommu_attach_device(struct drm_device *drm_dev,
+                               struct device *subdrv_dev)
+{
+       struct exynos_drm_private *priv = drm_dev->dev_private;
+       int ret;
+
+       if (get_dma_ops(priv->dma_dev) != get_dma_ops(subdrv_dev)) {
+               DRM_ERROR("Device %s lacks support for IOMMU\n",
+                         dev_name(subdrv_dev));
+               return -EINVAL;
+       }
+
+       ret = configure_dma_max_seg_size(subdrv_dev);
+       if (ret)
+               return ret;
+
+       if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) {
+               if (to_dma_iommu_mapping(subdrv_dev))
+                       arm_iommu_detach_device(subdrv_dev);
+
+               ret = arm_iommu_attach_device(subdrv_dev, priv->mapping);
+       } else if (IS_ENABLED(CONFIG_IOMMU_DMA)) {
+               ret = iommu_attach_device(priv->mapping, subdrv_dev);
+       }
+
+       if (ret)
+               clear_dma_max_seg_size(subdrv_dev);
+
+       return 0;
+}
+
+/*
+ * drm_iommu_detach_device -detach device address space mapping from device
+ *
+ * @drm_dev: DRM device
+ * @subdrv_dev: device to be detached
+ *
+ * This function should be called by sub drivers to detach it from iommu
+ * mapping
+ */
+static void drm_iommu_detach_device(struct drm_device *drm_dev,
+                               struct device *subdrv_dev)
+{
+       struct exynos_drm_private *priv = drm_dev->dev_private;
+
+       if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
+               arm_iommu_detach_device(subdrv_dev);
+       else if (IS_ENABLED(CONFIG_IOMMU_DMA))
+               iommu_detach_device(priv->mapping, subdrv_dev);
+
+       clear_dma_max_seg_size(subdrv_dev);
+}
+
+int exynos_drm_register_dma(struct drm_device *drm, struct device *dev)
+{
+       struct exynos_drm_private *priv = drm->dev_private;
+
+       if (!priv->dma_dev) {
+               priv->dma_dev = dev;
+               DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
+                        dev_name(dev));
+       }
+
+       if (!IS_ENABLED(CONFIG_EXYNOS_IOMMU))
+               return 0;
+
+       if (!priv->mapping) {
+               void *mapping;
+
+               if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
+                       mapping = arm_iommu_create_mapping(&platform_bus_type,
+                               EXYNOS_DEV_ADDR_START, EXYNOS_DEV_ADDR_SIZE);
+               else if (IS_ENABLED(CONFIG_IOMMU_DMA))
+                       mapping = iommu_get_domain_for_dev(priv->dma_dev);
+
+               if (IS_ERR(mapping))
+                       return PTR_ERR(mapping);
+               priv->mapping = mapping;
+       }
+
+       return drm_iommu_attach_device(drm, dev);
+}
+
+void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev)
+{
+       if (IS_ENABLED(CONFIG_EXYNOS_IOMMU))
+               drm_iommu_detach_device(drm, dev);
+}
+
+void exynos_drm_cleanup_dma(struct drm_device *drm)
+{
+       struct exynos_drm_private *priv = drm->dev_private;
+
+       if (!IS_ENABLED(CONFIG_EXYNOS_IOMMU))
+               return;
+
+       arm_iommu_release_mapping(priv->mapping);
+       priv->mapping = NULL;
+       priv->dma_dev = NULL;
+}
index 6f76baf4550ada0fc6a75990abde632914f656a3..2c75e789b2a7e9faf80aa9c6eac3ef5b65fa98e6 100644 (file)
@@ -30,7 +30,6 @@
 #include "exynos_drm_ipp.h"
 #include "exynos_drm_vidi.h"
 #include "exynos_drm_g2d.h"
-#include "exynos_drm_iommu.h"
 
 #define DRIVER_NAME    "exynos"
 #define DRIVER_DESC    "Samsung SoC DRM"
@@ -175,8 +174,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 +185,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 +265,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 +289,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);
@@ -385,8 +345,7 @@ err_unbind_all:
        component_unbind_all(drm->dev, drm);
 err_mode_config_cleanup:
        drm_mode_config_cleanup(drm);
-       drm_release_iommu_mapping(drm);
-err_free_private:
+       exynos_drm_cleanup_dma(drm);
        kfree(private);
 err_free_drm:
        drm_dev_put(drm);
@@ -405,7 +364,7 @@ static void exynos_drm_unbind(struct device *dev)
 
        component_unbind_all(drm->dev, drm);
        drm_mode_config_cleanup(drm);
-       drm_release_iommu_mapping(drm);
+       exynos_drm_cleanup_dma(drm);
 
        kfree(drm->dev_private);
        drm->dev_private = NULL;
index 5e61e707f95555da181969aa71254fc71ffa4098..71eb240bc1f4f7d7c7dc1ab342cf03216ef98a44 100644 (file)
@@ -214,6 +214,17 @@ static inline struct device *to_dma_dev(struct drm_device *dev)
        return priv->dma_dev;
 }
 
+static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
+{
+       struct exynos_drm_private *priv = drm_dev->dev_private;
+
+       return priv->mapping ? true : false;
+}
+
+int exynos_drm_register_dma(struct drm_device *drm, struct device *dev);
+void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev);
+void exynos_drm_cleanup_dma(struct drm_device *drm);
+
 #ifdef CONFIG_DRM_EXYNOS_DPI
 struct drm_encoder *exynos_dpi_probe(struct device *dev);
 int exynos_dpi_remove(struct drm_encoder *encoder);
index 9f52382e19ee338e18dbe8212b0d1a69c604d3e9..31eb538a44ae1950c7f94fa9b994abb154b525df 100644 (file)
@@ -24,7 +24,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_fbdev.h"
-#include "exynos_drm_iommu.h"
 #include "exynos_drm_crtc.h"
 
 static int check_fb_gem_memory_type(struct drm_device *drm_dev,
index 01d182289efa38fd75a83cd399b02bbfd1e590c0..ce9604ca8041d7b03a783e1cad743a7480074cc3 100644 (file)
@@ -23,7 +23,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_fbdev.h"
-#include "exynos_drm_iommu.h"
 
 #define MAX_CONNECTOR          4
 #define PREFERRED_BPP          32
index e8d0670bb5f8d280a9e17a1e4270c0464b1e4abc..90dfea0aec4d3cdcf33d6635c843f5dc578812a3 100644 (file)
@@ -25,7 +25,6 @@
 #include <drm/exynos_drm.h>
 #include "regs-fimc.h"
 #include "exynos_drm_drv.h"
-#include "exynos_drm_iommu.h"
 #include "exynos_drm_ipp.h"
 
 /*
@@ -1129,7 +1128,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 |
@@ -1149,7 +1148,7 @@ static void fimc_unbind(struct device *dev, struct device *master,
        struct exynos_drm_ipp *ipp = &ctx->ipp;
 
        exynos_drm_ipp_unregister(drm_dev, ipp);
-       drm_iommu_detach_device(drm_dev, dev);
+       exynos_drm_unregister_dma(drm_dev, dev);
 }
 
 static const struct component_ops fimc_component_ops = {
index b7f56935a46bc2a33fec03c18854774cb331f70d..e3d6a8584715a7966b2d87bfa546bdddf0f90605 100644 (file)
@@ -32,7 +32,6 @@
 #include "exynos_drm_fb.h"
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_plane.h"
-#include "exynos_drm_iommu.h"
 
 /*
  * FIMD stands for Fully Interactive Mobile Display and
@@ -1011,7 +1010,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
        if (is_drm_iommu_supported(drm_dev))
                fimd_clear_channels(ctx->crtc);
 
-       return drm_iommu_attach_device(drm_dev, dev);
+       return exynos_drm_register_dma(drm_dev, dev);
 }
 
 static void fimd_unbind(struct device *dev, struct device *master,
@@ -1021,7 +1020,7 @@ static void fimd_unbind(struct device *dev, struct device *master,
 
        fimd_disable(ctx->crtc);
 
-       drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
+       exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
 
        if (ctx->encoder)
                exynos_dpi_remove(ctx->encoder);
index f2481a2014bb3c91ac1c8d60711a5fea89f43636..24c536d6d9cf866afda4c9839fdbc6e61a5a8854 100644 (file)
@@ -25,7 +25,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_g2d.h"
 #include "exynos_drm_gem.h"
-#include "exynos_drm_iommu.h"
 
 #define G2D_HW_MAJOR_VER               4
 #define G2D_HW_MINOR_VER               1
@@ -1405,7 +1404,7 @@ static int g2d_bind(struct device *dev, struct device *master, void *data)
                return ret;
        }
 
-       ret = drm_iommu_attach_device(drm_dev, dev);
+       ret = exynos_drm_register_dma(drm_dev, dev);
        if (ret < 0) {
                dev_err(dev, "failed to enable iommu.\n");
                g2d_fini_cmdlist(g2d);
@@ -1430,7 +1429,7 @@ static void g2d_unbind(struct device *dev, struct device *master, void *data)
        priv->g2d_dev = NULL;
 
        cancel_work_sync(&g2d->runqueue_work);
-       drm_iommu_detach_device(g2d->drm_dev, dev);
+       exynos_drm_unregister_dma(g2d->drm_dev, dev);
 }
 
 static const struct component_ops g2d_component_ops = {
index 34ace85feb6883e3dcf9793d5057a5c1de2ebb21..df66c383a877a583be0e457a0f866a8b5f3b819f 100644 (file)
@@ -19,7 +19,6 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_gem.h"
-#include "exynos_drm_iommu.h"
 
 static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
 {
index ce15d46bfce8a57dc007e0af5317dd9d1f7385a0..f048d97fe9e2e9b522b0366b868e9ca09f156c97 100644 (file)
@@ -24,7 +24,6 @@
 #include <drm/exynos_drm.h>
 #include "regs-gsc.h"
 #include "exynos_drm_drv.h"
-#include "exynos_drm_iommu.h"
 #include "exynos_drm_ipp.h"
 
 /*
@@ -1170,7 +1169,7 @@ static int gsc_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 |
@@ -1190,7 +1189,7 @@ static void gsc_unbind(struct device *dev, struct device *master,
        struct exynos_drm_ipp *ipp = &ctx->ipp;
 
        exynos_drm_ipp_unregister(drm_dev, ipp);
-       drm_iommu_detach_device(drm_dev, dev);
+       exynos_drm_unregister_dma(drm_dev, dev);
 }
 
 static const struct component_ops gsc_component_ops = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
deleted file mode 100644 (file)
index 0f37370..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* exynos_drm_iommu.c
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * Author: Inki Dae <inki.dae@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <drm/drmP.h>
-#include <drm/exynos_drm.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/iommu.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_iommu.h"
-
-static inline int configure_dma_max_seg_size(struct device *dev)
-{
-       if (!dev->dma_parms)
-               dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL);
-       if (!dev->dma_parms)
-               return -ENOMEM;
-
-       dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
-       return 0;
-}
-
-static inline void clear_dma_max_seg_size(struct device *dev)
-{
-       kfree(dev->dma_parms);
-       dev->dma_parms = NULL;
-}
-
-/*
- * drm_create_iommu_mapping - create a mapping structure
- *
- * @drm_dev: DRM device
- */
-int drm_create_iommu_mapping(struct drm_device *drm_dev)
-{
-       struct exynos_drm_private *priv = drm_dev->dev_private;
-
-       return __exynos_iommu_create_mapping(priv, EXYNOS_DEV_ADDR_START,
-                                            EXYNOS_DEV_ADDR_SIZE);
-}
-
-/*
- * drm_release_iommu_mapping - release iommu mapping structure
- *
- * @drm_dev: DRM device
- */
-void drm_release_iommu_mapping(struct drm_device *drm_dev)
-{
-       struct exynos_drm_private *priv = drm_dev->dev_private;
-
-       __exynos_iommu_release_mapping(priv);
-}
-
-/*
- * drm_iommu_attach_device- attach device to iommu mapping
- *
- * @drm_dev: DRM device
- * @subdrv_dev: device to be attach
- *
- * This function should be called by sub drivers to attach it to iommu
- * mapping.
- */
-int drm_iommu_attach_device(struct drm_device *drm_dev,
-                               struct device *subdrv_dev)
-{
-       struct exynos_drm_private *priv = drm_dev->dev_private;
-       int ret;
-
-       if (get_dma_ops(priv->dma_dev) != get_dma_ops(subdrv_dev)) {
-               DRM_ERROR("Device %s lacks support for IOMMU\n",
-                         dev_name(subdrv_dev));
-               return -EINVAL;
-       }
-
-       ret = configure_dma_max_seg_size(subdrv_dev);
-       if (ret)
-               return ret;
-
-       ret = __exynos_iommu_attach(priv, subdrv_dev);
-       if (ret)
-               clear_dma_max_seg_size(subdrv_dev);
-
-       return 0;
-}
-
-/*
- * drm_iommu_detach_device -detach device address space mapping from device
- *
- * @drm_dev: DRM device
- * @subdrv_dev: device to be detached
- *
- * This function should be called by sub drivers to detach it from iommu
- * mapping
- */
-void drm_iommu_detach_device(struct drm_device *drm_dev,
-                               struct device *subdrv_dev)
-{
-       struct exynos_drm_private *priv = drm_dev->dev_private;
-
-       __exynos_iommu_detach(priv, subdrv_dev);
-       clear_dma_max_seg_size(subdrv_dev);
-}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
deleted file mode 100644 (file)
index 797d9ee..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/* exynos_drm_iommu.h
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * Authoer: Inki Dae <inki.dae@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef _EXYNOS_DRM_IOMMU_H_
-#define _EXYNOS_DRM_IOMMU_H_
-
-#define EXYNOS_DEV_ADDR_START  0x20000000
-#define EXYNOS_DEV_ADDR_SIZE   0x40000000
-
-#ifdef CONFIG_DRM_EXYNOS_IOMMU
-
-#if defined(CONFIG_ARM_DMA_USE_IOMMU)
-#include <asm/dma-iommu.h>
-
-static inline int __exynos_iommu_create_mapping(struct exynos_drm_private *priv,
-                                       unsigned long start, unsigned long size)
-{
-       priv->mapping = arm_iommu_create_mapping(&platform_bus_type, start,
-                                                size);
-       return IS_ERR(priv->mapping);
-}
-
-static inline void
-__exynos_iommu_release_mapping(struct exynos_drm_private *priv)
-{
-       arm_iommu_release_mapping(priv->mapping);
-}
-
-static inline int __exynos_iommu_attach(struct exynos_drm_private *priv,
-                                       struct device *dev)
-{
-       if (dev->archdata.mapping)
-               arm_iommu_detach_device(dev);
-
-       return arm_iommu_attach_device(dev, priv->mapping);
-}
-
-static inline void __exynos_iommu_detach(struct exynos_drm_private *priv,
-                                        struct device *dev)
-{
-       arm_iommu_detach_device(dev);
-}
-
-#elif defined(CONFIG_IOMMU_DMA)
-#include <linux/dma-iommu.h>
-
-static inline int __exynos_iommu_create_mapping(struct exynos_drm_private *priv,
-                                       unsigned long start, unsigned long size)
-{
-       priv->mapping = iommu_get_domain_for_dev(priv->dma_dev);
-       return 0;
-}
-
-static inline void __exynos_iommu_release_mapping(struct exynos_drm_private *priv)
-{
-       priv->mapping = NULL;
-}
-
-static inline int __exynos_iommu_attach(struct exynos_drm_private *priv,
-                                       struct device *dev)
-{
-       struct iommu_domain *domain = priv->mapping;
-
-       if (dev != priv->dma_dev)
-               return iommu_attach_device(domain, dev);
-       return 0;
-}
-
-static inline void __exynos_iommu_detach(struct exynos_drm_private *priv,
-                                        struct device *dev)
-{
-       struct iommu_domain *domain = priv->mapping;
-
-       if (dev != priv->dma_dev)
-               iommu_detach_device(domain, dev);
-}
-#else
-#error Unsupported architecture and IOMMU/DMA-mapping glue code
-#endif
-
-int drm_create_iommu_mapping(struct drm_device *drm_dev);
-
-void drm_release_iommu_mapping(struct drm_device *drm_dev);
-
-int drm_iommu_attach_device(struct drm_device *drm_dev,
-                               struct device *subdrv_dev);
-
-void drm_iommu_detach_device(struct drm_device *dev_dev,
-                               struct device *subdrv_dev);
-
-static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
-{
-       struct exynos_drm_private *priv = drm_dev->dev_private;
-
-       return priv->mapping ? true : false;
-}
-
-#else
-
-static inline int drm_create_iommu_mapping(struct drm_device *drm_dev)
-{
-       return 0;
-}
-
-static inline void drm_release_iommu_mapping(struct drm_device *drm_dev)
-{
-}
-
-static inline int drm_iommu_attach_device(struct drm_device *drm_dev,
-                                               struct device *subdrv_dev)
-{
-       return 0;
-}
-
-static inline void drm_iommu_detach_device(struct drm_device *drm_dev,
-                                               struct device *subdrv_dev)
-{
-}
-
-static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
-{
-       return false;
-}
-
-#endif
-#endif
index a820a68429b9a8f56be132d251b2f4ea81f6c1b4..8d67b2a54be3b66f68e008d07a6203140bf2f7f4 100644 (file)
@@ -23,7 +23,6 @@
 #include <drm/exynos_drm.h>
 #include "regs-rotator.h"
 #include "exynos_drm_drv.h"
-#include "exynos_drm_iommu.h"
 #include "exynos_drm_ipp.h"
 
 /*
@@ -244,7 +243,7 @@ static int rotator_bind(struct device *dev, struct device *master, void *data)
        struct exynos_drm_ipp *ipp = &rot->ipp;
 
        rot->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,
@@ -263,7 +262,7 @@ static void rotator_unbind(struct device *dev, struct device *master,
        struct exynos_drm_ipp *ipp = &rot->ipp;
 
        exynos_drm_ipp_unregister(drm_dev, ipp);
-       drm_iommu_detach_device(rot->drm_dev, rot->dev);
+       exynos_drm_unregister_dma(rot->drm_dev, rot->dev);
 }
 
 static const struct component_ops rotator_component_ops = {
index cd66774e817d37a9d49aa61c40733192164531e5..71270efa64f3f35e7d983488b13202192936b245 100644 (file)
@@ -23,7 +23,6 @@
 #include "regs-scaler.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_drv.h"
-#include "exynos_drm_iommu.h"
 #include "exynos_drm_ipp.h"
 
 #define scaler_read(offset)            readl(scaler->regs + (offset))
@@ -452,7 +451,7 @@ static int scaler_bind(struct device *dev, struct device *master, void *data)
        struct exynos_drm_ipp *ipp = &scaler->ipp;
 
        scaler->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 |
@@ -473,7 +472,7 @@ static void scaler_unbind(struct device *dev, struct device *master,
        struct exynos_drm_ipp *ipp = &scaler->ipp;
 
        exynos_drm_ipp_unregister(drm_dev, ipp);
-       drm_iommu_detach_device(scaler->drm_dev, scaler->dev);
+       exynos_drm_unregister_dma(scaler->drm_dev, scaler->dev);
 }
 
 static const struct component_ops scaler_component_ops = {
index e3a4ecbc503b937e4d93a24450e9132024381db1..0573eab0e190f6d76d0e970a9b0b37c67c6dfe3a 100644 (file)
@@ -40,7 +40,6 @@
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_plane.h"
-#include "exynos_drm_iommu.h"
 
 #define MIXER_WIN_NR           3
 #define VP_DEFAULT_WIN         2
@@ -381,19 +380,16 @@ static void mixer_cfg_scan(struct mixer_context *ctx, int width, int height)
        mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_SCAN_MASK);
 }
 
-static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
+static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, struct drm_display_mode *mode)
 {
+       enum hdmi_quantization_range range = drm_default_rgb_quant_range(mode);
        u32 val;
 
-       switch (height) {
-       case 480:
-       case 576:
-               val = MXR_CFG_RGB601_0_255;
-               break;
-       case 720:
-       case 1080:
-       default:
-               val = MXR_CFG_RGB709_16_235;
+       if (mode->vdisplay < 720) {
+               val = MXR_CFG_RGB601;
+       } else {
+               val = MXR_CFG_RGB709;
+
                /* Configure the BT.709 CSC matrix for full range RGB. */
                mixer_reg_write(ctx, MXR_CM_COEFF_Y,
                        MXR_CSC_CT( 0.184,  0.614,  0.063) |
@@ -402,9 +398,13 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
                        MXR_CSC_CT(-0.102, -0.338,  0.440));
                mixer_reg_write(ctx, MXR_CM_COEFF_CR,
                        MXR_CSC_CT( 0.440, -0.399, -0.040));
-               break;
        }
 
+       if (range == HDMI_QUANTIZATION_RANGE_FULL)
+               val |= MXR_CFG_QUANT_RANGE_FULL;
+       else
+               val |= MXR_CFG_QUANT_RANGE_LIMITED;
+
        mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
 }
 
@@ -461,7 +461,7 @@ static void mixer_commit(struct mixer_context *ctx)
        struct drm_display_mode *mode = &ctx->crtc->base.state->adjusted_mode;
 
        mixer_cfg_scan(ctx, mode->hdisplay, mode->vdisplay);
-       mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
+       mixer_cfg_rgb_fmt(ctx, mode);
        mixer_run(ctx);
 }
 
@@ -878,12 +878,12 @@ static int mixer_initialize(struct mixer_context *mixer_ctx,
                }
        }
 
-       return drm_iommu_attach_device(drm_dev, mixer_ctx->dev);
+       return exynos_drm_register_dma(drm_dev, mixer_ctx->dev);
 }
 
 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
 {
-       drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
+       exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev);
 }
 
 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
index 19ad9e47945eb6f3fa3902fb8b80084fdbf7672f..63db6974bf14bc597c8df59f5198904cdf69071f 100644 (file)
 #define WINCONx_BURSTLEN_16WORD                (0x0 << 10)
 #define WINCONx_BURSTLEN_8WORD         (0x1 << 10)
 #define WINCONx_BURSTLEN_4WORD         (0x2 << 10)
+#define WINCONx_ALPHA_MUL_F            (1 << 7)
 #define WINCONx_BLD_PIX_F              (1 << 6)
 #define WINCONx_BPPMODE_MASK           (0xf << 2)
 #define WINCONx_BPPMODE_16BPP_565      (0x5 << 2)
 #define WINCONx_BPPMODE_16BPP_A4444    (0xe << 2)
 #define WINCONx_ALPHA_SEL_F            (1 << 1)
 #define WINCONx_ENWIN_F                        (1 << 0)
+#define WINCONx_BLEND_MODE_MASK                (0xc2)
 
 /* SHADOWCON */
 #define SHADOWCON_PROTECT_MASK         GENMASK(14, 10)
 #define SHADOWCON_Wx_PROTECT(n)                (1 << (10 + (n)))
 
+/* VIDOSDxC */
+#define VIDOSDxC_ALPHA0_RGB_MASK       (0xffffff)
+
 /* VIDOSDxD */
 #define VIDOSD_Wx_ALPHA_R_F(n)         (((n) & 0xff) << 16)
 #define VIDOSD_Wx_ALPHA_G_F(n)         (((n) & 0xff) << 8)
 #define CRCCTRL_CRCEN                  (0x1 << 0)
 #define CRCCTRL_MASK                   (0x7)
 
+/* BLENDCON */
+#define BLEND_NEW                      (1 << 0)
+
+/* BLENDERQx */
+#define BLENDERQ_ZERO                  0x0
+#define BLENDERQ_ONE                   0x1
+#define BLENDERQ_ALPHA_A               0x2
+#define BLENDERQ_ONE_MINUS_ALPHA_A     0x3
+#define BLENDERQ_ALPHA0                        0x6
+#define BLENDERQ_Q_FUNC_F(n)           (n << 18)
+#define BLENDERQ_P_FUNC_F(n)           (n << 12)
+#define BLENDERQ_B_FUNC_F(n)           (n << 6)
+#define BLENDERQ_A_FUNC_F(n)           (n << 0)
+
+/* BLENDCON */
+#define BLEND_NEW                      (1 << 0)
+
 #endif /* EXYNOS_REGS_DECON5433_H */
index d2b8194a07bfb93c71aa21d4df6a154178a1a8bb..5ff095b0c1b371cb6355a6f7ba96a8a30c2e89f8 100644 (file)
 /* bits for MXR_CFG */
 #define MXR_CFG_LAYER_UPDATE           (1 << 31)
 #define MXR_CFG_LAYER_UPDATE_COUNT_MASK (3 << 29)
-#define MXR_CFG_RGB601_0_255           (0 << 9)
-#define MXR_CFG_RGB601_16_235          (1 << 9)
-#define MXR_CFG_RGB709_0_255           (2 << 9)
-#define MXR_CFG_RGB709_16_235          (3 << 9)
+#define MXR_CFG_QUANT_RANGE_FULL       (0 << 9)
+#define MXR_CFG_QUANT_RANGE_LIMITED    (1 << 9)
+#define MXR_CFG_RGB601                 (0 << 10)
+#define MXR_CFG_RGB709                 (1 << 10)
+
 #define MXR_CFG_RGB_FMT_MASK           0x600
 #define MXR_CFG_OUT_YUV444             (0 << 8)
 #define MXR_CFG_OUT_RGB888             (1 << 8)