aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/exynos/exynos_drm_rotator.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_rotator.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.c203
1 files changed, 110 insertions, 93 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index e9e83ef688f..f01fbb6dc1f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -10,7 +10,6 @@
*/
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -22,6 +21,7 @@
#include <drm/exynos_drm.h>
#include "regs-rotator.h"
#include "exynos_drm.h"
+#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h"
/*
@@ -158,8 +158,9 @@ static irqreturn_t rotator_irq_handler(int irq, void *arg)
rot->cur_buf_id[EXYNOS_DRM_OPS_DST];
queue_work(ippdrv->event_workq,
(struct work_struct *)event_work);
- } else
+ } else {
DRM_ERROR("the SFR is set illegally\n");
+ }
return IRQ_HANDLED;
}
@@ -244,7 +245,7 @@ static int rotator_src_set_size(struct device *dev, int swap,
/* Get format */
fmt = rotator_reg_get_fmt(rot);
if (!rotator_check_reg_fmt(fmt)) {
- DRM_ERROR("%s:invalid format.\n", __func__);
+ DRM_ERROR("invalid format.\n");
return -EINVAL;
}
@@ -287,7 +288,7 @@ static int rotator_src_set_addr(struct device *dev,
/* Get format */
fmt = rotator_reg_get_fmt(rot);
if (!rotator_check_reg_fmt(fmt)) {
- DRM_ERROR("%s:invalid format.\n", __func__);
+ DRM_ERROR("invalid format.\n");
return -EINVAL;
}
@@ -381,7 +382,7 @@ static int rotator_dst_set_size(struct device *dev, int swap,
/* Get format */
fmt = rotator_reg_get_fmt(rot);
if (!rotator_check_reg_fmt(fmt)) {
- DRM_ERROR("%s:invalid format.\n", __func__);
+ DRM_ERROR("invalid format.\n");
return -EINVAL;
}
@@ -422,7 +423,7 @@ static int rotator_dst_set_addr(struct device *dev,
/* Get format */
fmt = rotator_reg_get_fmt(rot);
if (!rotator_check_reg_fmt(fmt)) {
- DRM_ERROR("%s:invalid format.\n", __func__);
+ DRM_ERROR("invalid format.\n");
return -EINVAL;
}
@@ -469,15 +470,7 @@ static struct exynos_drm_ipp_ops rot_dst_ops = {
static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
{
- struct drm_exynos_ipp_prop_list *prop_list;
-
- DRM_DEBUG_KMS("%s\n", __func__);
-
- prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
- if (!prop_list) {
- DRM_ERROR("failed to alloc property list.\n");
- return -ENOMEM;
- }
+ struct drm_exynos_ipp_prop_list *prop_list = &ippdrv->prop_list;
prop_list->version = 1;
prop_list->flip = (1 << EXYNOS_DRM_FLIP_VERTICAL) |
@@ -490,8 +483,6 @@ static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
prop_list->crop = 0;
prop_list->scale = 0;
- ippdrv->prop_list = prop_list;
-
return 0;
}
@@ -502,7 +493,7 @@ static inline bool rotator_check_drm_fmt(u32 fmt)
case DRM_FORMAT_NV12:
return true;
default:
- DRM_DEBUG_KMS("%s:not support format\n", __func__);
+ DRM_DEBUG_KMS("not support format\n");
return false;
}
}
@@ -516,7 +507,7 @@ static inline bool rotator_check_drm_flip(enum drm_exynos_flip flip)
case EXYNOS_DRM_FLIP_BOTH:
return true;
default:
- DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
+ DRM_DEBUG_KMS("invalid flip\n");
return false;
}
}
@@ -536,19 +527,18 @@ static int rotator_ippdrv_check_property(struct device *dev,
/* Check format configuration */
if (src_config->fmt != dst_config->fmt) {
- DRM_DEBUG_KMS("%s:not support csc feature\n", __func__);
+ DRM_DEBUG_KMS("not support csc feature\n");
return -EINVAL;
}
if (!rotator_check_drm_fmt(dst_config->fmt)) {
- DRM_DEBUG_KMS("%s:invalid format\n", __func__);
+ DRM_DEBUG_KMS("invalid format\n");
return -EINVAL;
}
/* Check transform configuration */
if (src_config->degree != EXYNOS_DRM_DEGREE_0) {
- DRM_DEBUG_KMS("%s:not support source-side rotation\n",
- __func__);
+ DRM_DEBUG_KMS("not support source-side rotation\n");
return -EINVAL;
}
@@ -561,51 +551,47 @@ static int rotator_ippdrv_check_property(struct device *dev,
/* No problem */
break;
default:
- DRM_DEBUG_KMS("%s:invalid degree\n", __func__);
+ DRM_DEBUG_KMS("invalid degree\n");
return -EINVAL;
}
if (src_config->flip != EXYNOS_DRM_FLIP_NONE) {
- DRM_DEBUG_KMS("%s:not support source-side flip\n", __func__);
+ DRM_DEBUG_KMS("not support source-side flip\n");
return -EINVAL;
}
if (!rotator_check_drm_flip(dst_config->flip)) {
- DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
+ DRM_DEBUG_KMS("invalid flip\n");
return -EINVAL;
}
/* Check size configuration */
if ((src_pos->x + src_pos->w > src_sz->hsize) ||
(src_pos->y + src_pos->h > src_sz->vsize)) {
- DRM_DEBUG_KMS("%s:out of source buffer bound\n", __func__);
+ DRM_DEBUG_KMS("out of source buffer bound\n");
return -EINVAL;
}
if (swap) {
if ((dst_pos->x + dst_pos->h > dst_sz->vsize) ||
(dst_pos->y + dst_pos->w > dst_sz->hsize)) {
- DRM_DEBUG_KMS("%s:out of destination buffer bound\n",
- __func__);
+ DRM_DEBUG_KMS("out of destination buffer bound\n");
return -EINVAL;
}
if ((src_pos->w != dst_pos->h) || (src_pos->h != dst_pos->w)) {
- DRM_DEBUG_KMS("%s:not support scale feature\n",
- __func__);
+ DRM_DEBUG_KMS("not support scale feature\n");
return -EINVAL;
}
} else {
if ((dst_pos->x + dst_pos->w > dst_sz->hsize) ||
(dst_pos->y + dst_pos->h > dst_sz->vsize)) {
- DRM_DEBUG_KMS("%s:out of destination buffer bound\n",
- __func__);
+ DRM_DEBUG_KMS("out of destination buffer bound\n");
return -EINVAL;
}
if ((src_pos->w != dst_pos->w) || (src_pos->h != dst_pos->h)) {
- DRM_DEBUG_KMS("%s:not support scale feature\n",
- __func__);
+ DRM_DEBUG_KMS("not support scale feature\n");
return -EINVAL;
}
}
@@ -639,28 +625,101 @@ static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
return 0;
}
+static struct rot_limit_table rot_limit_tbl_4210 = {
+ .ycbcr420_2p = {
+ .min_w = 32,
+ .min_h = 32,
+ .max_w = SZ_64K,
+ .max_h = SZ_64K,
+ .align = 3,
+ },
+ .rgb888 = {
+ .min_w = 8,
+ .min_h = 8,
+ .max_w = SZ_16K,
+ .max_h = SZ_16K,
+ .align = 2,
+ },
+};
+
+static struct rot_limit_table rot_limit_tbl_4x12 = {
+ .ycbcr420_2p = {
+ .min_w = 32,
+ .min_h = 32,
+ .max_w = SZ_32K,
+ .max_h = SZ_32K,
+ .align = 3,
+ },
+ .rgb888 = {
+ .min_w = 8,
+ .min_h = 8,
+ .max_w = SZ_8K,
+ .max_h = SZ_8K,
+ .align = 2,
+ },
+};
+
+static struct rot_limit_table rot_limit_tbl_5250 = {
+ .ycbcr420_2p = {
+ .min_w = 32,
+ .min_h = 32,
+ .max_w = SZ_32K,
+ .max_h = SZ_32K,
+ .align = 3,
+ },
+ .rgb888 = {
+ .min_w = 8,
+ .min_h = 8,
+ .max_w = SZ_8K,
+ .max_h = SZ_8K,
+ .align = 1,
+ },
+};
+
+static const struct of_device_id exynos_rotator_match[] = {
+ {
+ .compatible = "samsung,exynos4210-rotator",
+ .data = &rot_limit_tbl_4210,
+ },
+ {
+ .compatible = "samsung,exynos4212-rotator",
+ .data = &rot_limit_tbl_4x12,
+ },
+ {
+ .compatible = "samsung,exynos5250-rotator",
+ .data = &rot_limit_tbl_5250,
+ },
+ {},
+};
+
static int rotator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rot_context *rot;
struct exynos_drm_ippdrv *ippdrv;
+ const struct of_device_id *match;
int ret;
+ if (!dev->of_node) {
+ dev_err(dev, "cannot find of_node.\n");
+ return -ENODEV;
+ }
+
rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL);
- if (!rot) {
- dev_err(dev, "failed to allocate rot\n");
+ if (!rot)
return -ENOMEM;
- }
- rot->limit_tbl = (struct rot_limit_table *)
- platform_get_device_id(pdev)->driver_data;
+ match = of_match_node(exynos_rotator_match, dev->of_node);
+ if (!match) {
+ dev_err(dev, "failed to match node\n");
+ return -ENODEV;
+ }
+ rot->limit_tbl = (struct rot_limit_table *)match->data;
rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- rot->regs = devm_request_and_ioremap(dev, rot->regs_res);
- if (!rot->regs) {
- dev_err(dev, "failed to map register\n");
- return -ENXIO;
- }
+ rot->regs = devm_ioremap_resource(dev, rot->regs_res);
+ if (IS_ERR(rot->regs))
+ return PTR_ERR(rot->regs);
rot->irq = platform_get_irq(pdev, 0);
if (rot->irq < 0) {
@@ -668,18 +727,17 @@ static int rotator_probe(struct platform_device *pdev)
return rot->irq;
}
- ret = request_threaded_irq(rot->irq, NULL, rotator_irq_handler,
- IRQF_ONESHOT, "drm_rotator", rot);
+ ret = devm_request_threaded_irq(dev, rot->irq, NULL,
+ rotator_irq_handler, IRQF_ONESHOT, "drm_rotator", rot);
if (ret < 0) {
dev_err(dev, "failed to request irq\n");
return ret;
}
rot->clock = devm_clk_get(dev, "rotator");
- if (IS_ERR_OR_NULL(rot->clock)) {
+ if (IS_ERR(rot->clock)) {
dev_err(dev, "failed to get clock\n");
- ret = PTR_ERR(rot->clock);
- goto err_clk_get;
+ return PTR_ERR(rot->clock);
}
pm_runtime_enable(dev);
@@ -696,7 +754,7 @@ static int rotator_probe(struct platform_device *pdev)
goto err_ippdrv_register;
}
- DRM_DEBUG_KMS("%s:ippdrv[0x%x]\n", __func__, (int)ippdrv);
+ DRM_DEBUG_KMS("ippdrv[0x%x]\n", (int)ippdrv);
platform_set_drvdata(pdev, rot);
@@ -711,10 +769,7 @@ static int rotator_probe(struct platform_device *pdev)
return 0;
err_ippdrv_register:
- devm_kfree(dev, ippdrv->prop_list);
pm_runtime_disable(dev);
-err_clk_get:
- free_irq(rot->irq, rot);
return ret;
}
@@ -724,45 +779,15 @@ static int rotator_remove(struct platform_device *pdev)
struct rot_context *rot = dev_get_drvdata(dev);
struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
- devm_kfree(dev, ippdrv->prop_list);
exynos_drm_ippdrv_unregister(ippdrv);
pm_runtime_disable(dev);
- free_irq(rot->irq, rot);
-
return 0;
}
-struct rot_limit_table rot_limit_tbl = {
- .ycbcr420_2p = {
- .min_w = 32,
- .min_h = 32,
- .max_w = SZ_32K,
- .max_h = SZ_32K,
- .align = 3,
- },
- .rgb888 = {
- .min_w = 8,
- .min_h = 8,
- .max_w = SZ_8K,
- .max_h = SZ_8K,
- .align = 2,
- },
-};
-
-struct platform_device_id rotator_driver_ids[] = {
- {
- .name = "exynos-rot",
- .driver_data = (unsigned long)&rot_limit_tbl,
- },
- {},
-};
-
static int rotator_clk_crtl(struct rot_context *rot, bool enable)
{
- DRM_DEBUG_KMS("%s\n", __func__);
-
if (enable) {
clk_enable(rot->clock);
rot->suspended = false;
@@ -780,8 +805,6 @@ static int rotator_suspend(struct device *dev)
{
struct rot_context *rot = dev_get_drvdata(dev);
- DRM_DEBUG_KMS("%s\n", __func__);
-
if (pm_runtime_suspended(dev))
return 0;
@@ -792,8 +815,6 @@ static int rotator_resume(struct device *dev)
{
struct rot_context *rot = dev_get_drvdata(dev);
- DRM_DEBUG_KMS("%s\n", __func__);
-
if (!pm_runtime_suspended(dev))
return rotator_clk_crtl(rot, true);
@@ -806,8 +827,6 @@ static int rotator_runtime_suspend(struct device *dev)
{
struct rot_context *rot = dev_get_drvdata(dev);
- DRM_DEBUG_KMS("%s\n", __func__);
-
return rotator_clk_crtl(rot, false);
}
@@ -815,8 +834,6 @@ static int rotator_runtime_resume(struct device *dev)
{
struct rot_context *rot = dev_get_drvdata(dev);
- DRM_DEBUG_KMS("%s\n", __func__);
-
return rotator_clk_crtl(rot, true);
}
#endif
@@ -830,10 +847,10 @@ static const struct dev_pm_ops rotator_pm_ops = {
struct platform_driver rotator_driver = {
.probe = rotator_probe,
.remove = rotator_remove,
- .id_table = rotator_driver_ids,
.driver = {
.name = "exynos-rot",
.owner = THIS_MODULE,
.pm = &rotator_pm_ops,
+ .of_match_table = exynos_rotator_match,
},
};