These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / exynos / exynos_drm_ipp.c
index b7f1cbc..67d2423 100644 (file)
@@ -45,9 +45,6 @@
 #define get_ipp_context(dev)   platform_get_drvdata(to_platform_device(dev))
 #define ipp_is_m2m_cmd(c)      (c == IPP_CMD_M2M)
 
-/* platform device pointer for ipp device. */
-static struct platform_device *exynos_drm_ipp_pdev;
-
 /*
  * A structure of event.
  *
@@ -102,30 +99,6 @@ static LIST_HEAD(exynos_drm_ippdrv_list);
 static DEFINE_MUTEX(exynos_drm_ippdrv_lock);
 static BLOCKING_NOTIFIER_HEAD(exynos_drm_ippnb_list);
 
-int exynos_platform_device_ipp_register(void)
-{
-       struct platform_device *pdev;
-
-       if (exynos_drm_ipp_pdev)
-               return -EEXIST;
-
-       pdev = platform_device_register_simple("exynos-drm-ipp", -1, NULL, 0);
-       if (IS_ERR(pdev))
-               return PTR_ERR(pdev);
-
-       exynos_drm_ipp_pdev = pdev;
-
-       return 0;
-}
-
-void exynos_platform_device_ipp_unregister(void)
-{
-       if (exynos_drm_ipp_pdev) {
-               platform_device_unregister(exynos_drm_ipp_pdev);
-               exynos_drm_ipp_pdev = NULL;
-       }
-}
-
 int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
 {
        mutex_lock(&exynos_drm_ippdrv_lock);
@@ -482,12 +455,11 @@ static int ipp_validate_mem_node(struct drm_device *drm_dev,
 {
        struct drm_exynos_ipp_config *ipp_cfg;
        unsigned int num_plane;
-       unsigned long min_size, size;
-       unsigned int bpp;
+       unsigned long size, buf_size = 0, plane_size, img_size = 0;
+       unsigned int bpp, width, height;
        int i;
 
-       /* The property id should already be varified */
-       ipp_cfg = &c_node->property.config[m_node->prop_id];
+       ipp_cfg = &c_node->property.config[m_node->ops_id];
        num_plane = drm_format_num_planes(ipp_cfg->fmt);
 
        /**
@@ -498,20 +470,45 @@ static int ipp_validate_mem_node(struct drm_device *drm_dev,
         * but it seems more than enough
         */
        for (i = 0; i < num_plane; ++i) {
-               if (!m_node->buf_info.handles[i]) {
-                       DRM_ERROR("invalid handle for plane %d\n", i);
-                       return -EINVAL;
-               }
+               width = ipp_cfg->sz.hsize;
+               height = ipp_cfg->sz.vsize;
                bpp = drm_format_plane_cpp(ipp_cfg->fmt, i);
-               min_size = (ipp_cfg->sz.hsize * ipp_cfg->sz.vsize * bpp) >> 3;
-               size = exynos_drm_gem_get_size(drm_dev,
-                                              m_node->buf_info.handles[i],
-                                              c_node->filp);
-               if (min_size > size) {
-                       DRM_ERROR("invalid size for plane %d\n", i);
-                       return -EINVAL;
+
+               /*
+                * The result of drm_format_plane_cpp() for chroma planes must
+                * be used with drm_format_xxxx_chroma_subsampling() for
+                * correct result.
+                */
+               if (i > 0) {
+                       width /= drm_format_horz_chroma_subsampling(
+                                                               ipp_cfg->fmt);
+                       height /= drm_format_vert_chroma_subsampling(
+                                                               ipp_cfg->fmt);
+               }
+               plane_size = width * height * bpp;
+               img_size += plane_size;
+
+               if (m_node->buf_info.handles[i]) {
+                       size = exynos_drm_gem_get_size(drm_dev,
+                                       m_node->buf_info.handles[i],
+                                       c_node->filp);
+                       if (plane_size > size) {
+                               DRM_ERROR(
+                                       "buffer %d is smaller than required\n",
+                                       i);
+                               return -EINVAL;
+                       }
+
+                       buf_size += size;
                }
        }
+
+       if (buf_size < img_size) {
+               DRM_ERROR("size of buffers(%lu) is smaller than image(%lu)\n",
+                       buf_size, img_size);
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -1625,12 +1622,10 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
                INIT_LIST_HEAD(&ippdrv->cmd_list);
                mutex_init(&ippdrv->cmd_lock);
 
-               if (is_drm_iommu_supported(drm_dev)) {
-                       ret = drm_iommu_attach_device(drm_dev, ippdrv->dev);
-                       if (ret) {
-                               DRM_ERROR("failed to activate iommu\n");
-                               goto err;
-                       }
+               ret = drm_iommu_attach_device(drm_dev, ippdrv->dev);
+               if (ret) {
+                       DRM_ERROR("failed to activate iommu\n");
+                       goto err;
                }
        }
 
@@ -1640,8 +1635,7 @@ err:
        /* get ipp driver entry */
        list_for_each_entry_continue_reverse(ippdrv, &exynos_drm_ippdrv_list,
                                                drv_list) {
-               if (is_drm_iommu_supported(drm_dev))
-                       drm_iommu_detach_device(drm_dev, ippdrv->dev);
+               drm_iommu_detach_device(drm_dev, ippdrv->dev);
 
                ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock,
                                ippdrv->prop_list.ipp_id);
@@ -1657,8 +1651,7 @@ static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
 
        /* get ipp driver entry */
        list_for_each_entry_safe(ippdrv, t, &exynos_drm_ippdrv_list, drv_list) {
-               if (is_drm_iommu_supported(drm_dev))
-                       drm_iommu_detach_device(drm_dev, ippdrv->dev);
+               drm_iommu_detach_device(drm_dev, ippdrv->dev);
 
                ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock,
                                ippdrv->prop_list.ipp_id);