aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-12-16 00:49:46 -0500
committerDave Airlie <airlied@redhat.com>2012-12-16 00:49:46 -0500
commit2f3f24061c5c489074ad492bf694a5a76ebd8fc5 (patch)
treea02e00a7e98a4fa543b1e7fc4eda2fbd62d16b6d /drivers/gpu
parent652a187664902399d34f5b3a084fdbb51b2ca12f (diff)
parentf2646380655b32481b5e76c666e1793dfef184bd (diff)
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
Inki writes: "- add dmabuf attach/detach feature . This patch would resolve performance deterioration issue when v4l2-based driver is using the buffer imported from gem. - drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute . With gem allocation, kernel space mapping isn't allocated and also physical pages aren't mapped with the kernel space. The physical pages are mapped with kernel space though vmap function only for console framebuffer. - add the below two patches I missed. drm: exynos: moved exynos drm device registration to drm driver drm: exynos: moved exynos drm hdmi device registration to drm driver - add IPP subsystem framework and its-based device drivers. . This patch set includes fimc, rotator and gsc drivers to perform image scaling, rotation and color space conversion. - add runtime pm support to hdmi driver. - And fixups and cleanups." * 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (30 commits) drm/exynos: add gsc ipp driver drm/exynos: add rotator ipp driver drm/exynos: add fimc ipp driver drm/exynos: add iommu support for ipp drm/exynos: add ipp subsystem drm/exynos: support device tree for fimd drm/exynos: support extended screen coordinate of fimd drm/exynos: fix x, y coordinates for right bottom pixel drm/exynos: fix fb offset calculation for plane drm/exynos: hdmi: Fix potential NULL pointer dereference error drm/exynos: hdmi: Add CONFIG_OF and use of_match_ptr() macro drm/exynos: add support for hdmiphy power control for exynos5 drm/exynos: add runtime pm support for mixer drm/exynos: added runtime pm support for hdmi drm/exynos: fix allocation and cache mapping type drm/exynos: reorder framebuffer init sequence drm/exynos/iommu: fix return value check in drm_create_iommu_mapping() drm/exynos: remove unused vaddr member drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute drm/exynos: add exception codes to exynos_drm_fbdev_create() ...
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/exynos/Kconfig24
-rw-r--r--drivers/gpu/drm/exynos/Makefile4
-rw-r--r--drivers/gpu/drm/exynos/exynos_ddc.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_buf.c49
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dmabuf.c104
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c94
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h29
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.c25
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c40
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c42
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c2001
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.h37
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c140
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.h2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c1870
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.h38
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.c44
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.h2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_iommu.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c2060
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.h266
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.c855
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.h33
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c6
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c87
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmiphy.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c297
-rw-r--r--drivers/gpu/drm/exynos/regs-fimc.h669
-rw-r--r--drivers/gpu/drm/exynos/regs-gsc.h284
-rw-r--r--drivers/gpu/drm/exynos/regs-hdmi.h5
-rw-r--r--drivers/gpu/drm/exynos/regs-rotator.h73
33 files changed, 8942 insertions, 264 deletions
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 86fb75d3fcad..1d1f1e5e33f0 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -45,3 +45,27 @@ config DRM_EXYNOS_G2D
45 depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D 45 depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D
46 help 46 help
47 Choose this option if you want to use Exynos G2D for DRM. 47 Choose this option if you want to use Exynos G2D for DRM.
48
49config DRM_EXYNOS_IPP
50 bool "Exynos DRM IPP"
51 depends on DRM_EXYNOS
52 help
53 Choose this option if you want to use IPP feature for DRM.
54
55config DRM_EXYNOS_FIMC
56 bool "Exynos DRM FIMC"
57 depends on DRM_EXYNOS_IPP
58 help
59 Choose this option if you want to use Exynos FIMC for DRM.
60
61config DRM_EXYNOS_ROTATOR
62 bool "Exynos DRM Rotator"
63 depends on DRM_EXYNOS_IPP
64 help
65 Choose this option if you want to use Exynos Rotator for DRM.
66
67config DRM_EXYNOS_GSC
68 bool "Exynos DRM GSC"
69 depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5
70 help
71 Choose this option if you want to use Exynos GSC for DRM.
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 26813b8a5056..639b49e1ec05 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -16,5 +16,9 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \
16 exynos_drm_hdmi.o 16 exynos_drm_hdmi.o
17exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o 17exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
18exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o 18exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
19exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o
20exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC) += exynos_drm_fimc.o
21exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o
22exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o
19 23
20obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o 24obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
diff --git a/drivers/gpu/drm/exynos/exynos_ddc.c b/drivers/gpu/drm/exynos/exynos_ddc.c
index 37e6ec704e1d..bef43e0342a6 100644
--- a/drivers/gpu/drm/exynos/exynos_ddc.c
+++ b/drivers/gpu/drm/exynos/exynos_ddc.c
@@ -48,6 +48,7 @@ static struct i2c_device_id ddc_idtable[] = {
48 { }, 48 { },
49}; 49};
50 50
51#ifdef CONFIG_OF
51static struct of_device_id hdmiddc_match_types[] = { 52static struct of_device_id hdmiddc_match_types[] = {
52 { 53 {
53 .compatible = "samsung,exynos5-hdmiddc", 54 .compatible = "samsung,exynos5-hdmiddc",
@@ -55,12 +56,13 @@ static struct of_device_id hdmiddc_match_types[] = {
55 /* end node */ 56 /* end node */
56 } 57 }
57}; 58};
59#endif
58 60
59struct i2c_driver ddc_driver = { 61struct i2c_driver ddc_driver = {
60 .driver = { 62 .driver = {
61 .name = "exynos-hdmiddc", 63 .name = "exynos-hdmiddc",
62 .owner = THIS_MODULE, 64 .owner = THIS_MODULE,
63 .of_match_table = hdmiddc_match_types, 65 .of_match_table = of_match_ptr(hdmiddc_match_types),
64 }, 66 },
65 .id_table = ddc_idtable, 67 .id_table = ddc_idtable,
66 .probe = s5p_ddc_probe, 68 .probe = s5p_ddc_probe,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c
index 72bf97b96ba0..9601bad47a2e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_buf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c
@@ -34,7 +34,8 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
34 unsigned int flags, struct exynos_drm_gem_buf *buf) 34 unsigned int flags, struct exynos_drm_gem_buf *buf)
35{ 35{
36 int ret = 0; 36 int ret = 0;
37 enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS; 37 enum dma_attr attr;
38 unsigned int nr_pages;
38 39
39 DRM_DEBUG_KMS("%s\n", __FILE__); 40 DRM_DEBUG_KMS("%s\n", __FILE__);
40 41
@@ -45,44 +46,49 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
45 46
46 init_dma_attrs(&buf->dma_attrs); 47 init_dma_attrs(&buf->dma_attrs);
47 48
48 if (flags & EXYNOS_BO_NONCONTIG) 49 /*
50 * if EXYNOS_BO_CONTIG, fully physically contiguous memory
51 * region will be allocated else physically contiguous
52 * as possible.
53 */
54 if (flags & EXYNOS_BO_CONTIG)
55 dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &buf->dma_attrs);
56
57 /*
58 * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
59 * else cachable mapping.
60 */
61 if (flags & EXYNOS_BO_WC || !(flags & EXYNOS_BO_CACHABLE))
49 attr = DMA_ATTR_WRITE_COMBINE; 62 attr = DMA_ATTR_WRITE_COMBINE;
63 else
64 attr = DMA_ATTR_NON_CONSISTENT;
50 65
51 dma_set_attr(attr, &buf->dma_attrs); 66 dma_set_attr(attr, &buf->dma_attrs);
67 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
52 68
53 buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size, 69 buf->pages = dma_alloc_attrs(dev->dev, buf->size,
54 &buf->dma_addr, GFP_KERNEL, &buf->dma_attrs); 70 &buf->dma_addr, GFP_KERNEL, &buf->dma_attrs);
55 if (!buf->kvaddr) { 71 if (!buf->pages) {
56 DRM_ERROR("failed to allocate buffer.\n"); 72 DRM_ERROR("failed to allocate buffer.\n");
57 return -ENOMEM; 73 return -ENOMEM;
58 } 74 }
59 75
60 buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); 76 nr_pages = buf->size >> PAGE_SHIFT;
77 buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
61 if (!buf->sgt) { 78 if (!buf->sgt) {
62 DRM_ERROR("failed to allocate sg table.\n"); 79 DRM_ERROR("failed to get sg table.\n");
63 ret = -ENOMEM; 80 ret = -ENOMEM;
64 goto err_free_attrs; 81 goto err_free_attrs;
65 } 82 }
66 83
67 ret = dma_get_sgtable(dev->dev, buf->sgt, buf->kvaddr, buf->dma_addr, 84 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
68 buf->size);
69 if (ret < 0) {
70 DRM_ERROR("failed to get sgtable.\n");
71 goto err_free_sgt;
72 }
73
74 DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
75 (unsigned long)buf->kvaddr,
76 (unsigned long)buf->dma_addr, 85 (unsigned long)buf->dma_addr,
77 buf->size); 86 buf->size);
78 87
79 return ret; 88 return ret;
80 89
81err_free_sgt:
82 kfree(buf->sgt);
83 buf->sgt = NULL;
84err_free_attrs: 90err_free_attrs:
85 dma_free_attrs(dev->dev, buf->size, buf->kvaddr, 91 dma_free_attrs(dev->dev, buf->size, buf->pages,
86 (dma_addr_t)buf->dma_addr, &buf->dma_attrs); 92 (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
87 buf->dma_addr = (dma_addr_t)NULL; 93 buf->dma_addr = (dma_addr_t)NULL;
88 94
@@ -99,8 +105,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
99 return; 105 return;
100 } 106 }
101 107
102 DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", 108 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
103 (unsigned long)buf->kvaddr,
104 (unsigned long)buf->dma_addr, 109 (unsigned long)buf->dma_addr,
105 buf->size); 110 buf->size);
106 111
@@ -109,7 +114,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
109 kfree(buf->sgt); 114 kfree(buf->sgt);
110 buf->sgt = NULL; 115 buf->sgt = NULL;
111 116
112 dma_free_attrs(dev->dev, buf->size, buf->kvaddr, 117 dma_free_attrs(dev->dev, buf->size, buf->pages,
113 (dma_addr_t)buf->dma_addr, &buf->dma_attrs); 118 (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
114 buf->dma_addr = (dma_addr_t)NULL; 119 buf->dma_addr = (dma_addr_t)NULL;
115} 120}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index 539da9f4eb97..61d5a8402eb8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -30,63 +30,107 @@
30 30
31#include <linux/dma-buf.h> 31#include <linux/dma-buf.h>
32 32
33static struct sg_table *exynos_get_sgt(struct drm_device *drm_dev, 33struct exynos_drm_dmabuf_attachment {
34 struct exynos_drm_gem_buf *buf) 34 struct sg_table sgt;
35 enum dma_data_direction dir;
36};
37
38static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf,
39 struct device *dev,
40 struct dma_buf_attachment *attach)
35{ 41{
36 struct sg_table *sgt = NULL; 42 struct exynos_drm_dmabuf_attachment *exynos_attach;
37 int ret;
38 43
39 sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); 44 exynos_attach = kzalloc(sizeof(*exynos_attach), GFP_KERNEL);
40 if (!sgt) 45 if (!exynos_attach)
41 goto out; 46 return -ENOMEM;
42 47
43 ret = dma_get_sgtable(drm_dev->dev, sgt, buf->kvaddr, 48 exynos_attach->dir = DMA_NONE;
44 buf->dma_addr, buf->size); 49 attach->priv = exynos_attach;
45 if (ret < 0) {
46 DRM_ERROR("failed to get sgtable.\n");
47 goto err_free_sgt;
48 }
49 50
50 return sgt; 51 return 0;
52}
51 53
52err_free_sgt: 54static void exynos_gem_detach_dma_buf(struct dma_buf *dmabuf,
53 kfree(sgt); 55 struct dma_buf_attachment *attach)
54 sgt = NULL; 56{
55out: 57 struct exynos_drm_dmabuf_attachment *exynos_attach = attach->priv;
56 return NULL; 58 struct sg_table *sgt;
59
60 if (!exynos_attach)
61 return;
62
63 sgt = &exynos_attach->sgt;
64
65 if (exynos_attach->dir != DMA_NONE)
66 dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents,
67 exynos_attach->dir);
68
69 sg_free_table(sgt);
70 kfree(exynos_attach);
71 attach->priv = NULL;
57} 72}
58 73
59static struct sg_table * 74static struct sg_table *
60 exynos_gem_map_dma_buf(struct dma_buf_attachment *attach, 75 exynos_gem_map_dma_buf(struct dma_buf_attachment *attach,
61 enum dma_data_direction dir) 76 enum dma_data_direction dir)
62{ 77{
78 struct exynos_drm_dmabuf_attachment *exynos_attach = attach->priv;
63 struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv; 79 struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv;
64 struct drm_device *dev = gem_obj->base.dev; 80 struct drm_device *dev = gem_obj->base.dev;
65 struct exynos_drm_gem_buf *buf; 81 struct exynos_drm_gem_buf *buf;
82 struct scatterlist *rd, *wr;
66 struct sg_table *sgt = NULL; 83 struct sg_table *sgt = NULL;
67 int nents; 84 unsigned int i;
85 int nents, ret;
68 86
69 DRM_DEBUG_PRIME("%s\n", __FILE__); 87 DRM_DEBUG_PRIME("%s\n", __FILE__);
70 88
89 if (WARN_ON(dir == DMA_NONE))
90 return ERR_PTR(-EINVAL);
91
92 /* just return current sgt if already requested. */
93 if (exynos_attach->dir == dir)
94 return &exynos_attach->sgt;
95
96 /* reattaching is not allowed. */
97 if (WARN_ON(exynos_attach->dir != DMA_NONE))
98 return ERR_PTR(-EBUSY);
99
71 buf = gem_obj->buffer; 100 buf = gem_obj->buffer;
72 if (!buf) { 101 if (!buf) {
73 DRM_ERROR("buffer is null.\n"); 102 DRM_ERROR("buffer is null.\n");
74 return sgt; 103 return ERR_PTR(-ENOMEM);
104 }
105
106 sgt = &exynos_attach->sgt;
107
108 ret = sg_alloc_table(sgt, buf->sgt->orig_nents, GFP_KERNEL);
109 if (ret) {
110 DRM_ERROR("failed to alloc sgt.\n");
111 return ERR_PTR(-ENOMEM);
75 } 112 }
76 113
77 mutex_lock(&dev->struct_mutex); 114 mutex_lock(&dev->struct_mutex);
78 115
79 sgt = exynos_get_sgt(dev, buf); 116 rd = buf->sgt->sgl;
80 if (!sgt) 117 wr = sgt->sgl;
81 goto err_unlock; 118 for (i = 0; i < sgt->orig_nents; ++i) {
119 sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
120 rd = sg_next(rd);
121 wr = sg_next(wr);
122 }
82 123
83 nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir); 124 nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
84 if (!nents) { 125 if (!nents) {
85 DRM_ERROR("failed to map sgl with iommu.\n"); 126 DRM_ERROR("failed to map sgl with iommu.\n");
86 sgt = NULL; 127 sgt = ERR_PTR(-EIO);
87 goto err_unlock; 128 goto err_unlock;
88 } 129 }
89 130
131 exynos_attach->dir = dir;
132 attach->priv = exynos_attach;
133
90 DRM_DEBUG_PRIME("buffer size = 0x%lx\n", buf->size); 134 DRM_DEBUG_PRIME("buffer size = 0x%lx\n", buf->size);
91 135
92err_unlock: 136err_unlock:
@@ -98,11 +142,7 @@ static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
98 struct sg_table *sgt, 142 struct sg_table *sgt,
99 enum dma_data_direction dir) 143 enum dma_data_direction dir)
100{ 144{
101 dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir); 145 /* Nothing to do. */
102
103 sg_free_table(sgt);
104 kfree(sgt);
105 sgt = NULL;
106} 146}
107 147
108static void exynos_dmabuf_release(struct dma_buf *dmabuf) 148static void exynos_dmabuf_release(struct dma_buf *dmabuf)
@@ -164,6 +204,8 @@ static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf,
164} 204}
165 205
166static struct dma_buf_ops exynos_dmabuf_ops = { 206static struct dma_buf_ops exynos_dmabuf_ops = {
207 .attach = exynos_gem_attach_dma_buf,
208 .detach = exynos_gem_detach_dma_buf,
167 .map_dma_buf = exynos_gem_map_dma_buf, 209 .map_dma_buf = exynos_gem_map_dma_buf,
168 .unmap_dma_buf = exynos_gem_unmap_dma_buf, 210 .unmap_dma_buf = exynos_gem_unmap_dma_buf,
169 .kmap = exynos_gem_dmabuf_kmap, 211 .kmap = exynos_gem_dmabuf_kmap,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 2b287d2fc92e..e0a8e8024b01 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -40,6 +40,7 @@
40#include "exynos_drm_vidi.h" 40#include "exynos_drm_vidi.h"
41#include "exynos_drm_dmabuf.h" 41#include "exynos_drm_dmabuf.h"
42#include "exynos_drm_g2d.h" 42#include "exynos_drm_g2d.h"
43#include "exynos_drm_ipp.h"
43#include "exynos_drm_iommu.h" 44#include "exynos_drm_iommu.h"
44 45
45#define DRIVER_NAME "exynos" 46#define DRIVER_NAME "exynos"
@@ -50,6 +51,9 @@
50 51
51#define VBLANK_OFF_DELAY 50000 52#define VBLANK_OFF_DELAY 50000
52 53
54/* platform device pointer for eynos drm device. */
55static struct platform_device *exynos_drm_pdev;
56
53static int exynos_drm_load(struct drm_device *dev, unsigned long flags) 57static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
54{ 58{
55 struct exynos_drm_private *private; 59 struct exynos_drm_private *private;
@@ -246,6 +250,14 @@ static struct drm_ioctl_desc exynos_ioctls[] = {
246 exynos_g2d_set_cmdlist_ioctl, DRM_UNLOCKED | DRM_AUTH), 250 exynos_g2d_set_cmdlist_ioctl, DRM_UNLOCKED | DRM_AUTH),
247 DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, 251 DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC,
248 exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH), 252 exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH),
253 DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY,
254 exynos_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH),
255 DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY,
256 exynos_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH),
257 DRM_IOCTL_DEF_DRV(EXYNOS_IPP_QUEUE_BUF,
258 exynos_drm_ipp_queue_buf, DRM_UNLOCKED | DRM_AUTH),
259 DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CMD_CTRL,
260 exynos_drm_ipp_cmd_ctrl, DRM_UNLOCKED | DRM_AUTH),
249}; 261};
250 262
251static const struct file_operations exynos_drm_driver_fops = { 263static const struct file_operations exynos_drm_driver_fops = {
@@ -296,6 +308,7 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
296{ 308{
297 DRM_DEBUG_DRIVER("%s\n", __FILE__); 309 DRM_DEBUG_DRIVER("%s\n", __FILE__);
298 310
311 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
299 exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls); 312 exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
300 313
301 return drm_platform_init(&exynos_drm_driver, pdev); 314 return drm_platform_init(&exynos_drm_driver, pdev);
@@ -341,6 +354,10 @@ static int __init exynos_drm_init(void)
341 ret = platform_driver_register(&exynos_drm_common_hdmi_driver); 354 ret = platform_driver_register(&exynos_drm_common_hdmi_driver);
342 if (ret < 0) 355 if (ret < 0)
343 goto out_common_hdmi; 356 goto out_common_hdmi;
357
358 ret = exynos_platform_device_hdmi_register();
359 if (ret < 0)
360 goto out_common_hdmi_dev;
344#endif 361#endif
345 362
346#ifdef CONFIG_DRM_EXYNOS_VIDI 363#ifdef CONFIG_DRM_EXYNOS_VIDI
@@ -355,24 +372,80 @@ static int __init exynos_drm_init(void)
355 goto out_g2d; 372 goto out_g2d;
356#endif 373#endif
357 374
375#ifdef CONFIG_DRM_EXYNOS_FIMC
376 ret = platform_driver_register(&fimc_driver);
377 if (ret < 0)
378 goto out_fimc;
379#endif
380
381#ifdef CONFIG_DRM_EXYNOS_ROTATOR
382 ret = platform_driver_register(&rotator_driver);
383 if (ret < 0)
384 goto out_rotator;
385#endif
386
387#ifdef CONFIG_DRM_EXYNOS_GSC
388 ret = platform_driver_register(&gsc_driver);
389 if (ret < 0)
390 goto out_gsc;
391#endif
392
393#ifdef CONFIG_DRM_EXYNOS_IPP
394 ret = platform_driver_register(&ipp_driver);
395 if (ret < 0)
396 goto out_ipp;
397#endif
398
358 ret = platform_driver_register(&exynos_drm_platform_driver); 399 ret = platform_driver_register(&exynos_drm_platform_driver);
359 if (ret < 0) 400 if (ret < 0)
401 goto out_drm;
402
403 exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1,
404 NULL, 0);
405 if (IS_ERR_OR_NULL(exynos_drm_pdev)) {
406 ret = PTR_ERR(exynos_drm_pdev);
360 goto out; 407 goto out;
408 }
361 409
362 return 0; 410 return 0;
363 411
364out: 412out:
413 platform_driver_unregister(&exynos_drm_platform_driver);
414
415out_drm:
416#ifdef CONFIG_DRM_EXYNOS_IPP
417 platform_driver_unregister(&ipp_driver);
418out_ipp:
419#endif
420
421#ifdef CONFIG_DRM_EXYNOS_GSC
422 platform_driver_unregister(&gsc_driver);
423out_gsc:
424#endif
425
426#ifdef CONFIG_DRM_EXYNOS_ROTATOR
427 platform_driver_unregister(&rotator_driver);
428out_rotator:
429#endif
430
431#ifdef CONFIG_DRM_EXYNOS_FIMC
432 platform_driver_unregister(&fimc_driver);
433out_fimc:
434#endif
435
365#ifdef CONFIG_DRM_EXYNOS_G2D 436#ifdef CONFIG_DRM_EXYNOS_G2D
366 platform_driver_unregister(&g2d_driver); 437 platform_driver_unregister(&g2d_driver);
367out_g2d: 438out_g2d:
368#endif 439#endif
369 440
370#ifdef CONFIG_DRM_EXYNOS_VIDI 441#ifdef CONFIG_DRM_EXYNOS_VIDI
371out_vidi:
372 platform_driver_unregister(&vidi_driver); 442 platform_driver_unregister(&vidi_driver);
443out_vidi:
373#endif 444#endif
374 445
375#ifdef CONFIG_DRM_EXYNOS_HDMI 446#ifdef CONFIG_DRM_EXYNOS_HDMI
447 exynos_platform_device_hdmi_unregister();
448out_common_hdmi_dev:
376 platform_driver_unregister(&exynos_drm_common_hdmi_driver); 449 platform_driver_unregister(&exynos_drm_common_hdmi_driver);
377out_common_hdmi: 450out_common_hdmi:
378 platform_driver_unregister(&mixer_driver); 451 platform_driver_unregister(&mixer_driver);
@@ -392,13 +465,32 @@ static void __exit exynos_drm_exit(void)
392{ 465{
393 DRM_DEBUG_DRIVER("%s\n", __FILE__); 466 DRM_DEBUG_DRIVER("%s\n", __FILE__);
394 467
468 platform_device_unregister(exynos_drm_pdev);
469
395 platform_driver_unregister(&exynos_drm_platform_driver); 470 platform_driver_unregister(&exynos_drm_platform_driver);
396 471
472#ifdef CONFIG_DRM_EXYNOS_IPP
473 platform_driver_unregister(&ipp_driver);
474#endif
475
476#ifdef CONFIG_DRM_EXYNOS_GSC
477 platform_driver_unregister(&gsc_driver);
478#endif
479
480#ifdef CONFIG_DRM_EXYNOS_ROTATOR
481 platform_driver_unregister(&rotator_driver);
482#endif
483
484#ifdef CONFIG_DRM_EXYNOS_FIMC
485 platform_driver_unregister(&fimc_driver);
486#endif
487
397#ifdef CONFIG_DRM_EXYNOS_G2D 488#ifdef CONFIG_DRM_EXYNOS_G2D
398 platform_driver_unregister(&g2d_driver); 489 platform_driver_unregister(&g2d_driver);
399#endif 490#endif
400 491
401#ifdef CONFIG_DRM_EXYNOS_HDMI 492#ifdef CONFIG_DRM_EXYNOS_HDMI
493 exynos_platform_device_hdmi_unregister();
402 platform_driver_unregister(&exynos_drm_common_hdmi_driver); 494 platform_driver_unregister(&exynos_drm_common_hdmi_driver);
403 platform_driver_unregister(&mixer_driver); 495 platform_driver_unregister(&mixer_driver);
404 platform_driver_unregister(&hdmi_driver); 496 platform_driver_unregister(&hdmi_driver);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 9c9c2dc75828..f5a97745bf93 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -74,8 +74,6 @@ enum exynos_drm_output_type {
74 * @commit: apply hardware specific overlay data to registers. 74 * @commit: apply hardware specific overlay data to registers.
75 * @enable: enable hardware specific overlay. 75 * @enable: enable hardware specific overlay.
76 * @disable: disable hardware specific overlay. 76 * @disable: disable hardware specific overlay.
77 * @wait_for_vblank: wait for vblank interrupt to make sure that
78 * hardware overlay is disabled.
79 */ 77 */
80struct exynos_drm_overlay_ops { 78struct exynos_drm_overlay_ops {
81 void (*mode_set)(struct device *subdrv_dev, 79 void (*mode_set)(struct device *subdrv_dev,
@@ -83,7 +81,6 @@ struct exynos_drm_overlay_ops {
83 void (*commit)(struct device *subdrv_dev, int zpos); 81 void (*commit)(struct device *subdrv_dev, int zpos);
84 void (*enable)(struct device *subdrv_dev, int zpos); 82 void (*enable)(struct device *subdrv_dev, int zpos);
85 void (*disable)(struct device *subdrv_dev, int zpos); 83 void (*disable)(struct device *subdrv_dev, int zpos);
86 void (*wait_for_vblank)(struct device *subdrv_dev);
87}; 84};
88 85
89/* 86/*
@@ -110,7 +107,6 @@ struct exynos_drm_overlay_ops {
110 * @pixel_format: fourcc pixel format of this overlay 107 * @pixel_format: fourcc pixel format of this overlay
111 * @dma_addr: array of bus(accessed by dma) address to the memory region 108 * @dma_addr: array of bus(accessed by dma) address to the memory region
112 * allocated for a overlay. 109 * allocated for a overlay.
113 * @vaddr: array of virtual memory addresss to this overlay.
114 * @zpos: order of overlay layer(z position). 110 * @zpos: order of overlay layer(z position).
115 * @default_win: a window to be enabled. 111 * @default_win: a window to be enabled.
116 * @color_key: color key on or off. 112 * @color_key: color key on or off.
@@ -142,7 +138,6 @@ struct exynos_drm_overlay {
142 unsigned int pitch; 138 unsigned int pitch;
143 uint32_t pixel_format; 139 uint32_t pixel_format;
144 dma_addr_t dma_addr[MAX_FB_BUFFER]; 140 dma_addr_t dma_addr[MAX_FB_BUFFER];
145 void __iomem *vaddr[MAX_FB_BUFFER];
146 int zpos; 141 int zpos;
147 142
148 bool default_win; 143 bool default_win;
@@ -186,6 +181,8 @@ struct exynos_drm_display_ops {
186 * @commit: set current hw specific display mode to hw. 181 * @commit: set current hw specific display mode to hw.
187 * @enable_vblank: specific driver callback for enabling vblank interrupt. 182 * @enable_vblank: specific driver callback for enabling vblank interrupt.
188 * @disable_vblank: specific driver callback for disabling vblank interrupt. 183 * @disable_vblank: specific driver callback for disabling vblank interrupt.
184 * @wait_for_vblank: wait for vblank interrupt to make sure that
185 * hardware overlay is updated.
189 */ 186 */
190struct exynos_drm_manager_ops { 187struct exynos_drm_manager_ops {
191 void (*dpms)(struct device *subdrv_dev, int mode); 188 void (*dpms)(struct device *subdrv_dev, int mode);
@@ -200,6 +197,7 @@ struct exynos_drm_manager_ops {
200 void (*commit)(struct device *subdrv_dev); 197 void (*commit)(struct device *subdrv_dev);
201 int (*enable_vblank)(struct device *subdrv_dev); 198 int (*enable_vblank)(struct device *subdrv_dev);
202 void (*disable_vblank)(struct device *subdrv_dev); 199 void (*disable_vblank)(struct device *subdrv_dev);
200 void (*wait_for_vblank)(struct device *subdrv_dev);
203}; 201};
204 202
205/* 203/*
@@ -234,8 +232,14 @@ struct exynos_drm_g2d_private {
234 struct list_head userptr_list; 232 struct list_head userptr_list;
235}; 233};
236 234
235struct exynos_drm_ipp_private {
236 struct device *dev;
237 struct list_head event_list;
238};
239
237struct drm_exynos_file_private { 240struct drm_exynos_file_private {
238 struct exynos_drm_g2d_private *g2d_priv; 241 struct exynos_drm_g2d_private *g2d_priv;
242 struct exynos_drm_ipp_private *ipp_priv;
239}; 243};
240 244
241/* 245/*
@@ -328,10 +332,25 @@ int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv);
328int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file); 332int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file);
329void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file); 333void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file);
330 334
335/*
336 * this function registers exynos drm hdmi platform device. It ensures only one
337 * instance of the device is created.
338 */
339extern int exynos_platform_device_hdmi_register(void);
340
341/*
342 * this function unregisters exynos drm hdmi platform device if it exists.
343 */
344void exynos_platform_device_hdmi_unregister(void);
345
331extern struct platform_driver fimd_driver; 346extern struct platform_driver fimd_driver;
332extern struct platform_driver hdmi_driver; 347extern struct platform_driver hdmi_driver;
333extern struct platform_driver mixer_driver; 348extern struct platform_driver mixer_driver;
334extern struct platform_driver exynos_drm_common_hdmi_driver; 349extern struct platform_driver exynos_drm_common_hdmi_driver;
335extern struct platform_driver vidi_driver; 350extern struct platform_driver vidi_driver;
336extern struct platform_driver g2d_driver; 351extern struct platform_driver g2d_driver;
352extern struct platform_driver fimc_driver;
353extern struct platform_driver rotator_driver;
354extern struct platform_driver gsc_driver;
355extern struct platform_driver ipp_driver;
337#endif 356#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index e5001dd85afc..301485215a70 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -237,8 +237,7 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
237void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb) 237void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb)
238{ 238{
239 struct exynos_drm_encoder *exynos_encoder; 239 struct exynos_drm_encoder *exynos_encoder;
240 struct exynos_drm_overlay_ops *overlay_ops; 240 struct exynos_drm_manager_ops *ops;
241 struct exynos_drm_manager *manager;
242 struct drm_device *dev = fb->dev; 241 struct drm_device *dev = fb->dev;
243 struct drm_encoder *encoder; 242 struct drm_encoder *encoder;
244 243
@@ -248,21 +247,15 @@ void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb)
248 */ 247 */
249 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 248 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
250 exynos_encoder = to_exynos_encoder(encoder); 249 exynos_encoder = to_exynos_encoder(encoder);
251 250 ops = exynos_encoder->manager->ops;
252 /* if exynos was disabled, just ignor it. */
253 if (exynos_encoder->dpms > DRM_MODE_DPMS_ON)
254 continue;
255
256 manager = exynos_encoder->manager;
257 overlay_ops = manager->overlay_ops;
258 251
259 /* 252 /*
260 * wait for vblank interrupt 253 * wait for vblank interrupt
261 * - this makes sure that overlay data are updated to 254 * - this makes sure that overlay data are updated to
262 * real hardware. 255 * real hardware.
263 */ 256 */
264 if (overlay_ops->wait_for_vblank) 257 if (ops->wait_for_vblank)
265 overlay_ops->wait_for_vblank(manager->dev); 258 ops->wait_for_vblank(exynos_encoder->manager->dev);
266 } 259 }
267} 260}
268 261
@@ -538,14 +531,4 @@ void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
538 531
539 if (overlay_ops && overlay_ops->disable) 532 if (overlay_ops && overlay_ops->disable)
540 overlay_ops->disable(manager->dev, zpos); 533 overlay_ops->disable(manager->dev, zpos);
541
542 /*
543 * wait for vblank interrupt
544 * - this makes sure that hardware overlay is disabled to avoid
545 * for the dma accesses to memory after gem buffer was released
546 * because the setting for disabling the overlay will be updated
547 * at vsync.
548 */
549 if (overlay_ops && overlay_ops->wait_for_vblank)
550 overlay_ops->wait_for_vblank(manager->dev);
551} 534}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 7413f4b729b0..5426cc5a5e8d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -177,6 +177,7 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
177 return ERR_PTR(-ENOMEM); 177 return ERR_PTR(-ENOMEM);
178 } 178 }
179 179
180 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
180 exynos_fb->exynos_gem_obj[0] = exynos_gem_obj; 181 exynos_fb->exynos_gem_obj[0] = exynos_gem_obj;
181 182
182 ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); 183 ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
@@ -185,8 +186,6 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
185 return ERR_PTR(ret); 186 return ERR_PTR(ret);
186 } 187 }
187 188
188 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
189
190 return &exynos_fb->fb; 189 return &exynos_fb->fb;
191} 190}
192 191
@@ -232,9 +231,8 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
232 struct drm_mode_fb_cmd2 *mode_cmd) 231 struct drm_mode_fb_cmd2 *mode_cmd)
233{ 232{
234 struct drm_gem_object *obj; 233 struct drm_gem_object *obj;
235 struct drm_framebuffer *fb;
236 struct exynos_drm_fb *exynos_fb; 234 struct exynos_drm_fb *exynos_fb;
237 int i; 235 int i, ret;
238 236
239 DRM_DEBUG_KMS("%s\n", __FILE__); 237 DRM_DEBUG_KMS("%s\n", __FILE__);
240 238
@@ -244,13 +242,14 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
244 return ERR_PTR(-ENOENT); 242 return ERR_PTR(-ENOENT);
245 } 243 }
246 244
247 fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj); 245 exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
248 if (IS_ERR(fb)) { 246 if (!exynos_fb) {
249 drm_gem_object_unreference_unlocked(obj); 247 DRM_ERROR("failed to allocate exynos drm framebuffer\n");
250 return fb; 248 return ERR_PTR(-ENOMEM);
251 } 249 }
252 250
253 exynos_fb = to_exynos_fb(fb); 251 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
252 exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
254 exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd); 253 exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd);
255 254
256 DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); 255 DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt);
@@ -263,7 +262,7 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
263 mode_cmd->handles[i]); 262 mode_cmd->handles[i]);
264 if (!obj) { 263 if (!obj) {
265 DRM_ERROR("failed to lookup gem object\n"); 264 DRM_ERROR("failed to lookup gem object\n");
266 exynos_drm_fb_destroy(fb); 265 kfree(exynos_fb);
267 return ERR_PTR(-ENOENT); 266 return ERR_PTR(-ENOENT);
268 } 267 }
269 268
@@ -272,14 +271,27 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
272 ret = check_fb_gem_memory_type(dev, exynos_gem_obj); 271 ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
273 if (ret < 0) { 272 if (ret < 0) {
274 DRM_ERROR("cannot use this gem memory type for fb.\n"); 273 DRM_ERROR("cannot use this gem memory type for fb.\n");
275 exynos_drm_fb_destroy(fb); 274 kfree(exynos_fb);
276 return ERR_PTR(ret); 275 return ERR_PTR(ret);
277 } 276 }
278 277
279 exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); 278 exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);
280 } 279 }
281 280
282 return fb; 281 ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
282 if (ret) {
283 for (i = 0; i < exynos_fb->buf_cnt; i++) {
284 struct exynos_drm_gem_obj *gem_obj;
285
286 gem_obj = exynos_fb->exynos_gem_obj[i];
287 drm_gem_object_unreference_unlocked(&gem_obj->base);
288 }
289
290 kfree(exynos_fb);
291 return ERR_PTR(ret);
292 }
293
294 return &exynos_fb->fb;
283} 295}
284 296
285struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, 297struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
@@ -297,9 +309,7 @@ struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
297 if (!buffer) 309 if (!buffer)
298 return NULL; 310 return NULL;
299 311
300 DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", 312 DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr);
301 (unsigned long)buffer->kvaddr,
302 (unsigned long)buffer->dma_addr);
303 313
304 return buffer; 314 return buffer;
305} 315}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index a2232792e0c0..f433eb7533a9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -65,7 +65,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
65 if (vm_size > buffer->size) 65 if (vm_size > buffer->size)
66 return -EINVAL; 66 return -EINVAL;
67 67
68 ret = dma_mmap_attrs(helper->dev->dev, vma, buffer->kvaddr, 68 ret = dma_mmap_attrs(helper->dev->dev, vma, buffer->pages,
69 buffer->dma_addr, buffer->size, &buffer->dma_attrs); 69 buffer->dma_addr, buffer->size, &buffer->dma_attrs);
70 if (ret < 0) { 70 if (ret < 0) {
71 DRM_ERROR("failed to mmap.\n"); 71 DRM_ERROR("failed to mmap.\n");
@@ -109,6 +109,17 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
109 return -EFAULT; 109 return -EFAULT;
110 } 110 }
111 111
112 /* map pages with kernel virtual space. */
113 if (!buffer->kvaddr) {
114 unsigned int nr_pages = buffer->size >> PAGE_SHIFT;
115 buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP,
116 pgprot_writecombine(PAGE_KERNEL));
117 if (!buffer->kvaddr) {
118 DRM_ERROR("failed to map pages to kernel space.\n");
119 return -EIO;
120 }
121 }
122
112 /* buffer count to framebuffer always is 1 at booting time. */ 123 /* buffer count to framebuffer always is 1 at booting time. */
113 exynos_drm_fb_set_buf_cnt(fb, 1); 124 exynos_drm_fb_set_buf_cnt(fb, 1);
114 125
@@ -164,7 +175,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
164 exynos_gem_obj = exynos_drm_gem_create(dev, 0, size); 175 exynos_gem_obj = exynos_drm_gem_create(dev, 0, size);
165 if (IS_ERR(exynos_gem_obj)) { 176 if (IS_ERR(exynos_gem_obj)) {
166 ret = PTR_ERR(exynos_gem_obj); 177 ret = PTR_ERR(exynos_gem_obj);
167 goto out; 178 goto err_release_framebuffer;
168 } 179 }
169 180
170 exynos_fbdev->exynos_gem_obj = exynos_gem_obj; 181 exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
@@ -174,7 +185,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
174 if (IS_ERR_OR_NULL(helper->fb)) { 185 if (IS_ERR_OR_NULL(helper->fb)) {
175 DRM_ERROR("failed to create drm framebuffer.\n"); 186 DRM_ERROR("failed to create drm framebuffer.\n");
176 ret = PTR_ERR(helper->fb); 187 ret = PTR_ERR(helper->fb);
177 goto out; 188 goto err_destroy_gem;
178 } 189 }
179 190
180 helper->fbdev = fbi; 191 helper->fbdev = fbi;
@@ -186,14 +197,24 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
186 ret = fb_alloc_cmap(&fbi->cmap, 256, 0); 197 ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
187 if (ret) { 198 if (ret) {
188 DRM_ERROR("failed to allocate cmap.\n"); 199 DRM_ERROR("failed to allocate cmap.\n");
189 goto out; 200 goto err_destroy_framebuffer;
190 } 201 }
191 202
192 ret = exynos_drm_fbdev_update(helper, helper->fb); 203 ret = exynos_drm_fbdev_update(helper, helper->fb);
193 if (ret < 0) { 204 if (ret < 0)
194 fb_dealloc_cmap(&fbi->cmap); 205 goto err_dealloc_cmap;
195 goto out; 206
196 } 207 mutex_unlock(&dev->struct_mutex);
208 return ret;
209
210err_dealloc_cmap:
211 fb_dealloc_cmap(&fbi->cmap);
212err_destroy_framebuffer:
213 drm_framebuffer_cleanup(helper->fb);
214err_destroy_gem:
215 exynos_drm_gem_destroy(exynos_gem_obj);
216err_release_framebuffer:
217 framebuffer_release(fbi);
197 218
198/* 219/*
199 * if failed, all resources allocated above would be released by 220 * if failed, all resources allocated above would be released by
@@ -295,8 +316,13 @@ err_init:
295static void exynos_drm_fbdev_destroy(struct drm_device *dev, 316static void exynos_drm_fbdev_destroy(struct drm_device *dev,
296 struct drm_fb_helper *fb_helper) 317 struct drm_fb_helper *fb_helper)
297{ 318{
319 struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper);
320 struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj;
298 struct drm_framebuffer *fb; 321 struct drm_framebuffer *fb;
299 322
323 if (exynos_gem_obj->buffer->kvaddr)
324 vunmap(exynos_gem_obj->buffer->kvaddr);
325
300 /* release drm framebuffer and real buffer */ 326 /* release drm framebuffer and real buffer */
301 if (fb_helper->fb && fb_helper->fb->funcs) { 327 if (fb_helper->fb && fb_helper->fb->funcs) {
302 fb = fb_helper->fb; 328 fb = fb_helper->fb;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
new file mode 100644
index 000000000000..61ea24296b52
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -0,0 +1,2001 @@
1/*
2 * Copyright (C) 2012 Samsung Electronics Co.Ltd
3 * Authors:
4 * Eunchul Kim <chulspro.kim@samsung.com>
5 * Jinyoung Jeon <jy0.jeon@samsung.com>
6 * Sangmin Lee <lsmin.lee@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/clk.h>
18#include <linux/pm_runtime.h>
19#include <plat/map-base.h>
20
21#include <drm/drmP.h>
22#include <drm/exynos_drm.h>
23#include "regs-fimc.h"
24#include "exynos_drm_ipp.h"
25#include "exynos_drm_fimc.h"
26
27/*
28 * FIMC is stand for Fully Interactive Mobile Camera and
29 * supports image scaler/rotator and input/output DMA operations.
30 * input DMA reads image data from the memory.
31 * output DMA writes image data to memory.
32 * FIMC supports image rotation and image effect functions.
33 *
34 * M2M operation : supports crop/scale/rotation/csc so on.
35 * Memory ----> FIMC H/W ----> Memory.
36 * Writeback operation : supports cloned screen with FIMD.
37 * FIMD ----> FIMC H/W ----> Memory.
38 * Output operation : supports direct display using local path.
39 * Memory ----> FIMC H/W ----> FIMD.
40 */
41
42/*
43 * TODO
44 * 1. check suspend/resume api if needed.
45 * 2. need to check use case platform_device_id.
46 * 3. check src/dst size with, height.
47 * 4. added check_prepare api for right register.
48 * 5. need to add supported list in prop_list.
49 * 6. check prescaler/scaler optimization.
50 */
51
52#define FIMC_MAX_DEVS 4
53#define FIMC_MAX_SRC 2
54#define FIMC_MAX_DST 32
55#define FIMC_SHFACTOR 10
56#define FIMC_BUF_STOP 1
57#define FIMC_BUF_START 2
58#define FIMC_REG_SZ 32
59#define FIMC_WIDTH_ITU_709 1280
60#define FIMC_REFRESH_MAX 60
61#define FIMC_REFRESH_MIN 12
62#define FIMC_CROP_MAX 8192
63#define FIMC_CROP_MIN 32
64#define FIMC_SCALE_MAX 4224
65#define FIMC_SCALE_MIN 32
66
67#define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
68#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
69 struct fimc_context, ippdrv);
70#define fimc_read(offset) readl(ctx->regs + (offset))
71#define fimc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
72
73enum fimc_wb {
74 FIMC_WB_NONE,
75 FIMC_WB_A,
76 FIMC_WB_B,
77};
78
79/*
80 * A structure of scaler.
81 *
82 * @range: narrow, wide.
83 * @bypass: unused scaler path.
84 * @up_h: horizontal scale up.
85 * @up_v: vertical scale up.
86 * @hratio: horizontal ratio.
87 * @vratio: vertical ratio.
88 */
89struct fimc_scaler {
90 bool range;
91 bool bypass;
92 bool up_h;
93 bool up_v;
94 u32 hratio;
95 u32 vratio;
96};
97
98/*
99 * A structure of scaler capability.
100 *
101 * find user manual table 43-1.
102 * @in_hori: scaler input horizontal size.
103 * @bypass: scaler bypass mode.
104 * @dst_h_wo_rot: target horizontal size without output rotation.
105 * @dst_h_rot: target horizontal size with output rotation.
106 * @rl_w_wo_rot: real width without input rotation.
107 * @rl_h_rot: real height without output rotation.
108 */
109struct fimc_capability {
110 /* scaler */
111 u32 in_hori;
112 u32 bypass;
113 /* output rotator */
114 u32 dst_h_wo_rot;
115 u32 dst_h_rot;
116 /* input rotator */
117 u32 rl_w_wo_rot;
118 u32 rl_h_rot;
119};
120
121/*
122 * A structure of fimc driver data.
123 *
124 * @parent_clk: name of parent clock.
125 */
126struct fimc_driverdata {
127 char *parent_clk;
128};
129
130/*
131 * A structure of fimc context.
132 *
133 * @ippdrv: prepare initialization using ippdrv.
134 * @regs_res: register resources.
135 * @regs: memory mapped io registers.
136 * @lock: locking of operations.
137 * @sclk_fimc_clk: fimc source clock.
138 * @fimc_clk: fimc clock.
139 * @wb_clk: writeback a clock.
140 * @wb_b_clk: writeback b clock.
141 * @sc: scaler infomations.
142 * @odr: ordering of YUV.
143 * @ver: fimc version.
144 * @pol: porarity of writeback.
145 * @id: fimc id.
146 * @irq: irq number.
147 * @suspended: qos operations.
148 */
149struct fimc_context {
150 struct exynos_drm_ippdrv ippdrv;
151 struct resource *regs_res;
152 void __iomem *regs;
153 struct mutex lock;
154 struct clk *sclk_fimc_clk;
155 struct clk *fimc_clk;
156 struct clk *wb_clk;
157 struct clk *wb_b_clk;
158 struct fimc_scaler sc;
159 struct fimc_driverdata *ddata;
160 struct exynos_drm_ipp_pol pol;
161 int id;
162 int irq;
163 bool suspended;
164};
165
166static void fimc_sw_reset(struct fimc_context *ctx, bool pattern)
167{
168 u32 cfg;
169
170 DRM_DEBUG_KMS("%s:pattern[%d]\n", __func__, pattern);
171
172 cfg = fimc_read(EXYNOS_CISRCFMT);
173 cfg |= EXYNOS_CISRCFMT_ITU601_8BIT;
174 if (pattern)
175 cfg |= EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR;
176
177 fimc_write(cfg, EXYNOS_CISRCFMT);
178
179 /* s/w reset */
180 cfg = fimc_read(EXYNOS_CIGCTRL);
181 cfg |= (EXYNOS_CIGCTRL_SWRST);
182 fimc_write(cfg, EXYNOS_CIGCTRL);
183
184 /* s/w reset complete */
185 cfg = fimc_read(EXYNOS_CIGCTRL);
186 cfg &= ~EXYNOS_CIGCTRL_SWRST;
187 fimc_write(cfg, EXYNOS_CIGCTRL);
188
189 /* reset sequence */
190 fimc_write(0x0, EXYNOS_CIFCNTSEQ);
191}
192
193static void fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
194{
195 u32 camblk_cfg;
196
197 DRM_DEBUG_KMS("%s\n", __func__);
198
199 camblk_cfg = readl(SYSREG_CAMERA_BLK);
200 camblk_cfg &= ~(SYSREG_FIMD0WB_DEST_MASK);
201 camblk_cfg |= ctx->id << (SYSREG_FIMD0WB_DEST_SHIFT);
202
203 writel(camblk_cfg, SYSREG_CAMERA_BLK);
204}
205
206static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
207{
208 u32 cfg;
209
210 DRM_DEBUG_KMS("%s:wb[%d]\n", __func__, wb);
211
212 cfg = fimc_read(EXYNOS_CIGCTRL);
213 cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK |
214 EXYNOS_CIGCTRL_SELCAM_ITU_MASK |
215 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK |
216 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK |
217 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK |
218 EXYNOS_CIGCTRL_SELWRITEBACK_MASK);
219
220 switch (wb) {
221 case FIMC_WB_A:
222 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_A |
223 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
224 break;
225 case FIMC_WB_B:
226 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_B |
227 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
228 break;
229 case FIMC_WB_NONE:
230 default:
231 cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A |
232 EXYNOS_CIGCTRL_SELWRITEBACK_A |
233 EXYNOS_CIGCTRL_SELCAM_MIPI_A |
234 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU);
235 break;
236 }
237
238 fimc_write(cfg, EXYNOS_CIGCTRL);
239}
240
241static void fimc_set_polarity(struct fimc_context *ctx,
242 struct exynos_drm_ipp_pol *pol)
243{
244 u32 cfg;
245
246 DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n",
247 __func__, pol->inv_pclk, pol->inv_vsync);
248 DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n",
249 __func__, pol->inv_href, pol->inv_hsync);
250
251 cfg = fimc_read(EXYNOS_CIGCTRL);
252 cfg &= ~(EXYNOS_CIGCTRL_INVPOLPCLK | EXYNOS_CIGCTRL_INVPOLVSYNC |
253 EXYNOS_CIGCTRL_INVPOLHREF | EXYNOS_CIGCTRL_INVPOLHSYNC);
254
255 if (pol->inv_pclk)
256 cfg |= EXYNOS_CIGCTRL_INVPOLPCLK;
257 if (pol->inv_vsync)
258 cfg |= EXYNOS_CIGCTRL_INVPOLVSYNC;
259 if (pol->inv_href)
260 cfg |= EXYNOS_CIGCTRL_INVPOLHREF;
261 if (pol->inv_hsync)
262 cfg |= EXYNOS_CIGCTRL_INVPOLHSYNC;
263
264 fimc_write(cfg, EXYNOS_CIGCTRL);
265}
266
267static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable)
268{
269 u32 cfg;
270
271 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
272
273 cfg = fimc_read(EXYNOS_CIGCTRL);
274 if (enable)
275 cfg |= EXYNOS_CIGCTRL_CAM_JPEG;
276 else
277 cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG;
278
279 fimc_write(cfg, EXYNOS_CIGCTRL);
280}
281
282static void fimc_handle_irq(struct fimc_context *ctx, bool enable,
283 bool overflow, bool level)
284{
285 u32 cfg;
286
287 DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
288 enable, overflow, level);
289
290 cfg = fimc_read(EXYNOS_CIGCTRL);
291 if (enable) {
292 cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_LEVEL);
293 cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE;
294 if (overflow)
295 cfg |= EXYNOS_CIGCTRL_IRQ_OVFEN;
296 if (level)
297 cfg |= EXYNOS_CIGCTRL_IRQ_LEVEL;
298 } else
299 cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_ENABLE);
300
301 fimc_write(cfg, EXYNOS_CIGCTRL);
302}
303
304static void fimc_clear_irq(struct fimc_context *ctx)
305{
306 u32 cfg;
307
308 DRM_DEBUG_KMS("%s\n", __func__);
309
310 cfg = fimc_read(EXYNOS_CIGCTRL);
311 cfg |= EXYNOS_CIGCTRL_IRQ_CLR;
312 fimc_write(cfg, EXYNOS_CIGCTRL);
313}
314
315static bool fimc_check_ovf(struct fimc_context *ctx)
316{
317 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
318 u32 cfg, status, flag;
319
320 status = fimc_read(EXYNOS_CISTATUS);
321 flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB |
322 EXYNOS_CISTATUS_OVFICR;
323
324 DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__, flag);
325
326 if (status & flag) {
327 cfg = fimc_read(EXYNOS_CIWDOFST);
328 cfg |= (EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
329 EXYNOS_CIWDOFST_CLROVFICR);
330
331 fimc_write(cfg, EXYNOS_CIWDOFST);
332
333 cfg = fimc_read(EXYNOS_CIWDOFST);
334 cfg &= ~(EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
335 EXYNOS_CIWDOFST_CLROVFICR);
336
337 fimc_write(cfg, EXYNOS_CIWDOFST);
338
339 dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n",
340 ctx->id, status);
341 return true;
342 }
343
344 return false;
345}
346
347static bool fimc_check_frame_end(struct fimc_context *ctx)
348{
349 u32 cfg;
350
351 cfg = fimc_read(EXYNOS_CISTATUS);
352
353 DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__, cfg);
354
355 if (!(cfg & EXYNOS_CISTATUS_FRAMEEND))
356 return false;
357
358 cfg &= ~(EXYNOS_CISTATUS_FRAMEEND);
359 fimc_write(cfg, EXYNOS_CISTATUS);
360
361 return true;
362}
363
364static int fimc_get_buf_id(struct fimc_context *ctx)
365{
366 u32 cfg;
367 int frame_cnt, buf_id;
368
369 DRM_DEBUG_KMS("%s\n", __func__);
370
371 cfg = fimc_read(EXYNOS_CISTATUS2);
372 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg);
373
374 if (frame_cnt == 0)
375 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg);
376
377 DRM_DEBUG_KMS("%s:present[%d]before[%d]\n", __func__,
378 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg),
379 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg));
380
381 if (frame_cnt == 0) {
382 DRM_ERROR("failed to get frame count.\n");
383 return -EIO;
384 }
385
386 buf_id = frame_cnt - 1;
387 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
388
389 return buf_id;
390}
391
392static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
393{
394 u32 cfg;
395
396 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
397
398 cfg = fimc_read(EXYNOS_CIOCTRL);
399 if (enable)
400 cfg |= EXYNOS_CIOCTRL_LASTENDEN;
401 else
402 cfg &= ~EXYNOS_CIOCTRL_LASTENDEN;
403
404 fimc_write(cfg, EXYNOS_CIOCTRL);
405}
406
407
408static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
409{
410 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
411 u32 cfg;
412
413 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
414
415 /* RGB */
416 cfg = fimc_read(EXYNOS_CISCCTRL);
417 cfg &= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK;
418
419 switch (fmt) {
420 case DRM_FORMAT_RGB565:
421 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565;
422 fimc_write(cfg, EXYNOS_CISCCTRL);
423 return 0;
424 case DRM_FORMAT_RGB888:
425 case DRM_FORMAT_XRGB8888:
426 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888;
427 fimc_write(cfg, EXYNOS_CISCCTRL);
428 return 0;
429 default:
430 /* bypass */
431 break;
432 }
433
434 /* YUV */
435 cfg = fimc_read(EXYNOS_MSCTRL);
436 cfg &= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK |
437 EXYNOS_MSCTRL_C_INT_IN_2PLANE |
438 EXYNOS_MSCTRL_ORDER422_YCBYCR);
439
440 switch (fmt) {
441 case DRM_FORMAT_YUYV:
442 cfg |= EXYNOS_MSCTRL_ORDER422_YCBYCR;
443 break;
444 case DRM_FORMAT_YVYU:
445 cfg |= EXYNOS_MSCTRL_ORDER422_YCRYCB;
446 break;
447 case DRM_FORMAT_UYVY:
448 cfg |= EXYNOS_MSCTRL_ORDER422_CBYCRY;
449 break;
450 case DRM_FORMAT_VYUY:
451 case DRM_FORMAT_YUV444:
452 cfg |= EXYNOS_MSCTRL_ORDER422_CRYCBY;
453 break;
454 case DRM_FORMAT_NV21:
455 case DRM_FORMAT_NV61:
456 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB |
457 EXYNOS_MSCTRL_C_INT_IN_2PLANE);
458 break;
459 case DRM_FORMAT_YUV422:
460 case DRM_FORMAT_YUV420:
461 case DRM_FORMAT_YVU420:
462 cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE;
463 break;
464 case DRM_FORMAT_NV12:
465 case DRM_FORMAT_NV12MT:
466 case DRM_FORMAT_NV16:
467 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR |
468 EXYNOS_MSCTRL_C_INT_IN_2PLANE);
469 break;
470 default:
471 dev_err(ippdrv->dev, "inavlid source yuv order 0x%x.\n", fmt);
472 return -EINVAL;
473 }
474
475 fimc_write(cfg, EXYNOS_MSCTRL);
476
477 return 0;
478}
479
480static int fimc_src_set_fmt(struct device *dev, u32 fmt)
481{
482 struct fimc_context *ctx = get_fimc_context(dev);
483 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
484 u32 cfg;
485
486 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
487
488 cfg = fimc_read(EXYNOS_MSCTRL);
489 cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB;
490
491 switch (fmt) {
492 case DRM_FORMAT_RGB565:
493 case DRM_FORMAT_RGB888:
494 case DRM_FORMAT_XRGB8888:
495 cfg |= EXYNOS_MSCTRL_INFORMAT_RGB;
496 break;
497 case DRM_FORMAT_YUV444:
498 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
499 break;
500 case DRM_FORMAT_YUYV:
501 case DRM_FORMAT_YVYU:
502 case DRM_FORMAT_UYVY:
503 case DRM_FORMAT_VYUY:
504 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE;
505 break;
506 case DRM_FORMAT_NV16:
507 case DRM_FORMAT_NV61:
508 case DRM_FORMAT_YUV422:
509 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422;
510 break;
511 case DRM_FORMAT_YUV420:
512 case DRM_FORMAT_YVU420:
513 case DRM_FORMAT_NV12:
514 case DRM_FORMAT_NV21:
515 case DRM_FORMAT_NV12MT:
516 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
517 break;
518 default:
519 dev_err(ippdrv->dev, "inavlid source format 0x%x.\n", fmt);
520 return -EINVAL;
521 }
522
523 fimc_write(cfg, EXYNOS_MSCTRL);
524
525 cfg = fimc_read(EXYNOS_CIDMAPARAM);
526 cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK;
527
528 if (fmt == DRM_FORMAT_NV12MT)
529 cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32;
530 else
531 cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR;
532
533 fimc_write(cfg, EXYNOS_CIDMAPARAM);
534
535 return fimc_src_set_fmt_order(ctx, fmt);
536}
537
538static int fimc_src_set_transf(struct device *dev,
539 enum drm_exynos_degree degree,
540 enum drm_exynos_flip flip, bool *swap)
541{
542 struct fimc_context *ctx = get_fimc_context(dev);
543 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
544 u32 cfg1, cfg2;
545
546 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
547 degree, flip);
548
549 cfg1 = fimc_read(EXYNOS_MSCTRL);
550 cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR |
551 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
552
553 cfg2 = fimc_read(EXYNOS_CITRGFMT);
554 cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
555
556 switch (degree) {
557 case EXYNOS_DRM_DEGREE_0:
558 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
559 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
560 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
561 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
562 break;
563 case EXYNOS_DRM_DEGREE_90:
564 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
565 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
566 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
567 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
568 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
569 break;
570 case EXYNOS_DRM_DEGREE_180:
571 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
572 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
573 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
574 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
575 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
576 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
577 break;
578 case EXYNOS_DRM_DEGREE_270:
579 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
580 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
581 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
582 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
583 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
584 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
585 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
586 break;
587 default:
588 dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
589 return -EINVAL;
590 }
591
592 fimc_write(cfg1, EXYNOS_MSCTRL);
593 fimc_write(cfg2, EXYNOS_CITRGFMT);
594 *swap = (cfg2 & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) ? 1 : 0;
595
596 return 0;
597}
598
599static int fimc_set_window(struct fimc_context *ctx,
600 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
601{
602 u32 cfg, h1, h2, v1, v2;
603
604 /* cropped image */
605 h1 = pos->x;
606 h2 = sz->hsize - pos->w - pos->x;
607 v1 = pos->y;
608 v2 = sz->vsize - pos->h - pos->y;
609
610 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
611 __func__, pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
612 DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__,
613 h1, h2, v1, v2);
614
615 /*
616 * set window offset 1, 2 size
617 * check figure 43-21 in user manual
618 */
619 cfg = fimc_read(EXYNOS_CIWDOFST);
620 cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK |
621 EXYNOS_CIWDOFST_WINVEROFST_MASK);
622 cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) |
623 EXYNOS_CIWDOFST_WINVEROFST(v1));
624 cfg |= EXYNOS_CIWDOFST_WINOFSEN;
625 fimc_write(cfg, EXYNOS_CIWDOFST);
626
627 cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) |
628 EXYNOS_CIWDOFST2_WINVEROFST2(v2));
629 fimc_write(cfg, EXYNOS_CIWDOFST2);
630
631 return 0;
632}
633
634static int fimc_src_set_size(struct device *dev, int swap,
635 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
636{
637 struct fimc_context *ctx = get_fimc_context(dev);
638 struct drm_exynos_pos img_pos = *pos;
639 struct drm_exynos_sz img_sz = *sz;
640 u32 cfg;
641
642 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
643 __func__, swap, sz->hsize, sz->vsize);
644
645 /* original size */
646 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) |
647 EXYNOS_ORGISIZE_VERTICAL(img_sz.vsize));
648
649 fimc_write(cfg, EXYNOS_ORGISIZE);
650
651 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__,
652 pos->x, pos->y, pos->w, pos->h);
653
654 if (swap) {
655 img_pos.w = pos->h;
656 img_pos.h = pos->w;
657 img_sz.hsize = sz->vsize;
658 img_sz.vsize = sz->hsize;
659 }
660
661 /* set input DMA image size */
662 cfg = fimc_read(EXYNOS_CIREAL_ISIZE);
663 cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK |
664 EXYNOS_CIREAL_ISIZE_WIDTH_MASK);
665 cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos.w) |
666 EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos.h));
667 fimc_write(cfg, EXYNOS_CIREAL_ISIZE);
668
669 /*
670 * set input FIFO image size
671 * for now, we support only ITU601 8 bit mode
672 */
673 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT |
674 EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz.hsize) |
675 EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz.vsize));
676 fimc_write(cfg, EXYNOS_CISRCFMT);
677
678 /* offset Y(RGB), Cb, Cr */
679 cfg = (EXYNOS_CIIYOFF_HORIZONTAL(img_pos.x) |
680 EXYNOS_CIIYOFF_VERTICAL(img_pos.y));
681 fimc_write(cfg, EXYNOS_CIIYOFF);
682 cfg = (EXYNOS_CIICBOFF_HORIZONTAL(img_pos.x) |
683 EXYNOS_CIICBOFF_VERTICAL(img_pos.y));
684 fimc_write(cfg, EXYNOS_CIICBOFF);
685 cfg = (EXYNOS_CIICROFF_HORIZONTAL(img_pos.x) |
686 EXYNOS_CIICROFF_VERTICAL(img_pos.y));
687 fimc_write(cfg, EXYNOS_CIICROFF);
688
689 return fimc_set_window(ctx, &img_pos, &img_sz);
690}
691
692static int fimc_src_set_addr(struct device *dev,
693 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
694 enum drm_exynos_ipp_buf_type buf_type)
695{
696 struct fimc_context *ctx = get_fimc_context(dev);
697 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
698 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
699 struct drm_exynos_ipp_property *property;
700 struct drm_exynos_ipp_config *config;
701
702 if (!c_node) {
703 DRM_ERROR("failed to get c_node.\n");
704 return -EINVAL;
705 }
706
707 property = &c_node->property;
708 if (!property) {
709 DRM_ERROR("failed to get property.\n");
710 return -EINVAL;
711 }
712
713 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
714 property->prop_id, buf_id, buf_type);
715
716 if (buf_id > FIMC_MAX_SRC) {
717 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
718 return -ENOMEM;
719 }
720
721 /* address register set */
722 switch (buf_type) {
723 case IPP_BUF_ENQUEUE:
724 config = &property->config[EXYNOS_DRM_OPS_SRC];
725 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
726 EXYNOS_CIIYSA(buf_id));
727
728 if (config->fmt == DRM_FORMAT_YVU420) {
729 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
730 EXYNOS_CIICBSA(buf_id));
731 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
732 EXYNOS_CIICRSA(buf_id));
733 } else {
734 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
735 EXYNOS_CIICBSA(buf_id));
736 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
737 EXYNOS_CIICRSA(buf_id));
738 }
739 break;
740 case IPP_BUF_DEQUEUE:
741 fimc_write(0x0, EXYNOS_CIIYSA(buf_id));
742 fimc_write(0x0, EXYNOS_CIICBSA(buf_id));
743 fimc_write(0x0, EXYNOS_CIICRSA(buf_id));
744 break;
745 default:
746 /* bypass */
747 break;
748 }
749
750 return 0;
751}
752
753static struct exynos_drm_ipp_ops fimc_src_ops = {
754 .set_fmt = fimc_src_set_fmt,
755 .set_transf = fimc_src_set_transf,
756 .set_size = fimc_src_set_size,
757 .set_addr = fimc_src_set_addr,
758};
759
760static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
761{
762 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
763 u32 cfg;
764
765 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
766
767 /* RGB */
768 cfg = fimc_read(EXYNOS_CISCCTRL);
769 cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK;
770
771 switch (fmt) {
772 case DRM_FORMAT_RGB565:
773 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565;
774 fimc_write(cfg, EXYNOS_CISCCTRL);
775 return 0;
776 case DRM_FORMAT_RGB888:
777 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888;
778 fimc_write(cfg, EXYNOS_CISCCTRL);
779 return 0;
780 case DRM_FORMAT_XRGB8888:
781 cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 |
782 EXYNOS_CISCCTRL_EXTRGB_EXTENSION);
783 fimc_write(cfg, EXYNOS_CISCCTRL);
784 break;
785 default:
786 /* bypass */
787 break;
788 }
789
790 /* YUV */
791 cfg = fimc_read(EXYNOS_CIOCTRL);
792 cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK |
793 EXYNOS_CIOCTRL_ORDER422_MASK |
794 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK);
795
796 switch (fmt) {
797 case DRM_FORMAT_XRGB8888:
798 cfg |= EXYNOS_CIOCTRL_ALPHA_OUT;
799 break;
800 case DRM_FORMAT_YUYV:
801 cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR;
802 break;
803 case DRM_FORMAT_YVYU:
804 cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB;
805 break;
806 case DRM_FORMAT_UYVY:
807 cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY;
808 break;
809 case DRM_FORMAT_VYUY:
810 cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY;
811 break;
812 case DRM_FORMAT_NV21:
813 case DRM_FORMAT_NV61:
814 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB;
815 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
816 break;
817 case DRM_FORMAT_YUV422:
818 case DRM_FORMAT_YUV420:
819 case DRM_FORMAT_YVU420:
820 cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE;
821 break;
822 case DRM_FORMAT_NV12:
823 case DRM_FORMAT_NV12MT:
824 case DRM_FORMAT_NV16:
825 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR;
826 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
827 break;
828 default:
829 dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
830 return -EINVAL;
831 }
832
833 fimc_write(cfg, EXYNOS_CIOCTRL);
834
835 return 0;
836}
837
838static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
839{
840 struct fimc_context *ctx = get_fimc_context(dev);
841 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
842 u32 cfg;
843
844 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
845
846 cfg = fimc_read(EXYNOS_CIEXTEN);
847
848 if (fmt == DRM_FORMAT_AYUV) {
849 cfg |= EXYNOS_CIEXTEN_YUV444_OUT;
850 fimc_write(cfg, EXYNOS_CIEXTEN);
851 } else {
852 cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT;
853 fimc_write(cfg, EXYNOS_CIEXTEN);
854
855 cfg = fimc_read(EXYNOS_CITRGFMT);
856 cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK;
857
858 switch (fmt) {
859 case DRM_FORMAT_RGB565:
860 case DRM_FORMAT_RGB888:
861 case DRM_FORMAT_XRGB8888:
862 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB;
863 break;
864 case DRM_FORMAT_YUYV:
865 case DRM_FORMAT_YVYU:
866 case DRM_FORMAT_UYVY:
867 case DRM_FORMAT_VYUY:
868 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
869 break;
870 case DRM_FORMAT_NV16:
871 case DRM_FORMAT_NV61:
872 case DRM_FORMAT_YUV422:
873 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422;
874 break;
875 case DRM_FORMAT_YUV420:
876 case DRM_FORMAT_YVU420:
877 case DRM_FORMAT_NV12:
878 case DRM_FORMAT_NV12MT:
879 case DRM_FORMAT_NV21:
880 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420;
881 break;
882 default:
883 dev_err(ippdrv->dev, "inavlid target format 0x%x.\n",
884 fmt);
885 return -EINVAL;
886 }
887
888 fimc_write(cfg, EXYNOS_CITRGFMT);
889 }
890
891 cfg = fimc_read(EXYNOS_CIDMAPARAM);
892 cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK;
893
894 if (fmt == DRM_FORMAT_NV12MT)
895 cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32;
896 else
897 cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR;
898
899 fimc_write(cfg, EXYNOS_CIDMAPARAM);
900
901 return fimc_dst_set_fmt_order(ctx, fmt);
902}
903
904static int fimc_dst_set_transf(struct device *dev,
905 enum drm_exynos_degree degree,
906 enum drm_exynos_flip flip, bool *swap)
907{
908 struct fimc_context *ctx = get_fimc_context(dev);
909 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
910 u32 cfg;
911
912 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
913 degree, flip);
914
915 cfg = fimc_read(EXYNOS_CITRGFMT);
916 cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
917 cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
918
919 switch (degree) {
920 case EXYNOS_DRM_DEGREE_0:
921 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
922 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
923 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
924 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
925 break;
926 case EXYNOS_DRM_DEGREE_90:
927 cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
928 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
929 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
930 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
931 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
932 break;
933 case EXYNOS_DRM_DEGREE_180:
934 cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR |
935 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
936 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
937 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
938 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
939 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
940 break;
941 case EXYNOS_DRM_DEGREE_270:
942 cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE |
943 EXYNOS_CITRGFMT_FLIP_X_MIRROR |
944 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
945 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
946 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
947 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
948 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
949 break;
950 default:
951 dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
952 return -EINVAL;
953 }
954
955 fimc_write(cfg, EXYNOS_CITRGFMT);
956 *swap = (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0;
957
958 return 0;
959}
960
961static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift)
962{
963 DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
964
965 if (src >= dst * 64) {
966 DRM_ERROR("failed to make ratio and shift.\n");
967 return -EINVAL;
968 } else if (src >= dst * 32) {
969 *ratio = 32;
970 *shift = 5;
971 } else if (src >= dst * 16) {
972 *ratio = 16;
973 *shift = 4;
974 } else if (src >= dst * 8) {
975 *ratio = 8;
976 *shift = 3;
977 } else if (src >= dst * 4) {
978 *ratio = 4;
979 *shift = 2;
980 } else if (src >= dst * 2) {
981 *ratio = 2;
982 *shift = 1;
983 } else {
984 *ratio = 1;
985 *shift = 0;
986 }
987
988 return 0;
989}
990
991static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
992 struct drm_exynos_pos *src, struct drm_exynos_pos *dst)
993{
994 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
995 u32 cfg, cfg_ext, shfactor;
996 u32 pre_dst_width, pre_dst_height;
997 u32 pre_hratio, hfactor, pre_vratio, vfactor;
998 int ret = 0;
999 u32 src_w, src_h, dst_w, dst_h;
1000
1001 cfg_ext = fimc_read(EXYNOS_CITRGFMT);
1002 if (cfg_ext & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) {
1003 src_w = src->h;
1004 src_h = src->w;
1005 } else {
1006 src_w = src->w;
1007 src_h = src->h;
1008 }
1009
1010 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) {
1011 dst_w = dst->h;
1012 dst_h = dst->w;
1013 } else {
1014 dst_w = dst->w;
1015 dst_h = dst->h;
1016 }
1017
1018 ret = fimc_get_ratio_shift(src_w, dst_w, &pre_hratio, &hfactor);
1019 if (ret) {
1020 dev_err(ippdrv->dev, "failed to get ratio horizontal.\n");
1021 return ret;
1022 }
1023
1024 ret = fimc_get_ratio_shift(src_h, dst_h, &pre_vratio, &vfactor);
1025 if (ret) {
1026 dev_err(ippdrv->dev, "failed to get ratio vertical.\n");
1027 return ret;
1028 }
1029
1030 pre_dst_width = src_w / pre_hratio;
1031 pre_dst_height = src_h / pre_vratio;
1032 DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__,
1033 pre_dst_width, pre_dst_height);
1034 DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
1035 __func__, pre_hratio, hfactor, pre_vratio, vfactor);
1036
1037 sc->hratio = (src_w << 14) / (dst_w << hfactor);
1038 sc->vratio = (src_h << 14) / (dst_h << vfactor);
1039 sc->up_h = (dst_w >= src_w) ? true : false;
1040 sc->up_v = (dst_h >= src_h) ? true : false;
1041 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
1042 __func__, sc->hratio, sc->vratio, sc->up_h, sc->up_v);
1043
1044 shfactor = FIMC_SHFACTOR - (hfactor + vfactor);
1045 DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__, shfactor);
1046
1047 cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) |
1048 EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) |
1049 EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio));
1050 fimc_write(cfg, EXYNOS_CISCPRERATIO);
1051
1052 cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) |
1053 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height));
1054 fimc_write(cfg, EXYNOS_CISCPREDST);
1055
1056 return ret;
1057}
1058
1059static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
1060{
1061 u32 cfg, cfg_ext;
1062
1063 DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
1064 __func__, sc->range, sc->bypass, sc->up_h, sc->up_v);
1065 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n",
1066 __func__, sc->hratio, sc->vratio);
1067
1068 cfg = fimc_read(EXYNOS_CISCCTRL);
1069 cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS |
1070 EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V |
1071 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK |
1072 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK |
1073 EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1074 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1075
1076 if (sc->range)
1077 cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1078 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1079 if (sc->bypass)
1080 cfg |= EXYNOS_CISCCTRL_SCALERBYPASS;
1081 if (sc->up_h)
1082 cfg |= EXYNOS_CISCCTRL_SCALEUP_H;
1083 if (sc->up_v)
1084 cfg |= EXYNOS_CISCCTRL_SCALEUP_V;
1085
1086 cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) |
1087 EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6)));
1088 fimc_write(cfg, EXYNOS_CISCCTRL);
1089
1090 cfg_ext = fimc_read(EXYNOS_CIEXTEN);
1091 cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK;
1092 cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK;
1093 cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) |
1094 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio));
1095 fimc_write(cfg_ext, EXYNOS_CIEXTEN);
1096}
1097
1098static int fimc_dst_set_size(struct device *dev, int swap,
1099 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
1100{
1101 struct fimc_context *ctx = get_fimc_context(dev);
1102 struct drm_exynos_pos img_pos = *pos;
1103 struct drm_exynos_sz img_sz = *sz;
1104 u32 cfg;
1105
1106 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
1107 __func__, swap, sz->hsize, sz->vsize);
1108
1109 /* original size */
1110 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) |
1111 EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize));
1112
1113 fimc_write(cfg, EXYNOS_ORGOSIZE);
1114
1115 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
1116 __func__, pos->x, pos->y, pos->w, pos->h);
1117
1118 /* CSC ITU */
1119 cfg = fimc_read(EXYNOS_CIGCTRL);
1120 cfg &= ~EXYNOS_CIGCTRL_CSC_MASK;
1121
1122 if (sz->hsize >= FIMC_WIDTH_ITU_709)
1123 cfg |= EXYNOS_CIGCTRL_CSC_ITU709;
1124 else
1125 cfg |= EXYNOS_CIGCTRL_CSC_ITU601;
1126
1127 fimc_write(cfg, EXYNOS_CIGCTRL);
1128
1129 if (swap) {
1130 img_pos.w = pos->h;
1131 img_pos.h = pos->w;
1132 img_sz.hsize = sz->vsize;
1133 img_sz.vsize = sz->hsize;
1134 }
1135
1136 /* target image size */
1137 cfg = fimc_read(EXYNOS_CITRGFMT);
1138 cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK |
1139 EXYNOS_CITRGFMT_TARGETV_MASK);
1140 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) |
1141 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h));
1142 fimc_write(cfg, EXYNOS_CITRGFMT);
1143
1144 /* target area */
1145 cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h);
1146 fimc_write(cfg, EXYNOS_CITAREA);
1147
1148 /* offset Y(RGB), Cb, Cr */
1149 cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) |
1150 EXYNOS_CIOYOFF_VERTICAL(img_pos.y));
1151 fimc_write(cfg, EXYNOS_CIOYOFF);
1152 cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) |
1153 EXYNOS_CIOCBOFF_VERTICAL(img_pos.y));
1154 fimc_write(cfg, EXYNOS_CIOCBOFF);
1155 cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) |
1156 EXYNOS_CIOCROFF_VERTICAL(img_pos.y));
1157 fimc_write(cfg, EXYNOS_CIOCROFF);
1158
1159 return 0;
1160}
1161
1162static int fimc_dst_get_buf_seq(struct fimc_context *ctx)
1163{
1164 u32 cfg, i, buf_num = 0;
1165 u32 mask = 0x00000001;
1166
1167 cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1168
1169 for (i = 0; i < FIMC_REG_SZ; i++)
1170 if (cfg & (mask << i))
1171 buf_num++;
1172
1173 DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
1174
1175 return buf_num;
1176}
1177
1178static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
1179 enum drm_exynos_ipp_buf_type buf_type)
1180{
1181 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1182 bool enable;
1183 u32 cfg;
1184 u32 mask = 0x00000001 << buf_id;
1185 int ret = 0;
1186
1187 DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
1188 buf_id, buf_type);
1189
1190 mutex_lock(&ctx->lock);
1191
1192 /* mask register set */
1193 cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1194
1195 switch (buf_type) {
1196 case IPP_BUF_ENQUEUE:
1197 enable = true;
1198 break;
1199 case IPP_BUF_DEQUEUE:
1200 enable = false;
1201 break;
1202 default:
1203 dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
1204 ret = -EINVAL;
1205 goto err_unlock;
1206 }
1207
1208 /* sequence id */
1209 cfg &= (~mask);
1210 cfg |= (enable << buf_id);
1211 fimc_write(cfg, EXYNOS_CIFCNTSEQ);
1212
1213 /* interrupt enable */
1214 if (buf_type == IPP_BUF_ENQUEUE &&
1215 fimc_dst_get_buf_seq(ctx) >= FIMC_BUF_START)
1216 fimc_handle_irq(ctx, true, false, true);
1217
1218 /* interrupt disable */
1219 if (buf_type == IPP_BUF_DEQUEUE &&
1220 fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP)
1221 fimc_handle_irq(ctx, false, false, true);
1222
1223err_unlock:
1224 mutex_unlock(&ctx->lock);
1225 return ret;
1226}
1227
1228static int fimc_dst_set_addr(struct device *dev,
1229 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
1230 enum drm_exynos_ipp_buf_type buf_type)
1231{
1232 struct fimc_context *ctx = get_fimc_context(dev);
1233 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1234 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1235 struct drm_exynos_ipp_property *property;
1236 struct drm_exynos_ipp_config *config;
1237
1238 if (!c_node) {
1239 DRM_ERROR("failed to get c_node.\n");
1240 return -EINVAL;
1241 }
1242
1243 property = &c_node->property;
1244 if (!property) {
1245 DRM_ERROR("failed to get property.\n");
1246 return -EINVAL;
1247 }
1248
1249 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
1250 property->prop_id, buf_id, buf_type);
1251
1252 if (buf_id > FIMC_MAX_DST) {
1253 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
1254 return -ENOMEM;
1255 }
1256
1257 /* address register set */
1258 switch (buf_type) {
1259 case IPP_BUF_ENQUEUE:
1260 config = &property->config[EXYNOS_DRM_OPS_DST];
1261
1262 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
1263 EXYNOS_CIOYSA(buf_id));
1264
1265 if (config->fmt == DRM_FORMAT_YVU420) {
1266 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1267 EXYNOS_CIOCBSA(buf_id));
1268 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1269 EXYNOS_CIOCRSA(buf_id));
1270 } else {
1271 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1272 EXYNOS_CIOCBSA(buf_id));
1273 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1274 EXYNOS_CIOCRSA(buf_id));
1275 }
1276 break;
1277 case IPP_BUF_DEQUEUE:
1278 fimc_write(0x0, EXYNOS_CIOYSA(buf_id));
1279 fimc_write(0x0, EXYNOS_CIOCBSA(buf_id));
1280 fimc_write(0x0, EXYNOS_CIOCRSA(buf_id));
1281 break;
1282 default:
1283 /* bypass */
1284 break;
1285 }
1286
1287 return fimc_dst_set_buf_seq(ctx, buf_id, buf_type);
1288}
1289
1290static struct exynos_drm_ipp_ops fimc_dst_ops = {
1291 .set_fmt = fimc_dst_set_fmt,
1292 .set_transf = fimc_dst_set_transf,
1293 .set_size = fimc_dst_set_size,
1294 .set_addr = fimc_dst_set_addr,
1295};
1296
1297static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
1298{
1299 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
1300
1301 if (enable) {
1302 clk_enable(ctx->sclk_fimc_clk);
1303 clk_enable(ctx->fimc_clk);
1304 clk_enable(ctx->wb_clk);
1305 ctx->suspended = false;
1306 } else {
1307 clk_disable(ctx->sclk_fimc_clk);
1308 clk_disable(ctx->fimc_clk);
1309 clk_disable(ctx->wb_clk);
1310 ctx->suspended = true;
1311 }
1312
1313 return 0;
1314}
1315
1316static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
1317{
1318 struct fimc_context *ctx = dev_id;
1319 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1320 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1321 struct drm_exynos_ipp_event_work *event_work =
1322 c_node->event_work;
1323 int buf_id;
1324
1325 DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__, ctx->id);
1326
1327 fimc_clear_irq(ctx);
1328 if (fimc_check_ovf(ctx))
1329 return IRQ_NONE;
1330
1331 if (!fimc_check_frame_end(ctx))
1332 return IRQ_NONE;
1333
1334 buf_id = fimc_get_buf_id(ctx);
1335 if (buf_id < 0)
1336 return IRQ_HANDLED;
1337
1338 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
1339
1340 if (fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE) < 0) {
1341 DRM_ERROR("failed to dequeue.\n");
1342 return IRQ_HANDLED;
1343 }
1344
1345 event_work->ippdrv = ippdrv;
1346 event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id;
1347 queue_work(ippdrv->event_workq, (struct work_struct *)event_work);
1348
1349 return IRQ_HANDLED;
1350}
1351
1352static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
1353{
1354 struct drm_exynos_ipp_prop_list *prop_list;
1355
1356 DRM_DEBUG_KMS("%s\n", __func__);
1357
1358 prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
1359 if (!prop_list) {
1360 DRM_ERROR("failed to alloc property list.\n");
1361 return -ENOMEM;
1362 }
1363
1364 prop_list->version = 1;
1365 prop_list->writeback = 1;
1366 prop_list->refresh_min = FIMC_REFRESH_MIN;
1367 prop_list->refresh_max = FIMC_REFRESH_MAX;
1368 prop_list->flip = (1 << EXYNOS_DRM_FLIP_NONE) |
1369 (1 << EXYNOS_DRM_FLIP_VERTICAL) |
1370 (1 << EXYNOS_DRM_FLIP_HORIZONTAL);
1371 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
1372 (1 << EXYNOS_DRM_DEGREE_90) |
1373 (1 << EXYNOS_DRM_DEGREE_180) |
1374 (1 << EXYNOS_DRM_DEGREE_270);
1375 prop_list->csc = 1;
1376 prop_list->crop = 1;
1377 prop_list->crop_max.hsize = FIMC_CROP_MAX;
1378 prop_list->crop_max.vsize = FIMC_CROP_MAX;
1379 prop_list->crop_min.hsize = FIMC_CROP_MIN;
1380 prop_list->crop_min.vsize = FIMC_CROP_MIN;
1381 prop_list->scale = 1;
1382 prop_list->scale_max.hsize = FIMC_SCALE_MAX;
1383 prop_list->scale_max.vsize = FIMC_SCALE_MAX;
1384 prop_list->scale_min.hsize = FIMC_SCALE_MIN;
1385 prop_list->scale_min.vsize = FIMC_SCALE_MIN;
1386
1387 ippdrv->prop_list = prop_list;
1388
1389 return 0;
1390}
1391
1392static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
1393{
1394 switch (flip) {
1395 case EXYNOS_DRM_FLIP_NONE:
1396 case EXYNOS_DRM_FLIP_VERTICAL:
1397 case EXYNOS_DRM_FLIP_HORIZONTAL:
1398 return true;
1399 default:
1400 DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
1401 return false;
1402 }
1403}
1404
1405static int fimc_ippdrv_check_property(struct device *dev,
1406 struct drm_exynos_ipp_property *property)
1407{
1408 struct fimc_context *ctx = get_fimc_context(dev);
1409 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1410 struct drm_exynos_ipp_prop_list *pp = ippdrv->prop_list;
1411 struct drm_exynos_ipp_config *config;
1412 struct drm_exynos_pos *pos;
1413 struct drm_exynos_sz *sz;
1414 bool swap;
1415 int i;
1416
1417 DRM_DEBUG_KMS("%s\n", __func__);
1418
1419 for_each_ipp_ops(i) {
1420 if ((i == EXYNOS_DRM_OPS_SRC) &&
1421 (property->cmd == IPP_CMD_WB))
1422 continue;
1423
1424 config = &property->config[i];
1425 pos = &config->pos;
1426 sz = &config->sz;
1427
1428 /* check for flip */
1429 if (!fimc_check_drm_flip(config->flip)) {
1430 DRM_ERROR("invalid flip.\n");
1431 goto err_property;
1432 }
1433
1434 /* check for degree */
1435 switch (config->degree) {
1436 case EXYNOS_DRM_DEGREE_90:
1437 case EXYNOS_DRM_DEGREE_270:
1438 swap = true;
1439 break;
1440 case EXYNOS_DRM_DEGREE_0:
1441 case EXYNOS_DRM_DEGREE_180:
1442 swap = false;
1443 break;
1444 default:
1445 DRM_ERROR("invalid degree.\n");
1446 goto err_property;
1447 }
1448
1449 /* check for buffer bound */
1450 if ((pos->x + pos->w > sz->hsize) ||
1451 (pos->y + pos->h > sz->vsize)) {
1452 DRM_ERROR("out of buf bound.\n");
1453 goto err_property;
1454 }
1455
1456 /* check for crop */
1457 if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) {
1458 if (swap) {
1459 if ((pos->h < pp->crop_min.hsize) ||
1460 (sz->vsize > pp->crop_max.hsize) ||
1461 (pos->w < pp->crop_min.vsize) ||
1462 (sz->hsize > pp->crop_max.vsize)) {
1463 DRM_ERROR("out of crop size.\n");
1464 goto err_property;
1465 }
1466 } else {
1467 if ((pos->w < pp->crop_min.hsize) ||
1468 (sz->hsize > pp->crop_max.hsize) ||
1469 (pos->h < pp->crop_min.vsize) ||
1470 (sz->vsize > pp->crop_max.vsize)) {
1471 DRM_ERROR("out of crop size.\n");
1472 goto err_property;
1473 }
1474 }
1475 }
1476
1477 /* check for scale */
1478 if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) {
1479 if (swap) {
1480 if ((pos->h < pp->scale_min.hsize) ||
1481 (sz->vsize > pp->scale_max.hsize) ||
1482 (pos->w < pp->scale_min.vsize) ||
1483 (sz->hsize > pp->scale_max.vsize)) {
1484 DRM_ERROR("out of scale size.\n");
1485 goto err_property;
1486 }
1487 } else {
1488 if ((pos->w < pp->scale_min.hsize) ||
1489 (sz->hsize > pp->scale_max.hsize) ||
1490 (pos->h < pp->scale_min.vsize) ||
1491 (sz->vsize > pp->scale_max.vsize)) {
1492 DRM_ERROR("out of scale size.\n");
1493 goto err_property;
1494 }
1495 }
1496 }
1497 }
1498
1499 return 0;
1500
1501err_property:
1502 for_each_ipp_ops(i) {
1503 if ((i == EXYNOS_DRM_OPS_SRC) &&
1504 (property->cmd == IPP_CMD_WB))
1505 continue;
1506
1507 config = &property->config[i];
1508 pos = &config->pos;
1509 sz = &config->sz;
1510
1511 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1512 i ? "dst" : "src", config->flip, config->degree,
1513 pos->x, pos->y, pos->w, pos->h,
1514 sz->hsize, sz->vsize);
1515 }
1516
1517 return -EINVAL;
1518}
1519
1520static void fimc_clear_addr(struct fimc_context *ctx)
1521{
1522 int i;
1523
1524 DRM_DEBUG_KMS("%s:\n", __func__);
1525
1526 for (i = 0; i < FIMC_MAX_SRC; i++) {
1527 fimc_write(0, EXYNOS_CIIYSA(i));
1528 fimc_write(0, EXYNOS_CIICBSA(i));
1529 fimc_write(0, EXYNOS_CIICRSA(i));
1530 }
1531
1532 for (i = 0; i < FIMC_MAX_DST; i++) {
1533 fimc_write(0, EXYNOS_CIOYSA(i));
1534 fimc_write(0, EXYNOS_CIOCBSA(i));
1535 fimc_write(0, EXYNOS_CIOCRSA(i));
1536 }
1537}
1538
1539static int fimc_ippdrv_reset(struct device *dev)
1540{
1541 struct fimc_context *ctx = get_fimc_context(dev);
1542
1543 DRM_DEBUG_KMS("%s\n", __func__);
1544
1545 /* reset h/w block */
1546 fimc_sw_reset(ctx, false);
1547
1548 /* reset scaler capability */
1549 memset(&ctx->sc, 0x0, sizeof(ctx->sc));
1550
1551 fimc_clear_addr(ctx);
1552
1553 return 0;
1554}
1555
1556static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1557{
1558 struct fimc_context *ctx = get_fimc_context(dev);
1559 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1560 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1561 struct drm_exynos_ipp_property *property;
1562 struct drm_exynos_ipp_config *config;
1563 struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX];
1564 struct drm_exynos_ipp_set_wb set_wb;
1565 int ret, i;
1566 u32 cfg0, cfg1;
1567
1568 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1569
1570 if (!c_node) {
1571 DRM_ERROR("failed to get c_node.\n");
1572 return -EINVAL;
1573 }
1574
1575 property = &c_node->property;
1576 if (!property) {
1577 DRM_ERROR("failed to get property.\n");
1578 return -EINVAL;
1579 }
1580
1581 fimc_handle_irq(ctx, true, false, true);
1582
1583 for_each_ipp_ops(i) {
1584 config = &property->config[i];
1585 img_pos[i] = config->pos;
1586 }
1587
1588 ret = fimc_set_prescaler(ctx, &ctx->sc,
1589 &img_pos[EXYNOS_DRM_OPS_SRC],
1590 &img_pos[EXYNOS_DRM_OPS_DST]);
1591 if (ret) {
1592 dev_err(dev, "failed to set precalser.\n");
1593 return ret;
1594 }
1595
1596 /* If set ture, we can save jpeg about screen */
1597 fimc_handle_jpeg(ctx, false);
1598 fimc_set_scaler(ctx, &ctx->sc);
1599 fimc_set_polarity(ctx, &ctx->pol);
1600
1601 switch (cmd) {
1602 case IPP_CMD_M2M:
1603 fimc_set_type_ctrl(ctx, FIMC_WB_NONE);
1604 fimc_handle_lastend(ctx, false);
1605
1606 /* setup dma */
1607 cfg0 = fimc_read(EXYNOS_MSCTRL);
1608 cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK;
1609 cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY;
1610 fimc_write(cfg0, EXYNOS_MSCTRL);
1611 break;
1612 case IPP_CMD_WB:
1613 fimc_set_type_ctrl(ctx, FIMC_WB_A);
1614 fimc_handle_lastend(ctx, true);
1615
1616 /* setup FIMD */
1617 fimc_set_camblk_fimd0_wb(ctx);
1618
1619 set_wb.enable = 1;
1620 set_wb.refresh = property->refresh_rate;
1621 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1622 break;
1623 case IPP_CMD_OUTPUT:
1624 default:
1625 ret = -EINVAL;
1626 dev_err(dev, "invalid operations.\n");
1627 return ret;
1628 }
1629
1630 /* Reset status */
1631 fimc_write(0x0, EXYNOS_CISTATUS);
1632
1633 cfg0 = fimc_read(EXYNOS_CIIMGCPT);
1634 cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1635 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1636
1637 /* Scaler */
1638 cfg1 = fimc_read(EXYNOS_CISCCTRL);
1639 cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK;
1640 cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE |
1641 EXYNOS_CISCCTRL_SCALERSTART);
1642
1643 fimc_write(cfg1, EXYNOS_CISCCTRL);
1644
1645 /* Enable image capture*/
1646 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN;
1647 fimc_write(cfg0, EXYNOS_CIIMGCPT);
1648
1649 /* Disable frame end irq */
1650 cfg0 = fimc_read(EXYNOS_CIGCTRL);
1651 cfg0 &= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1652 fimc_write(cfg0, EXYNOS_CIGCTRL);
1653
1654 cfg0 = fimc_read(EXYNOS_CIOCTRL);
1655 cfg0 &= ~EXYNOS_CIOCTRL_WEAVE_MASK;
1656 fimc_write(cfg0, EXYNOS_CIOCTRL);
1657
1658 if (cmd == IPP_CMD_M2M) {
1659 cfg0 = fimc_read(EXYNOS_MSCTRL);
1660 cfg0 |= EXYNOS_MSCTRL_ENVID;
1661 fimc_write(cfg0, EXYNOS_MSCTRL);
1662
1663 cfg0 = fimc_read(EXYNOS_MSCTRL);
1664 cfg0 |= EXYNOS_MSCTRL_ENVID;
1665 fimc_write(cfg0, EXYNOS_MSCTRL);
1666 }
1667
1668 return 0;
1669}
1670
1671static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1672{
1673 struct fimc_context *ctx = get_fimc_context(dev);
1674 struct drm_exynos_ipp_set_wb set_wb = {0, 0};
1675 u32 cfg;
1676
1677 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1678
1679 switch (cmd) {
1680 case IPP_CMD_M2M:
1681 /* Source clear */
1682 cfg = fimc_read(EXYNOS_MSCTRL);
1683 cfg &= ~EXYNOS_MSCTRL_INPUT_MASK;
1684 cfg &= ~EXYNOS_MSCTRL_ENVID;
1685 fimc_write(cfg, EXYNOS_MSCTRL);
1686 break;
1687 case IPP_CMD_WB:
1688 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1689 break;
1690 case IPP_CMD_OUTPUT:
1691 default:
1692 dev_err(dev, "invalid operations.\n");
1693 break;
1694 }
1695
1696 fimc_handle_irq(ctx, false, false, true);
1697
1698 /* reset sequence */
1699 fimc_write(0x0, EXYNOS_CIFCNTSEQ);
1700
1701 /* Scaler disable */
1702 cfg = fimc_read(EXYNOS_CISCCTRL);
1703 cfg &= ~EXYNOS_CISCCTRL_SCALERSTART;
1704 fimc_write(cfg, EXYNOS_CISCCTRL);
1705
1706 /* Disable image capture */
1707 cfg = fimc_read(EXYNOS_CIIMGCPT);
1708 cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
1709 fimc_write(cfg, EXYNOS_CIIMGCPT);
1710
1711 /* Enable frame end irq */
1712 cfg = fimc_read(EXYNOS_CIGCTRL);
1713 cfg |= EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1714 fimc_write(cfg, EXYNOS_CIGCTRL);
1715}
1716
1717static int __devinit fimc_probe(struct platform_device *pdev)
1718{
1719 struct device *dev = &pdev->dev;
1720 struct fimc_context *ctx;
1721 struct clk *parent_clk;
1722 struct resource *res;
1723 struct exynos_drm_ippdrv *ippdrv;
1724 struct exynos_drm_fimc_pdata *pdata;
1725 struct fimc_driverdata *ddata;
1726 int ret;
1727
1728 pdata = pdev->dev.platform_data;
1729 if (!pdata) {
1730 dev_err(dev, "no platform data specified.\n");
1731 return -EINVAL;
1732 }
1733
1734 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1735 if (!ctx)
1736 return -ENOMEM;
1737
1738 ddata = (struct fimc_driverdata *)
1739 platform_get_device_id(pdev)->driver_data;
1740
1741 /* clock control */
1742 ctx->sclk_fimc_clk = clk_get(dev, "sclk_fimc");
1743 if (IS_ERR(ctx->sclk_fimc_clk)) {
1744 dev_err(dev, "failed to get src fimc clock.\n");
1745 ret = PTR_ERR(ctx->sclk_fimc_clk);
1746 goto err_ctx;
1747 }
1748 clk_enable(ctx->sclk_fimc_clk);
1749
1750 ctx->fimc_clk = clk_get(dev, "fimc");
1751 if (IS_ERR(ctx->fimc_clk)) {
1752 dev_err(dev, "failed to get fimc clock.\n");
1753 ret = PTR_ERR(ctx->fimc_clk);
1754 clk_disable(ctx->sclk_fimc_clk);
1755 clk_put(ctx->sclk_fimc_clk);
1756 goto err_ctx;
1757 }
1758
1759 ctx->wb_clk = clk_get(dev, "pxl_async0");
1760 if (IS_ERR(ctx->wb_clk)) {
1761 dev_err(dev, "failed to get writeback a clock.\n");
1762 ret = PTR_ERR(ctx->wb_clk);
1763 clk_disable(ctx->sclk_fimc_clk);
1764 clk_put(ctx->sclk_fimc_clk);
1765 clk_put(ctx->fimc_clk);
1766 goto err_ctx;
1767 }
1768
1769 ctx->wb_b_clk = clk_get(dev, "pxl_async1");
1770 if (IS_ERR(ctx->wb_b_clk)) {
1771 dev_err(dev, "failed to get writeback b clock.\n");
1772 ret = PTR_ERR(ctx->wb_b_clk);
1773 clk_disable(ctx->sclk_fimc_clk);
1774 clk_put(ctx->sclk_fimc_clk);
1775 clk_put(ctx->fimc_clk);
1776 clk_put(ctx->wb_clk);
1777 goto err_ctx;
1778 }
1779
1780 parent_clk = clk_get(dev, ddata->parent_clk);
1781
1782 if (IS_ERR(parent_clk)) {
1783 dev_err(dev, "failed to get parent clock.\n");
1784 ret = PTR_ERR(parent_clk);
1785 clk_disable(ctx->sclk_fimc_clk);
1786 clk_put(ctx->sclk_fimc_clk);
1787 clk_put(ctx->fimc_clk);
1788 clk_put(ctx->wb_clk);
1789 clk_put(ctx->wb_b_clk);
1790 goto err_ctx;
1791 }
1792
1793 if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
1794 dev_err(dev, "failed to set parent.\n");
1795 ret = -EINVAL;
1796 clk_put(parent_clk);
1797 clk_disable(ctx->sclk_fimc_clk);
1798 clk_put(ctx->sclk_fimc_clk);
1799 clk_put(ctx->fimc_clk);
1800 clk_put(ctx->wb_clk);
1801 clk_put(ctx->wb_b_clk);
1802 goto err_ctx;
1803 }
1804
1805 clk_put(parent_clk);
1806 clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
1807
1808 /* resource memory */
1809 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1810 if (!ctx->regs_res) {
1811 dev_err(dev, "failed to find registers.\n");
1812 ret = -ENOENT;
1813 goto err_clk;
1814 }
1815
1816 ctx->regs = devm_request_and_ioremap(dev, ctx->regs_res);
1817 if (!ctx->regs) {
1818 dev_err(dev, "failed to map registers.\n");
1819 ret = -ENXIO;
1820 goto err_clk;
1821 }
1822
1823 /* resource irq */
1824 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1825 if (!res) {
1826 dev_err(dev, "failed to request irq resource.\n");
1827 ret = -ENOENT;
1828 goto err_get_regs;
1829 }
1830
1831 ctx->irq = res->start;
1832 ret = request_threaded_irq(ctx->irq, NULL, fimc_irq_handler,
1833 IRQF_ONESHOT, "drm_fimc", ctx);
1834 if (ret < 0) {
1835 dev_err(dev, "failed to request irq.\n");
1836 goto err_get_regs;
1837 }
1838
1839 /* context initailization */
1840 ctx->id = pdev->id;
1841 ctx->pol = pdata->pol;
1842 ctx->ddata = ddata;
1843
1844 ippdrv = &ctx->ippdrv;
1845 ippdrv->dev = dev;
1846 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
1847 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops;
1848 ippdrv->check_property = fimc_ippdrv_check_property;
1849 ippdrv->reset = fimc_ippdrv_reset;
1850 ippdrv->start = fimc_ippdrv_start;
1851 ippdrv->stop = fimc_ippdrv_stop;
1852 ret = fimc_init_prop_list(ippdrv);
1853 if (ret < 0) {
1854 dev_err(dev, "failed to init property list.\n");
1855 goto err_get_irq;
1856 }
1857
1858 DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
1859 (int)ippdrv);
1860
1861 mutex_init(&ctx->lock);
1862 platform_set_drvdata(pdev, ctx);
1863
1864 pm_runtime_set_active(dev);
1865 pm_runtime_enable(dev);
1866
1867 ret = exynos_drm_ippdrv_register(ippdrv);
1868 if (ret < 0) {
1869 dev_err(dev, "failed to register drm fimc device.\n");
1870 goto err_ippdrv_register;
1871 }
1872
1873 dev_info(&pdev->dev, "drm fimc registered successfully.\n");
1874
1875 return 0;
1876
1877err_ippdrv_register:
1878 devm_kfree(dev, ippdrv->prop_list);
1879 pm_runtime_disable(dev);
1880err_get_irq:
1881 free_irq(ctx->irq, ctx);
1882err_get_regs:
1883 devm_iounmap(dev, ctx->regs);
1884err_clk:
1885 clk_put(ctx->sclk_fimc_clk);
1886 clk_put(ctx->fimc_clk);
1887 clk_put(ctx->wb_clk);
1888 clk_put(ctx->wb_b_clk);
1889err_ctx:
1890 devm_kfree(dev, ctx);
1891 return ret;
1892}
1893
1894static int __devexit fimc_remove(struct platform_device *pdev)
1895{
1896 struct device *dev = &pdev->dev;
1897 struct fimc_context *ctx = get_fimc_context(dev);
1898 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1899
1900 devm_kfree(dev, ippdrv->prop_list);
1901 exynos_drm_ippdrv_unregister(ippdrv);
1902 mutex_destroy(&ctx->lock);
1903
1904 pm_runtime_set_suspended(dev);
1905 pm_runtime_disable(dev);
1906
1907 free_irq(ctx->irq, ctx);
1908 devm_iounmap(dev, ctx->regs);
1909
1910 clk_put(ctx->sclk_fimc_clk);
1911 clk_put(ctx->fimc_clk);
1912 clk_put(ctx->wb_clk);
1913 clk_put(ctx->wb_b_clk);
1914
1915 devm_kfree(dev, ctx);
1916
1917 return 0;
1918}
1919
1920#ifdef CONFIG_PM_SLEEP
1921static int fimc_suspend(struct device *dev)
1922{
1923 struct fimc_context *ctx = get_fimc_context(dev);
1924
1925 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1926
1927 if (pm_runtime_suspended(dev))
1928 return 0;
1929
1930 return fimc_clk_ctrl(ctx, false);
1931}
1932
1933static int fimc_resume(struct device *dev)
1934{
1935 struct fimc_context *ctx = get_fimc_context(dev);
1936
1937 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1938
1939 if (!pm_runtime_suspended(dev))
1940 return fimc_clk_ctrl(ctx, true);
1941
1942 return 0;
1943}
1944#endif
1945
1946#ifdef CONFIG_PM_RUNTIME
1947static int fimc_runtime_suspend(struct device *dev)
1948{
1949 struct fimc_context *ctx = get_fimc_context(dev);
1950
1951 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1952
1953 return fimc_clk_ctrl(ctx, false);
1954}
1955
1956static int fimc_runtime_resume(struct device *dev)
1957{
1958 struct fimc_context *ctx = get_fimc_context(dev);
1959
1960 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1961
1962 return fimc_clk_ctrl(ctx, true);
1963}
1964#endif
1965
1966static struct fimc_driverdata exynos4210_fimc_data = {
1967 .parent_clk = "mout_mpll",
1968};
1969
1970static struct fimc_driverdata exynos4410_fimc_data = {
1971 .parent_clk = "mout_mpll_user",
1972};
1973
1974static struct platform_device_id fimc_driver_ids[] = {
1975 {
1976 .name = "exynos4210-fimc",
1977 .driver_data = (unsigned long)&exynos4210_fimc_data,
1978 }, {
1979 .name = "exynos4412-fimc",
1980 .driver_data = (unsigned long)&exynos4410_fimc_data,
1981 },
1982 {},
1983};
1984MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1985
1986static const struct dev_pm_ops fimc_pm_ops = {
1987 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
1988 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
1989};
1990
1991struct platform_driver fimc_driver = {
1992 .probe = fimc_probe,
1993 .remove = __devexit_p(fimc_remove),
1994 .id_table = fimc_driver_ids,
1995 .driver = {
1996 .name = "exynos-drm-fimc",
1997 .owner = THIS_MODULE,
1998 .pm = &fimc_pm_ops,
1999 },
2000};
2001
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.h b/drivers/gpu/drm/exynos/exynos_drm_fimc.h
new file mode 100644
index 000000000000..dc970fa0d888
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.h
@@ -0,0 +1,37 @@
1/*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 *
4 * Authors:
5 * Eunchul Kim <chulspro.kim@samsung.com>
6 * Jinyoung Jeon <jy0.jeon@samsung.com>
7 * Sangmin Lee <lsmin.lee@samsung.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29#ifndef _EXYNOS_DRM_FIMC_H_
30#define _EXYNOS_DRM_FIMC_H_
31
32/*
33 * TODO
34 * FIMD output interface notifier callback.
35 */
36
37#endif /* _EXYNOS_DRM_FIMC_H_ */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 00bd266a31bb..bf0d9baca2bc 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -17,6 +17,7 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/clk.h> 19#include <linux/clk.h>
20#include <linux/of_device.h>
20#include <linux/pm_runtime.h> 21#include <linux/pm_runtime.h>
21 22
22#include <video/samsung_fimd.h> 23#include <video/samsung_fimd.h>
@@ -79,10 +80,10 @@ struct fimd_win_data {
79 unsigned int fb_height; 80 unsigned int fb_height;
80 unsigned int bpp; 81 unsigned int bpp;
81 dma_addr_t dma_addr; 82 dma_addr_t dma_addr;
82 void __iomem *vaddr;
83 unsigned int buf_offsize; 83 unsigned int buf_offsize;
84 unsigned int line_size; /* bytes */ 84 unsigned int line_size; /* bytes */
85 bool enabled; 85 bool enabled;
86 bool resume;
86}; 87};
87 88
88struct fimd_context { 89struct fimd_context {
@@ -100,13 +101,34 @@ struct fimd_context {
100 u32 vidcon1; 101 u32 vidcon1;
101 bool suspended; 102 bool suspended;
102 struct mutex lock; 103 struct mutex lock;
104 wait_queue_head_t wait_vsync_queue;
105 atomic_t wait_vsync_event;
103 106
104 struct exynos_drm_panel_info *panel; 107 struct exynos_drm_panel_info *panel;
105}; 108};
106 109
110#ifdef CONFIG_OF
111static const struct of_device_id fimd_driver_dt_match[] = {
112 { .compatible = "samsung,exynos4-fimd",
113 .data = &exynos4_fimd_driver_data },
114 { .compatible = "samsung,exynos5-fimd",
115 .data = &exynos5_fimd_driver_data },
116 {},
117};
118MODULE_DEVICE_TABLE(of, fimd_driver_dt_match);
119#endif
120
107static inline struct fimd_driver_data *drm_fimd_get_driver_data( 121static inline struct fimd_driver_data *drm_fimd_get_driver_data(
108 struct platform_device *pdev) 122 struct platform_device *pdev)
109{ 123{
124#ifdef CONFIG_OF
125 const struct of_device_id *of_id =
126 of_match_device(fimd_driver_dt_match, &pdev->dev);
127
128 if (of_id)
129 return (struct fimd_driver_data *)of_id->data;
130#endif
131
110 return (struct fimd_driver_data *) 132 return (struct fimd_driver_data *)
111 platform_get_device_id(pdev)->driver_data; 133 platform_get_device_id(pdev)->driver_data;
112} 134}
@@ -241,7 +263,9 @@ static void fimd_commit(struct device *dev)
241 263
242 /* setup horizontal and vertical display size. */ 264 /* setup horizontal and vertical display size. */
243 val = VIDTCON2_LINEVAL(timing->yres - 1) | 265 val = VIDTCON2_LINEVAL(timing->yres - 1) |
244 VIDTCON2_HOZVAL(timing->xres - 1); 266 VIDTCON2_HOZVAL(timing->xres - 1) |
267 VIDTCON2_LINEVAL_E(timing->yres - 1) |
268 VIDTCON2_HOZVAL_E(timing->xres - 1);
245 writel(val, ctx->regs + driver_data->timing_base + VIDTCON2); 269 writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
246 270
247 /* setup clock source, clock divider, enable dma. */ 271 /* setup clock source, clock divider, enable dma. */
@@ -308,12 +332,32 @@ static void fimd_disable_vblank(struct device *dev)
308 } 332 }
309} 333}
310 334
335static void fimd_wait_for_vblank(struct device *dev)
336{
337 struct fimd_context *ctx = get_fimd_context(dev);
338
339 if (ctx->suspended)
340 return;
341
342 atomic_set(&ctx->wait_vsync_event, 1);
343
344 /*
345 * wait for FIMD to signal VSYNC interrupt or return after
346 * timeout which is set to 50ms (refresh rate of 20).
347 */
348 if (!wait_event_timeout(ctx->wait_vsync_queue,
349 !atomic_read(&ctx->wait_vsync_event),
350 DRM_HZ/20))
351 DRM_DEBUG_KMS("vblank wait timed out.\n");
352}
353
311static struct exynos_drm_manager_ops fimd_manager_ops = { 354static struct exynos_drm_manager_ops fimd_manager_ops = {
312 .dpms = fimd_dpms, 355 .dpms = fimd_dpms,
313 .apply = fimd_apply, 356 .apply = fimd_apply,
314 .commit = fimd_commit, 357 .commit = fimd_commit,
315 .enable_vblank = fimd_enable_vblank, 358 .enable_vblank = fimd_enable_vblank,
316 .disable_vblank = fimd_disable_vblank, 359 .disable_vblank = fimd_disable_vblank,
360 .wait_for_vblank = fimd_wait_for_vblank,
317}; 361};
318 362
319static void fimd_win_mode_set(struct device *dev, 363static void fimd_win_mode_set(struct device *dev,
@@ -352,7 +396,6 @@ static void fimd_win_mode_set(struct device *dev,
352 win_data->fb_width = overlay->fb_width; 396 win_data->fb_width = overlay->fb_width;
353 win_data->fb_height = overlay->fb_height; 397 win_data->fb_height = overlay->fb_height;
354 win_data->dma_addr = overlay->dma_addr[0] + offset; 398 win_data->dma_addr = overlay->dma_addr[0] + offset;
355 win_data->vaddr = overlay->vaddr[0] + offset;
356 win_data->bpp = overlay->bpp; 399 win_data->bpp = overlay->bpp;
357 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * 400 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
358 (overlay->bpp >> 3); 401 (overlay->bpp >> 3);
@@ -362,9 +405,7 @@ static void fimd_win_mode_set(struct device *dev,
362 win_data->offset_x, win_data->offset_y); 405 win_data->offset_x, win_data->offset_y);
363 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", 406 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
364 win_data->ovl_width, win_data->ovl_height); 407 win_data->ovl_width, win_data->ovl_height);
365 DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n", 408 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
366 (unsigned long)win_data->dma_addr,
367 (unsigned long)win_data->vaddr);
368 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", 409 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
369 overlay->fb_width, overlay->crtc_width); 410 overlay->fb_width, overlay->crtc_width);
370} 411}
@@ -452,6 +493,8 @@ static void fimd_win_commit(struct device *dev, int zpos)
452 struct fimd_win_data *win_data; 493 struct fimd_win_data *win_data;
453 int win = zpos; 494 int win = zpos;
454 unsigned long val, alpha, size; 495 unsigned long val, alpha, size;
496 unsigned int last_x;
497 unsigned int last_y;
455 498
456 DRM_DEBUG_KMS("%s\n", __FILE__); 499 DRM_DEBUG_KMS("%s\n", __FILE__);
457 500
@@ -497,24 +540,32 @@ static void fimd_win_commit(struct device *dev, int zpos)
497 540
498 /* buffer size */ 541 /* buffer size */
499 val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) | 542 val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
500 VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size); 543 VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) |
544 VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) |
545 VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size);
501 writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0)); 546 writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
502 547
503 /* OSD position */ 548 /* OSD position */
504 val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) | 549 val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
505 VIDOSDxA_TOPLEFT_Y(win_data->offset_y); 550 VIDOSDxA_TOPLEFT_Y(win_data->offset_y) |
551 VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) |
552 VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y);
506 writel(val, ctx->regs + VIDOSD_A(win)); 553 writel(val, ctx->regs + VIDOSD_A(win));
507 554
508 val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x + 555 last_x = win_data->offset_x + win_data->ovl_width;
509 win_data->ovl_width - 1) | 556 if (last_x)
510 VIDOSDxB_BOTRIGHT_Y(win_data->offset_y + 557 last_x--;
511 win_data->ovl_height - 1); 558 last_y = win_data->offset_y + win_data->ovl_height;
559 if (last_y)
560 last_y--;
561
562 val = VIDOSDxB_BOTRIGHT_X(last_x) | VIDOSDxB_BOTRIGHT_Y(last_y) |
563 VIDOSDxB_BOTRIGHT_X_E(last_x) | VIDOSDxB_BOTRIGHT_Y_E(last_y);
564
512 writel(val, ctx->regs + VIDOSD_B(win)); 565 writel(val, ctx->regs + VIDOSD_B(win));
513 566
514 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", 567 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
515 win_data->offset_x, win_data->offset_y, 568 win_data->offset_x, win_data->offset_y, last_x, last_y);
516 win_data->offset_x + win_data->ovl_width - 1,
517 win_data->offset_y + win_data->ovl_height - 1);
518 569
519 /* hardware window 0 doesn't support alpha channel. */ 570 /* hardware window 0 doesn't support alpha channel. */
520 if (win != 0) { 571 if (win != 0) {
@@ -574,6 +625,12 @@ static void fimd_win_disable(struct device *dev, int zpos)
574 625
575 win_data = &ctx->win_data[win]; 626 win_data = &ctx->win_data[win];
576 627
628 if (ctx->suspended) {
629 /* do not resume this window*/
630 win_data->resume = false;
631 return;
632 }
633
577 /* protect windows */ 634 /* protect windows */
578 val = readl(ctx->regs + SHADOWCON); 635 val = readl(ctx->regs + SHADOWCON);
579 val |= SHADOWCON_WINx_PROTECT(win); 636 val |= SHADOWCON_WINx_PROTECT(win);
@@ -593,22 +650,10 @@ static void fimd_win_disable(struct device *dev, int zpos)
593 win_data->enabled = false; 650 win_data->enabled = false;
594} 651}
595 652
596static void fimd_wait_for_vblank(struct device *dev)
597{
598 struct fimd_context *ctx = get_fimd_context(dev);
599 int ret;
600
601 ret = wait_for((__raw_readl(ctx->regs + VIDCON1) &
602 VIDCON1_VSTATUS_VSYNC), 50);
603 if (ret < 0)
604 DRM_DEBUG_KMS("vblank wait timed out.\n");
605}
606
607static struct exynos_drm_overlay_ops fimd_overlay_ops = { 653static struct exynos_drm_overlay_ops fimd_overlay_ops = {
608 .mode_set = fimd_win_mode_set, 654 .mode_set = fimd_win_mode_set,
609 .commit = fimd_win_commit, 655 .commit = fimd_win_commit,
610 .disable = fimd_win_disable, 656 .disable = fimd_win_disable,
611 .wait_for_vblank = fimd_wait_for_vblank,
612}; 657};
613 658
614static struct exynos_drm_manager fimd_manager = { 659static struct exynos_drm_manager fimd_manager = {
@@ -667,6 +712,11 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
667 drm_handle_vblank(drm_dev, manager->pipe); 712 drm_handle_vblank(drm_dev, manager->pipe);
668 fimd_finish_pageflip(drm_dev, manager->pipe); 713 fimd_finish_pageflip(drm_dev, manager->pipe);
669 714
715 /* set wait vsync event to zero and wake up queue. */
716 if (atomic_read(&ctx->wait_vsync_event)) {
717 atomic_set(&ctx->wait_vsync_event, 0);
718 DRM_WAKEUP(&ctx->wait_vsync_queue);
719 }
670out: 720out:
671 return IRQ_HANDLED; 721 return IRQ_HANDLED;
672} 722}
@@ -794,11 +844,38 @@ static int fimd_clock(struct fimd_context *ctx, bool enable)
794 return 0; 844 return 0;
795} 845}
796 846
847static void fimd_window_suspend(struct device *dev)
848{
849 struct fimd_context *ctx = get_fimd_context(dev);
850 struct fimd_win_data *win_data;
851 int i;
852
853 for (i = 0; i < WINDOWS_NR; i++) {
854 win_data = &ctx->win_data[i];
855 win_data->resume = win_data->enabled;
856 fimd_win_disable(dev, i);
857 }
858 fimd_wait_for_vblank(dev);
859}
860
861static void fimd_window_resume(struct device *dev)
862{
863 struct fimd_context *ctx = get_fimd_context(dev);
864 struct fimd_win_data *win_data;
865 int i;
866
867 for (i = 0; i < WINDOWS_NR; i++) {
868 win_data = &ctx->win_data[i];
869 win_data->enabled = win_data->resume;
870 win_data->resume = false;
871 }
872}
873
797static int fimd_activate(struct fimd_context *ctx, bool enable) 874static int fimd_activate(struct fimd_context *ctx, bool enable)
798{ 875{
876 struct device *dev = ctx->subdrv.dev;
799 if (enable) { 877 if (enable) {
800 int ret; 878 int ret;
801 struct device *dev = ctx->subdrv.dev;
802 879
803 ret = fimd_clock(ctx, true); 880 ret = fimd_clock(ctx, true);
804 if (ret < 0) 881 if (ret < 0)
@@ -809,7 +886,11 @@ static int fimd_activate(struct fimd_context *ctx, bool enable)
809 /* if vblank was enabled status, enable it again. */ 886 /* if vblank was enabled status, enable it again. */
810 if (test_and_clear_bit(0, &ctx->irq_flags)) 887 if (test_and_clear_bit(0, &ctx->irq_flags))
811 fimd_enable_vblank(dev); 888 fimd_enable_vblank(dev);
889
890 fimd_window_resume(dev);
812 } else { 891 } else {
892 fimd_window_suspend(dev);
893
813 fimd_clock(ctx, false); 894 fimd_clock(ctx, false);
814 ctx->suspended = true; 895 ctx->suspended = true;
815 } 896 }
@@ -885,6 +966,8 @@ static int __devinit fimd_probe(struct platform_device *pdev)
885 ctx->vidcon1 = pdata->vidcon1; 966 ctx->vidcon1 = pdata->vidcon1;
886 ctx->default_win = pdata->default_win; 967 ctx->default_win = pdata->default_win;
887 ctx->panel = panel; 968 ctx->panel = panel;
969 DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
970 atomic_set(&ctx->wait_vsync_event, 0);
888 971
889 subdrv = &ctx->subdrv; 972 subdrv = &ctx->subdrv;
890 973
@@ -1028,5 +1111,6 @@ struct platform_driver fimd_driver = {
1028 .name = "exynos4-fb", 1111 .name = "exynos4-fb",
1029 .owner = THIS_MODULE, 1112 .owner = THIS_MODULE,
1030 .pm = &fimd_pm_ops, 1113 .pm = &fimd_pm_ops,
1114 .of_match_table = of_match_ptr(fimd_driver_dt_match),
1031 }, 1115 },
1032}; 1116};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 99227246ce82..d48183e7e056 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -400,7 +400,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
400 if (vm_size > buffer->size) 400 if (vm_size > buffer->size)
401 return -EINVAL; 401 return -EINVAL;
402 402
403 ret = dma_mmap_attrs(drm_dev->dev, vma, buffer->kvaddr, 403 ret = dma_mmap_attrs(drm_dev->dev, vma, buffer->pages,
404 buffer->dma_addr, buffer->size, 404 buffer->dma_addr, buffer->size,
405 &buffer->dma_attrs); 405 &buffer->dma_attrs);
406 if (ret < 0) { 406 if (ret < 0) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index d3ea106a9a77..f11f2afd5bfc 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -40,6 +40,7 @@
40 * - this address could be physical address without IOMMU and 40 * - this address could be physical address without IOMMU and
41 * device address with IOMMU. 41 * device address with IOMMU.
42 * @write: whether pages will be written to by the caller. 42 * @write: whether pages will be written to by the caller.
43 * @pages: Array of backing pages.
43 * @sgt: sg table to transfer page data. 44 * @sgt: sg table to transfer page data.
44 * @size: size of allocated memory region. 45 * @size: size of allocated memory region.
45 * @pfnmap: indicate whether memory region from userptr is mmaped with 46 * @pfnmap: indicate whether memory region from userptr is mmaped with
@@ -51,6 +52,7 @@ struct exynos_drm_gem_buf {
51 dma_addr_t dma_addr; 52 dma_addr_t dma_addr;
52 struct dma_attrs dma_attrs; 53 struct dma_attrs dma_attrs;
53 unsigned int write; 54 unsigned int write;
55 struct page **pages;
54 struct sg_table *sgt; 56 struct sg_table *sgt;
55 unsigned long size; 57 unsigned long size;
56 bool pfnmap; 58 bool pfnmap;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
new file mode 100644
index 000000000000..5639353d47b9
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -0,0 +1,1870 @@
1/*
2 * Copyright (C) 2012 Samsung Electronics Co.Ltd
3 * Authors:
4 * Eunchul Kim <chulspro.kim@samsung.com>
5 * Jinyoung Jeon <jy0.jeon@samsung.com>
6 * Sangmin Lee <lsmin.lee@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/clk.h>
18#include <linux/pm_runtime.h>
19#include <plat/map-base.h>
20
21#include <drm/drmP.h>
22#include <drm/exynos_drm.h>
23#include "regs-gsc.h"
24#include "exynos_drm_ipp.h"
25#include "exynos_drm_gsc.h"
26
27/*
28 * GSC is stand for General SCaler and
29 * supports image scaler/rotator and input/output DMA operations.
30 * input DMA reads image data from the memory.
31 * output DMA writes image data to memory.
32 * GSC supports image rotation and image effect functions.
33 *
34 * M2M operation : supports crop/scale/rotation/csc so on.
35 * Memory ----> GSC H/W ----> Memory.
36 * Writeback operation : supports cloned screen with FIMD.
37 * FIMD ----> GSC H/W ----> Memory.
38 * Output operation : supports direct display using local path.
39 * Memory ----> GSC H/W ----> FIMD, Mixer.
40 */
41
42/*
43 * TODO
44 * 1. check suspend/resume api if needed.
45 * 2. need to check use case platform_device_id.
46 * 3. check src/dst size with, height.
47 * 4. added check_prepare api for right register.
48 * 5. need to add supported list in prop_list.
49 * 6. check prescaler/scaler optimization.
50 */
51
52#define GSC_MAX_DEVS 4
53#define GSC_MAX_SRC 4
54#define GSC_MAX_DST 16
55#define GSC_RESET_TIMEOUT 50
56#define GSC_BUF_STOP 1
57#define GSC_BUF_START 2
58#define GSC_REG_SZ 16
59#define GSC_WIDTH_ITU_709 1280
60#define GSC_SC_UP_MAX_RATIO 65536
61#define GSC_SC_DOWN_RATIO_7_8 74898
62#define GSC_SC_DOWN_RATIO_6_8 87381
63#define GSC_SC_DOWN_RATIO_5_8 104857
64#define GSC_SC_DOWN_RATIO_4_8 131072
65#define GSC_SC_DOWN_RATIO_3_8 174762
66#define GSC_SC_DOWN_RATIO_2_8 262144
67#define GSC_REFRESH_MIN 12
68#define GSC_REFRESH_MAX 60
69#define GSC_CROP_MAX 8192
70#define GSC_CROP_MIN 32
71#define GSC_SCALE_MAX 4224
72#define GSC_SCALE_MIN 32
73#define GSC_COEF_RATIO 7
74#define GSC_COEF_PHASE 9
75#define GSC_COEF_ATTR 16
76#define GSC_COEF_H_8T 8
77#define GSC_COEF_V_4T 4
78#define GSC_COEF_DEPTH 3
79
80#define get_gsc_context(dev) platform_get_drvdata(to_platform_device(dev))
81#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
82 struct gsc_context, ippdrv);
83#define gsc_read(offset) readl(ctx->regs + (offset))
84#define gsc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
85
86/*
87 * A structure of scaler.
88 *
89 * @range: narrow, wide.
90 * @pre_shfactor: pre sclaer shift factor.
91 * @pre_hratio: horizontal ratio of the prescaler.
92 * @pre_vratio: vertical ratio of the prescaler.
93 * @main_hratio: the main scaler's horizontal ratio.
94 * @main_vratio: the main scaler's vertical ratio.
95 */
96struct gsc_scaler {
97 bool range;
98 u32 pre_shfactor;
99 u32 pre_hratio;
100 u32 pre_vratio;
101 unsigned long main_hratio;
102 unsigned long main_vratio;
103};
104
105/*
106 * A structure of scaler capability.
107 *
108 * find user manual 49.2 features.
109 * @tile_w: tile mode or rotation width.
110 * @tile_h: tile mode or rotation height.
111 * @w: other cases width.
112 * @h: other cases height.
113 */
114struct gsc_capability {
115 /* tile or rotation */
116 u32 tile_w;
117 u32 tile_h;
118 /* other cases */
119 u32 w;
120 u32 h;
121};
122
123/*
124 * A structure of gsc context.
125 *
126 * @ippdrv: prepare initialization using ippdrv.
127 * @regs_res: register resources.
128 * @regs: memory mapped io registers.
129 * @lock: locking of operations.
130 * @gsc_clk: gsc gate clock.
131 * @sc: scaler infomations.
132 * @id: gsc id.
133 * @irq: irq number.
134 * @rotation: supports rotation of src.
135 * @suspended: qos operations.
136 */
137struct gsc_context {
138 struct exynos_drm_ippdrv ippdrv;
139 struct resource *regs_res;
140 void __iomem *regs;
141 struct mutex lock;
142 struct clk *gsc_clk;
143 struct gsc_scaler sc;
144 int id;
145 int irq;
146 bool rotation;
147 bool suspended;
148};
149
150/* 8-tap Filter Coefficient */
151static const int h_coef_8t[GSC_COEF_RATIO][GSC_COEF_ATTR][GSC_COEF_H_8T] = {
152 { /* Ratio <= 65536 (~8:8) */
153 { 0, 0, 0, 128, 0, 0, 0, 0 },
154 { -1, 2, -6, 127, 7, -2, 1, 0 },
155 { -1, 4, -12, 125, 16, -5, 1, 0 },
156 { -1, 5, -15, 120, 25, -8, 2, 0 },
157 { -1, 6, -18, 114, 35, -10, 3, -1 },
158 { -1, 6, -20, 107, 46, -13, 4, -1 },
159 { -2, 7, -21, 99, 57, -16, 5, -1 },
160 { -1, 6, -20, 89, 68, -18, 5, -1 },
161 { -1, 6, -20, 79, 79, -20, 6, -1 },
162 { -1, 5, -18, 68, 89, -20, 6, -1 },
163 { -1, 5, -16, 57, 99, -21, 7, -2 },
164 { -1, 4, -13, 46, 107, -20, 6, -1 },
165 { -1, 3, -10, 35, 114, -18, 6, -1 },
166 { 0, 2, -8, 25, 120, -15, 5, -1 },
167 { 0, 1, -5, 16, 125, -12, 4, -1 },
168 { 0, 1, -2, 7, 127, -6, 2, -1 }
169 }, { /* 65536 < Ratio <= 74898 (~8:7) */
170 { 3, -8, 14, 111, 13, -8, 3, 0 },
171 { 2, -6, 7, 112, 21, -10, 3, -1 },
172 { 2, -4, 1, 110, 28, -12, 4, -1 },
173 { 1, -2, -3, 106, 36, -13, 4, -1 },
174 { 1, -1, -7, 103, 44, -15, 4, -1 },
175 { 1, 1, -11, 97, 53, -16, 4, -1 },
176 { 0, 2, -13, 91, 61, -16, 4, -1 },
177 { 0, 3, -15, 85, 69, -17, 4, -1 },
178 { 0, 3, -16, 77, 77, -16, 3, 0 },
179 { -1, 4, -17, 69, 85, -15, 3, 0 },
180 { -1, 4, -16, 61, 91, -13, 2, 0 },
181 { -1, 4, -16, 53, 97, -11, 1, 1 },
182 { -1, 4, -15, 44, 103, -7, -1, 1 },
183 { -1, 4, -13, 36, 106, -3, -2, 1 },
184 { -1, 4, -12, 28, 110, 1, -4, 2 },
185 { -1, 3, -10, 21, 112, 7, -6, 2 }
186 }, { /* 74898 < Ratio <= 87381 (~8:6) */
187 { 2, -11, 25, 96, 25, -11, 2, 0 },
188 { 2, -10, 19, 96, 31, -12, 2, 0 },
189 { 2, -9, 14, 94, 37, -12, 2, 0 },
190 { 2, -8, 10, 92, 43, -12, 1, 0 },
191 { 2, -7, 5, 90, 49, -12, 1, 0 },
192 { 2, -5, 1, 86, 55, -12, 0, 1 },
193 { 2, -4, -2, 82, 61, -11, -1, 1 },
194 { 1, -3, -5, 77, 67, -9, -1, 1 },
195 { 1, -2, -7, 72, 72, -7, -2, 1 },
196 { 1, -1, -9, 67, 77, -5, -3, 1 },
197 { 1, -1, -11, 61, 82, -2, -4, 2 },
198 { 1, 0, -12, 55, 86, 1, -5, 2 },
199 { 0, 1, -12, 49, 90, 5, -7, 2 },
200 { 0, 1, -12, 43, 92, 10, -8, 2 },
201 { 0, 2, -12, 37, 94, 14, -9, 2 },
202 { 0, 2, -12, 31, 96, 19, -10, 2 }
203 }, { /* 87381 < Ratio <= 104857 (~8:5) */
204 { -1, -8, 33, 80, 33, -8, -1, 0 },
205 { -1, -8, 28, 80, 37, -7, -2, 1 },
206 { 0, -8, 24, 79, 41, -7, -2, 1 },
207 { 0, -8, 20, 78, 46, -6, -3, 1 },
208 { 0, -8, 16, 76, 50, -4, -3, 1 },
209 { 0, -7, 13, 74, 54, -3, -4, 1 },
210 { 1, -7, 10, 71, 58, -1, -5, 1 },
211 { 1, -6, 6, 68, 62, 1, -5, 1 },
212 { 1, -6, 4, 65, 65, 4, -6, 1 },
213 { 1, -5, 1, 62, 68, 6, -6, 1 },
214 { 1, -5, -1, 58, 71, 10, -7, 1 },
215 { 1, -4, -3, 54, 74, 13, -7, 0 },
216 { 1, -3, -4, 50, 76, 16, -8, 0 },
217 { 1, -3, -6, 46, 78, 20, -8, 0 },
218 { 1, -2, -7, 41, 79, 24, -8, 0 },
219 { 1, -2, -7, 37, 80, 28, -8, -1 }
220 }, { /* 104857 < Ratio <= 131072 (~8:4) */
221 { -3, 0, 35, 64, 35, 0, -3, 0 },
222 { -3, -1, 32, 64, 38, 1, -3, 0 },
223 { -2, -2, 29, 63, 41, 2, -3, 0 },
224 { -2, -3, 27, 63, 43, 4, -4, 0 },
225 { -2, -3, 24, 61, 46, 6, -4, 0 },
226 { -2, -3, 21, 60, 49, 7, -4, 0 },
227 { -1, -4, 19, 59, 51, 9, -4, -1 },
228 { -1, -4, 16, 57, 53, 12, -4, -1 },
229 { -1, -4, 14, 55, 55, 14, -4, -1 },
230 { -1, -4, 12, 53, 57, 16, -4, -1 },
231 { -1, -4, 9, 51, 59, 19, -4, -1 },
232 { 0, -4, 7, 49, 60, 21, -3, -2 },
233 { 0, -4, 6, 46, 61, 24, -3, -2 },
234 { 0, -4, 4, 43, 63, 27, -3, -2 },
235 { 0, -3, 2, 41, 63, 29, -2, -2 },
236 { 0, -3, 1, 38, 64, 32, -1, -3 }
237 }, { /* 131072 < Ratio <= 174762 (~8:3) */
238 { -1, 8, 33, 48, 33, 8, -1, 0 },
239 { -1, 7, 31, 49, 35, 9, -1, -1 },
240 { -1, 6, 30, 49, 36, 10, -1, -1 },
241 { -1, 5, 28, 48, 38, 12, -1, -1 },
242 { -1, 4, 26, 48, 39, 13, 0, -1 },
243 { -1, 3, 24, 47, 41, 15, 0, -1 },
244 { -1, 2, 23, 47, 42, 16, 0, -1 },
245 { -1, 2, 21, 45, 43, 18, 1, -1 },
246 { -1, 1, 19, 45, 45, 19, 1, -1 },
247 { -1, 1, 18, 43, 45, 21, 2, -1 },
248 { -1, 0, 16, 42, 47, 23, 2, -1 },
249 { -1, 0, 15, 41, 47, 24, 3, -1 },
250 { -1, 0, 13, 39, 48, 26, 4, -1 },
251 { -1, -1, 12, 38, 48, 28, 5, -1 },
252 { -1, -1, 10, 36, 49, 30, 6, -1 },
253 { -1, -1, 9, 35, 49, 31, 7, -1 }
254 }, { /* 174762 < Ratio <= 262144 (~8:2) */
255 { 2, 13, 30, 38, 30, 13, 2, 0 },
256 { 2, 12, 29, 38, 30, 14, 3, 0 },
257 { 2, 11, 28, 38, 31, 15, 3, 0 },
258 { 2, 10, 26, 38, 32, 16, 4, 0 },
259 { 1, 10, 26, 37, 33, 17, 4, 0 },
260 { 1, 9, 24, 37, 34, 18, 5, 0 },
261 { 1, 8, 24, 37, 34, 19, 5, 0 },
262 { 1, 7, 22, 36, 35, 20, 6, 1 },
263 { 1, 6, 21, 36, 36, 21, 6, 1 },
264 { 1, 6, 20, 35, 36, 22, 7, 1 },
265 { 0, 5, 19, 34, 37, 24, 8, 1 },
266 { 0, 5, 18, 34, 37, 24, 9, 1 },
267 { 0, 4, 17, 33, 37, 26, 10, 1 },
268 { 0, 4, 16, 32, 38, 26, 10, 2 },
269 { 0, 3, 15, 31, 38, 28, 11, 2 },
270 { 0, 3, 14, 30, 38, 29, 12, 2 }
271 }
272};
273
274/* 4-tap Filter Coefficient */
275static const int v_coef_4t[GSC_COEF_RATIO][GSC_COEF_ATTR][GSC_COEF_V_4T] = {
276 { /* Ratio <= 65536 (~8:8) */
277 { 0, 128, 0, 0 },
278 { -4, 127, 5, 0 },
279 { -6, 124, 11, -1 },
280 { -8, 118, 19, -1 },
281 { -8, 111, 27, -2 },
282 { -8, 102, 37, -3 },
283 { -8, 92, 48, -4 },
284 { -7, 81, 59, -5 },
285 { -6, 70, 70, -6 },
286 { -5, 59, 81, -7 },
287 { -4, 48, 92, -8 },
288 { -3, 37, 102, -8 },
289 { -2, 27, 111, -8 },
290 { -1, 19, 118, -8 },
291 { -1, 11, 124, -6 },
292 { 0, 5, 127, -4 }
293 }, { /* 65536 < Ratio <= 74898 (~8:7) */
294 { 8, 112, 8, 0 },
295 { 4, 111, 14, -1 },
296 { 1, 109, 20, -2 },
297 { -2, 105, 27, -2 },
298 { -3, 100, 34, -3 },
299 { -5, 93, 43, -3 },
300 { -5, 86, 51, -4 },
301 { -5, 77, 60, -4 },
302 { -5, 69, 69, -5 },
303 { -4, 60, 77, -5 },
304 { -4, 51, 86, -5 },
305 { -3, 43, 93, -5 },
306 { -3, 34, 100, -3 },
307 { -2, 27, 105, -2 },
308 { -2, 20, 109, 1 },
309 { -1, 14, 111, 4 }
310 }, { /* 74898 < Ratio <= 87381 (~8:6) */
311 { 16, 96, 16, 0 },
312 { 12, 97, 21, -2 },
313 { 8, 96, 26, -2 },
314 { 5, 93, 32, -2 },
315 { 2, 89, 39, -2 },
316 { 0, 84, 46, -2 },
317 { -1, 79, 53, -3 },
318 { -2, 73, 59, -2 },
319 { -2, 66, 66, -2 },
320 { -2, 59, 73, -2 },
321 { -3, 53, 79, -1 },
322 { -2, 46, 84, 0 },
323 { -2, 39, 89, 2 },
324 { -2, 32, 93, 5 },
325 { -2, 26, 96, 8 },
326 { -2, 21, 97, 12 }
327 }, { /* 87381 < Ratio <= 104857 (~8:5) */
328 { 22, 84, 22, 0 },
329 { 18, 85, 26, -1 },
330 { 14, 84, 31, -1 },
331 { 11, 82, 36, -1 },
332 { 8, 79, 42, -1 },
333 { 6, 76, 47, -1 },
334 { 4, 72, 52, 0 },
335 { 2, 68, 58, 0 },
336 { 1, 63, 63, 1 },
337 { 0, 58, 68, 2 },
338 { 0, 52, 72, 4 },
339 { -1, 47, 76, 6 },
340 { -1, 42, 79, 8 },
341 { -1, 36, 82, 11 },
342 { -1, 31, 84, 14 },
343 { -1, 26, 85, 18 }
344 }, { /* 104857 < Ratio <= 131072 (~8:4) */
345 { 26, 76, 26, 0 },
346 { 22, 76, 30, 0 },
347 { 19, 75, 34, 0 },
348 { 16, 73, 38, 1 },
349 { 13, 71, 43, 1 },
350 { 10, 69, 47, 2 },
351 { 8, 66, 51, 3 },
352 { 6, 63, 55, 4 },
353 { 5, 59, 59, 5 },
354 { 4, 55, 63, 6 },
355 { 3, 51, 66, 8 },
356 { 2, 47, 69, 10 },
357 { 1, 43, 71, 13 },
358 { 1, 38, 73, 16 },
359 { 0, 34, 75, 19 },
360 { 0, 30, 76, 22 }
361 }, { /* 131072 < Ratio <= 174762 (~8:3) */
362 { 29, 70, 29, 0 },
363 { 26, 68, 32, 2 },
364 { 23, 67, 36, 2 },
365 { 20, 66, 39, 3 },
366 { 17, 65, 43, 3 },
367 { 15, 63, 46, 4 },
368 { 12, 61, 50, 5 },
369 { 10, 58, 53, 7 },
370 { 8, 56, 56, 8 },
371 { 7, 53, 58, 10 },
372 { 5, 50, 61, 12 },
373 { 4, 46, 63, 15 },
374 { 3, 43, 65, 17 },
375 { 3, 39, 66, 20 },
376 { 2, 36, 67, 23 },
377 { 2, 32, 68, 26 }
378 }, { /* 174762 < Ratio <= 262144 (~8:2) */
379 { 32, 64, 32, 0 },
380 { 28, 63, 34, 3 },
381 { 25, 62, 37, 4 },
382 { 22, 62, 40, 4 },
383 { 19, 61, 43, 5 },
384 { 17, 59, 46, 6 },
385 { 15, 58, 48, 7 },
386 { 13, 55, 51, 9 },
387 { 11, 53, 53, 11 },
388 { 9, 51, 55, 13 },
389 { 7, 48, 58, 15 },
390 { 6, 46, 59, 17 },
391 { 5, 43, 61, 19 },
392 { 4, 40, 62, 22 },
393 { 4, 37, 62, 25 },
394 { 3, 34, 63, 28 }
395 }
396};
397
398static int gsc_sw_reset(struct gsc_context *ctx)
399{
400 u32 cfg;
401 int count = GSC_RESET_TIMEOUT;
402
403 DRM_DEBUG_KMS("%s\n", __func__);
404
405 /* s/w reset */
406 cfg = (GSC_SW_RESET_SRESET);
407 gsc_write(cfg, GSC_SW_RESET);
408
409 /* wait s/w reset complete */
410 while (count--) {
411 cfg = gsc_read(GSC_SW_RESET);
412 if (!cfg)
413 break;
414 usleep_range(1000, 2000);
415 }
416
417 if (cfg) {
418 DRM_ERROR("failed to reset gsc h/w.\n");
419 return -EBUSY;
420 }
421
422 /* reset sequence */
423 cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
424 cfg |= (GSC_IN_BASE_ADDR_MASK |
425 GSC_IN_BASE_ADDR_PINGPONG(0));
426 gsc_write(cfg, GSC_IN_BASE_ADDR_Y_MASK);
427 gsc_write(cfg, GSC_IN_BASE_ADDR_CB_MASK);
428 gsc_write(cfg, GSC_IN_BASE_ADDR_CR_MASK);
429
430 cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK);
431 cfg |= (GSC_OUT_BASE_ADDR_MASK |
432 GSC_OUT_BASE_ADDR_PINGPONG(0));
433 gsc_write(cfg, GSC_OUT_BASE_ADDR_Y_MASK);
434 gsc_write(cfg, GSC_OUT_BASE_ADDR_CB_MASK);
435 gsc_write(cfg, GSC_OUT_BASE_ADDR_CR_MASK);
436
437 return 0;
438}
439
440static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable)
441{
442 u32 gscblk_cfg;
443
444 DRM_DEBUG_KMS("%s\n", __func__);
445
446 gscblk_cfg = readl(SYSREG_GSCBLK_CFG1);
447
448 if (enable)
449 gscblk_cfg |= GSC_BLK_DISP1WB_DEST(ctx->id) |
450 GSC_BLK_GSCL_WB_IN_SRC_SEL(ctx->id) |
451 GSC_BLK_SW_RESET_WB_DEST(ctx->id);
452 else
453 gscblk_cfg |= GSC_BLK_PXLASYNC_LO_MASK_WB(ctx->id);
454
455 writel(gscblk_cfg, SYSREG_GSCBLK_CFG1);
456}
457
458static void gsc_handle_irq(struct gsc_context *ctx, bool enable,
459 bool overflow, bool done)
460{
461 u32 cfg;
462
463 DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
464 enable, overflow, done);
465
466 cfg = gsc_read(GSC_IRQ);
467 cfg |= (GSC_IRQ_OR_MASK | GSC_IRQ_FRMDONE_MASK);
468
469 if (enable)
470 cfg |= GSC_IRQ_ENABLE;
471 else
472 cfg &= ~GSC_IRQ_ENABLE;
473
474 if (overflow)
475 cfg &= ~GSC_IRQ_OR_MASK;
476 else
477 cfg |= GSC_IRQ_OR_MASK;
478
479 if (done)
480 cfg &= ~GSC_IRQ_FRMDONE_MASK;
481 else
482 cfg |= GSC_IRQ_FRMDONE_MASK;
483
484 gsc_write(cfg, GSC_IRQ);
485}
486
487
488static int gsc_src_set_fmt(struct device *dev, u32 fmt)
489{
490 struct gsc_context *ctx = get_gsc_context(dev);
491 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
492 u32 cfg;
493
494 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
495
496 cfg = gsc_read(GSC_IN_CON);
497 cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
498 GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK |
499 GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE |
500 GSC_IN_CHROM_STRIDE_SEL_MASK | GSC_IN_RB_SWAP_MASK);
501
502 switch (fmt) {
503 case DRM_FORMAT_RGB565:
504 cfg |= GSC_IN_RGB565;
505 break;
506 case DRM_FORMAT_XRGB8888:
507 cfg |= GSC_IN_XRGB8888;
508 break;
509 case DRM_FORMAT_BGRX8888:
510 cfg |= (GSC_IN_XRGB8888 | GSC_IN_RB_SWAP);
511 break;
512 case DRM_FORMAT_YUYV:
513 cfg |= (GSC_IN_YUV422_1P |
514 GSC_IN_YUV422_1P_ORDER_LSB_Y |
515 GSC_IN_CHROMA_ORDER_CBCR);
516 break;
517 case DRM_FORMAT_YVYU:
518 cfg |= (GSC_IN_YUV422_1P |
519 GSC_IN_YUV422_1P_ORDER_LSB_Y |
520 GSC_IN_CHROMA_ORDER_CRCB);
521 break;
522 case DRM_FORMAT_UYVY:
523 cfg |= (GSC_IN_YUV422_1P |
524 GSC_IN_YUV422_1P_OEDER_LSB_C |
525 GSC_IN_CHROMA_ORDER_CBCR);
526 break;
527 case DRM_FORMAT_VYUY:
528 cfg |= (GSC_IN_YUV422_1P |
529 GSC_IN_YUV422_1P_OEDER_LSB_C |
530 GSC_IN_CHROMA_ORDER_CRCB);
531 break;
532 case DRM_FORMAT_NV21:
533 case DRM_FORMAT_NV61:
534 cfg |= (GSC_IN_CHROMA_ORDER_CRCB |
535 GSC_IN_YUV420_2P);
536 break;
537 case DRM_FORMAT_YUV422:
538 cfg |= GSC_IN_YUV422_3P;
539 break;
540 case DRM_FORMAT_YUV420:
541 case DRM_FORMAT_YVU420:
542 cfg |= GSC_IN_YUV420_3P;
543 break;
544 case DRM_FORMAT_NV12:
545 case DRM_FORMAT_NV16:
546 cfg |= (GSC_IN_CHROMA_ORDER_CBCR |
547 GSC_IN_YUV420_2P);
548 break;
549 case DRM_FORMAT_NV12MT:
550 cfg |= (GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE);
551 break;
552 default:
553 dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
554 return -EINVAL;
555 }
556
557 gsc_write(cfg, GSC_IN_CON);
558
559 return 0;
560}
561
562static int gsc_src_set_transf(struct device *dev,
563 enum drm_exynos_degree degree,
564 enum drm_exynos_flip flip, bool *swap)
565{
566 struct gsc_context *ctx = get_gsc_context(dev);
567 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
568 u32 cfg;
569
570 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
571 degree, flip);
572
573 cfg = gsc_read(GSC_IN_CON);
574 cfg &= ~GSC_IN_ROT_MASK;
575
576 switch (degree) {
577 case EXYNOS_DRM_DEGREE_0:
578 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
579 cfg |= GSC_IN_ROT_XFLIP;
580 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
581 cfg |= GSC_IN_ROT_YFLIP;
582 break;
583 case EXYNOS_DRM_DEGREE_90:
584 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
585 cfg |= GSC_IN_ROT_90_XFLIP;
586 else if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
587 cfg |= GSC_IN_ROT_90_YFLIP;
588 else
589 cfg |= GSC_IN_ROT_90;
590 break;
591 case EXYNOS_DRM_DEGREE_180:
592 cfg |= GSC_IN_ROT_180;
593 break;
594 case EXYNOS_DRM_DEGREE_270:
595 cfg |= GSC_IN_ROT_270;
596 break;
597 default:
598 dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
599 return -EINVAL;
600 }
601
602 gsc_write(cfg, GSC_IN_CON);
603
604 ctx->rotation = cfg &
605 (GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
606 *swap = ctx->rotation;
607
608 return 0;
609}
610
611static int gsc_src_set_size(struct device *dev, int swap,
612 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
613{
614 struct gsc_context *ctx = get_gsc_context(dev);
615 struct drm_exynos_pos img_pos = *pos;
616 struct gsc_scaler *sc = &ctx->sc;
617 u32 cfg;
618
619 DRM_DEBUG_KMS("%s:swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
620 __func__, swap, pos->x, pos->y, pos->w, pos->h);
621
622 if (swap) {
623 img_pos.w = pos->h;
624 img_pos.h = pos->w;
625 }
626
627 /* pixel offset */
628 cfg = (GSC_SRCIMG_OFFSET_X(img_pos.x) |
629 GSC_SRCIMG_OFFSET_Y(img_pos.y));
630 gsc_write(cfg, GSC_SRCIMG_OFFSET);
631
632 /* cropped size */
633 cfg = (GSC_CROPPED_WIDTH(img_pos.w) |
634 GSC_CROPPED_HEIGHT(img_pos.h));
635 gsc_write(cfg, GSC_CROPPED_SIZE);
636
637 DRM_DEBUG_KMS("%s:hsize[%d]vsize[%d]\n",
638 __func__, sz->hsize, sz->vsize);
639
640 /* original size */
641 cfg = gsc_read(GSC_SRCIMG_SIZE);
642 cfg &= ~(GSC_SRCIMG_HEIGHT_MASK |
643 GSC_SRCIMG_WIDTH_MASK);
644
645 cfg |= (GSC_SRCIMG_WIDTH(sz->hsize) |
646 GSC_SRCIMG_HEIGHT(sz->vsize));
647
648 gsc_write(cfg, GSC_SRCIMG_SIZE);
649
650 cfg = gsc_read(GSC_IN_CON);
651 cfg &= ~GSC_IN_RGB_TYPE_MASK;
652
653 DRM_DEBUG_KMS("%s:width[%d]range[%d]\n",
654 __func__, pos->w, sc->range);
655
656 if (pos->w >= GSC_WIDTH_ITU_709)
657 if (sc->range)
658 cfg |= GSC_IN_RGB_HD_WIDE;
659 else
660 cfg |= GSC_IN_RGB_HD_NARROW;
661 else
662 if (sc->range)
663 cfg |= GSC_IN_RGB_SD_WIDE;
664 else
665 cfg |= GSC_IN_RGB_SD_NARROW;
666
667 gsc_write(cfg, GSC_IN_CON);
668
669 return 0;
670}
671
672static int gsc_src_set_buf_seq(struct gsc_context *ctx, u32 buf_id,
673 enum drm_exynos_ipp_buf_type buf_type)
674{
675 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
676 bool masked;
677 u32 cfg;
678 u32 mask = 0x00000001 << buf_id;
679
680 DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
681 buf_id, buf_type);
682
683 /* mask register set */
684 cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
685
686 switch (buf_type) {
687 case IPP_BUF_ENQUEUE:
688 masked = false;
689 break;
690 case IPP_BUF_DEQUEUE:
691 masked = true;
692 break;
693 default:
694 dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
695 return -EINVAL;
696 }
697
698 /* sequence id */
699 cfg &= ~mask;
700 cfg |= masked << buf_id;
701 gsc_write(cfg, GSC_IN_BASE_ADDR_Y_MASK);
702 gsc_write(cfg, GSC_IN_BASE_ADDR_CB_MASK);
703 gsc_write(cfg, GSC_IN_BASE_ADDR_CR_MASK);
704
705 return 0;
706}
707
708static int gsc_src_set_addr(struct device *dev,
709 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
710 enum drm_exynos_ipp_buf_type buf_type)
711{
712 struct gsc_context *ctx = get_gsc_context(dev);
713 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
714 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
715 struct drm_exynos_ipp_property *property;
716
717 if (!c_node) {
718 DRM_ERROR("failed to get c_node.\n");
719 return -EFAULT;
720 }
721
722 property = &c_node->property;
723 if (!property) {
724 DRM_ERROR("failed to get property.\n");
725 return -EFAULT;
726 }
727
728 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
729 property->prop_id, buf_id, buf_type);
730
731 if (buf_id > GSC_MAX_SRC) {
732 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
733 return -EINVAL;
734 }
735
736 /* address register set */
737 switch (buf_type) {
738 case IPP_BUF_ENQUEUE:
739 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
740 GSC_IN_BASE_ADDR_Y(buf_id));
741 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
742 GSC_IN_BASE_ADDR_CB(buf_id));
743 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
744 GSC_IN_BASE_ADDR_CR(buf_id));
745 break;
746 case IPP_BUF_DEQUEUE:
747 gsc_write(0x0, GSC_IN_BASE_ADDR_Y(buf_id));
748 gsc_write(0x0, GSC_IN_BASE_ADDR_CB(buf_id));
749 gsc_write(0x0, GSC_IN_BASE_ADDR_CR(buf_id));
750 break;
751 default:
752 /* bypass */
753 break;
754 }
755
756 return gsc_src_set_buf_seq(ctx, buf_id, buf_type);
757}
758
759static struct exynos_drm_ipp_ops gsc_src_ops = {
760 .set_fmt = gsc_src_set_fmt,
761 .set_transf = gsc_src_set_transf,
762 .set_size = gsc_src_set_size,
763 .set_addr = gsc_src_set_addr,
764};
765
766static int gsc_dst_set_fmt(struct device *dev, u32 fmt)
767{
768 struct gsc_context *ctx = get_gsc_context(dev);
769 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
770 u32 cfg;
771
772 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
773
774 cfg = gsc_read(GSC_OUT_CON);
775 cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
776 GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK |
777 GSC_OUT_CHROM_STRIDE_SEL_MASK | GSC_OUT_RB_SWAP_MASK |
778 GSC_OUT_GLOBAL_ALPHA_MASK);
779
780 switch (fmt) {
781 case DRM_FORMAT_RGB565:
782 cfg |= GSC_OUT_RGB565;
783 break;
784 case DRM_FORMAT_XRGB8888:
785 cfg |= GSC_OUT_XRGB8888;
786 break;
787 case DRM_FORMAT_BGRX8888:
788 cfg |= (GSC_OUT_XRGB8888 | GSC_OUT_RB_SWAP);
789 break;
790 case DRM_FORMAT_YUYV:
791 cfg |= (GSC_OUT_YUV422_1P |
792 GSC_OUT_YUV422_1P_ORDER_LSB_Y |
793 GSC_OUT_CHROMA_ORDER_CBCR);
794 break;
795 case DRM_FORMAT_YVYU:
796 cfg |= (GSC_OUT_YUV422_1P |
797 GSC_OUT_YUV422_1P_ORDER_LSB_Y |
798 GSC_OUT_CHROMA_ORDER_CRCB);
799 break;
800 case DRM_FORMAT_UYVY:
801 cfg |= (GSC_OUT_YUV422_1P |
802 GSC_OUT_YUV422_1P_OEDER_LSB_C |
803 GSC_OUT_CHROMA_ORDER_CBCR);
804 break;
805 case DRM_FORMAT_VYUY:
806 cfg |= (GSC_OUT_YUV422_1P |
807 GSC_OUT_YUV422_1P_OEDER_LSB_C |
808 GSC_OUT_CHROMA_ORDER_CRCB);
809 break;
810 case DRM_FORMAT_NV21:
811 case DRM_FORMAT_NV61:
812 cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_2P);
813 break;
814 case DRM_FORMAT_YUV422:
815 case DRM_FORMAT_YUV420:
816 case DRM_FORMAT_YVU420:
817 cfg |= GSC_OUT_YUV420_3P;
818 break;
819 case DRM_FORMAT_NV12:
820 case DRM_FORMAT_NV16:
821 cfg |= (GSC_OUT_CHROMA_ORDER_CBCR |
822 GSC_OUT_YUV420_2P);
823 break;
824 case DRM_FORMAT_NV12MT:
825 cfg |= (GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE);
826 break;
827 default:
828 dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
829 return -EINVAL;
830 }
831
832 gsc_write(cfg, GSC_OUT_CON);
833
834 return 0;
835}
836
837static int gsc_dst_set_transf(struct device *dev,
838 enum drm_exynos_degree degree,
839 enum drm_exynos_flip flip, bool *swap)
840{
841 struct gsc_context *ctx = get_gsc_context(dev);
842 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
843 u32 cfg;
844
845 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
846 degree, flip);
847
848 cfg = gsc_read(GSC_IN_CON);
849 cfg &= ~GSC_IN_ROT_MASK;
850
851 switch (degree) {
852 case EXYNOS_DRM_DEGREE_0:
853 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
854 cfg |= GSC_IN_ROT_XFLIP;
855 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
856 cfg |= GSC_IN_ROT_YFLIP;
857 break;
858 case EXYNOS_DRM_DEGREE_90:
859 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
860 cfg |= GSC_IN_ROT_90_XFLIP;
861 else if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
862 cfg |= GSC_IN_ROT_90_YFLIP;
863 else
864 cfg |= GSC_IN_ROT_90;
865 break;
866 case EXYNOS_DRM_DEGREE_180:
867 cfg |= GSC_IN_ROT_180;
868 break;
869 case EXYNOS_DRM_DEGREE_270:
870 cfg |= GSC_IN_ROT_270;
871 break;
872 default:
873 dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
874 return -EINVAL;
875 }
876
877 gsc_write(cfg, GSC_IN_CON);
878
879 ctx->rotation = cfg &
880 (GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
881 *swap = ctx->rotation;
882
883 return 0;
884}
885
886static int gsc_get_ratio_shift(u32 src, u32 dst, u32 *ratio)
887{
888 DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
889
890 if (src >= dst * 8) {
891 DRM_ERROR("failed to make ratio and shift.\n");
892 return -EINVAL;
893 } else if (src >= dst * 4)
894 *ratio = 4;
895 else if (src >= dst * 2)
896 *ratio = 2;
897 else
898 *ratio = 1;
899
900 return 0;
901}
902
903static void gsc_get_prescaler_shfactor(u32 hratio, u32 vratio, u32 *shfactor)
904{
905 if (hratio == 4 && vratio == 4)
906 *shfactor = 4;
907 else if ((hratio == 4 && vratio == 2) ||
908 (hratio == 2 && vratio == 4))
909 *shfactor = 3;
910 else if ((hratio == 4 && vratio == 1) ||
911 (hratio == 1 && vratio == 4) ||
912 (hratio == 2 && vratio == 2))
913 *shfactor = 2;
914 else if (hratio == 1 && vratio == 1)
915 *shfactor = 0;
916 else
917 *shfactor = 1;
918}
919
920static int gsc_set_prescaler(struct gsc_context *ctx, struct gsc_scaler *sc,
921 struct drm_exynos_pos *src, struct drm_exynos_pos *dst)
922{
923 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
924 u32 cfg;
925 u32 src_w, src_h, dst_w, dst_h;
926 int ret = 0;
927
928 src_w = src->w;
929 src_h = src->h;
930
931 if (ctx->rotation) {
932 dst_w = dst->h;
933 dst_h = dst->w;
934 } else {
935 dst_w = dst->w;
936 dst_h = dst->h;
937 }
938
939 ret = gsc_get_ratio_shift(src_w, dst_w, &sc->pre_hratio);
940 if (ret) {
941 dev_err(ippdrv->dev, "failed to get ratio horizontal.\n");
942 return ret;
943 }
944
945 ret = gsc_get_ratio_shift(src_h, dst_h, &sc->pre_vratio);
946 if (ret) {
947 dev_err(ippdrv->dev, "failed to get ratio vertical.\n");
948 return ret;
949 }
950
951 DRM_DEBUG_KMS("%s:pre_hratio[%d]pre_vratio[%d]\n",
952 __func__, sc->pre_hratio, sc->pre_vratio);
953
954 sc->main_hratio = (src_w << 16) / dst_w;
955 sc->main_vratio = (src_h << 16) / dst_h;
956
957 DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n",
958 __func__, sc->main_hratio, sc->main_vratio);
959
960 gsc_get_prescaler_shfactor(sc->pre_hratio, sc->pre_vratio,
961 &sc->pre_shfactor);
962
963 DRM_DEBUG_KMS("%s:pre_shfactor[%d]\n", __func__,
964 sc->pre_shfactor);
965
966 cfg = (GSC_PRESC_SHFACTOR(sc->pre_shfactor) |
967 GSC_PRESC_H_RATIO(sc->pre_hratio) |
968 GSC_PRESC_V_RATIO(sc->pre_vratio));
969 gsc_write(cfg, GSC_PRE_SCALE_RATIO);
970
971 return ret;
972}
973
974static void gsc_set_h_coef(struct gsc_context *ctx, unsigned long main_hratio)
975{
976 int i, j, k, sc_ratio;
977
978 if (main_hratio <= GSC_SC_UP_MAX_RATIO)
979 sc_ratio = 0;
980 else if (main_hratio <= GSC_SC_DOWN_RATIO_7_8)
981 sc_ratio = 1;
982 else if (main_hratio <= GSC_SC_DOWN_RATIO_6_8)
983 sc_ratio = 2;
984 else if (main_hratio <= GSC_SC_DOWN_RATIO_5_8)
985 sc_ratio = 3;
986 else if (main_hratio <= GSC_SC_DOWN_RATIO_4_8)
987 sc_ratio = 4;
988 else if (main_hratio <= GSC_SC_DOWN_RATIO_3_8)
989 sc_ratio = 5;
990 else
991 sc_ratio = 6;
992
993 for (i = 0; i < GSC_COEF_PHASE; i++)
994 for (j = 0; j < GSC_COEF_H_8T; j++)
995 for (k = 0; k < GSC_COEF_DEPTH; k++)
996 gsc_write(h_coef_8t[sc_ratio][i][j],
997 GSC_HCOEF(i, j, k));
998}
999
1000static void gsc_set_v_coef(struct gsc_context *ctx, unsigned long main_vratio)
1001{
1002 int i, j, k, sc_ratio;
1003
1004 if (main_vratio <= GSC_SC_UP_MAX_RATIO)
1005 sc_ratio = 0;
1006 else if (main_vratio <= GSC_SC_DOWN_RATIO_7_8)
1007 sc_ratio = 1;
1008 else if (main_vratio <= GSC_SC_DOWN_RATIO_6_8)
1009 sc_ratio = 2;
1010 else if (main_vratio <= GSC_SC_DOWN_RATIO_5_8)
1011 sc_ratio = 3;
1012 else if (main_vratio <= GSC_SC_DOWN_RATIO_4_8)
1013 sc_ratio = 4;
1014 else if (main_vratio <= GSC_SC_DOWN_RATIO_3_8)
1015 sc_ratio = 5;
1016 else
1017 sc_ratio = 6;
1018
1019 for (i = 0; i < GSC_COEF_PHASE; i++)
1020 for (j = 0; j < GSC_COEF_V_4T; j++)
1021 for (k = 0; k < GSC_COEF_DEPTH; k++)
1022 gsc_write(v_coef_4t[sc_ratio][i][j],
1023 GSC_VCOEF(i, j, k));
1024}
1025
1026static void gsc_set_scaler(struct gsc_context *ctx, struct gsc_scaler *sc)
1027{
1028 u32 cfg;
1029
1030 DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n",
1031 __func__, sc->main_hratio, sc->main_vratio);
1032
1033 gsc_set_h_coef(ctx, sc->main_hratio);
1034 cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
1035 gsc_write(cfg, GSC_MAIN_H_RATIO);
1036
1037 gsc_set_v_coef(ctx, sc->main_vratio);
1038 cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio);
1039 gsc_write(cfg, GSC_MAIN_V_RATIO);
1040}
1041
1042static int gsc_dst_set_size(struct device *dev, int swap,
1043 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
1044{
1045 struct gsc_context *ctx = get_gsc_context(dev);
1046 struct drm_exynos_pos img_pos = *pos;
1047 struct gsc_scaler *sc = &ctx->sc;
1048 u32 cfg;
1049
1050 DRM_DEBUG_KMS("%s:swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
1051 __func__, swap, pos->x, pos->y, pos->w, pos->h);
1052
1053 if (swap) {
1054 img_pos.w = pos->h;
1055 img_pos.h = pos->w;
1056 }
1057
1058 /* pixel offset */
1059 cfg = (GSC_DSTIMG_OFFSET_X(pos->x) |
1060 GSC_DSTIMG_OFFSET_Y(pos->y));
1061 gsc_write(cfg, GSC_DSTIMG_OFFSET);
1062
1063 /* scaled size */
1064 cfg = (GSC_SCALED_WIDTH(img_pos.w) | GSC_SCALED_HEIGHT(img_pos.h));
1065 gsc_write(cfg, GSC_SCALED_SIZE);
1066
1067 DRM_DEBUG_KMS("%s:hsize[%d]vsize[%d]\n",
1068 __func__, sz->hsize, sz->vsize);
1069
1070 /* original size */
1071 cfg = gsc_read(GSC_DSTIMG_SIZE);
1072 cfg &= ~(GSC_DSTIMG_HEIGHT_MASK |
1073 GSC_DSTIMG_WIDTH_MASK);
1074 cfg |= (GSC_DSTIMG_WIDTH(sz->hsize) |
1075 GSC_DSTIMG_HEIGHT(sz->vsize));
1076 gsc_write(cfg, GSC_DSTIMG_SIZE);
1077
1078 cfg = gsc_read(GSC_OUT_CON);
1079 cfg &= ~GSC_OUT_RGB_TYPE_MASK;
1080
1081 DRM_DEBUG_KMS("%s:width[%d]range[%d]\n",
1082 __func__, pos->w, sc->range);
1083
1084 if (pos->w >= GSC_WIDTH_ITU_709)
1085 if (sc->range)
1086 cfg |= GSC_OUT_RGB_HD_WIDE;
1087 else
1088 cfg |= GSC_OUT_RGB_HD_NARROW;
1089 else
1090 if (sc->range)
1091 cfg |= GSC_OUT_RGB_SD_WIDE;
1092 else
1093 cfg |= GSC_OUT_RGB_SD_NARROW;
1094
1095 gsc_write(cfg, GSC_OUT_CON);
1096
1097 return 0;
1098}
1099
1100static int gsc_dst_get_buf_seq(struct gsc_context *ctx)
1101{
1102 u32 cfg, i, buf_num = GSC_REG_SZ;
1103 u32 mask = 0x00000001;
1104
1105 cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK);
1106
1107 for (i = 0; i < GSC_REG_SZ; i++)
1108 if (cfg & (mask << i))
1109 buf_num--;
1110
1111 DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
1112
1113 return buf_num;
1114}
1115
1116static int gsc_dst_set_buf_seq(struct gsc_context *ctx, u32 buf_id,
1117 enum drm_exynos_ipp_buf_type buf_type)
1118{
1119 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1120 bool masked;
1121 u32 cfg;
1122 u32 mask = 0x00000001 << buf_id;
1123 int ret = 0;
1124
1125 DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
1126 buf_id, buf_type);
1127
1128 mutex_lock(&ctx->lock);
1129
1130 /* mask register set */
1131 cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK);
1132
1133 switch (buf_type) {
1134 case IPP_BUF_ENQUEUE:
1135 masked = false;
1136 break;
1137 case IPP_BUF_DEQUEUE:
1138 masked = true;
1139 break;
1140 default:
1141 dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
1142 ret = -EINVAL;
1143 goto err_unlock;
1144 }
1145
1146 /* sequence id */
1147 cfg &= ~mask;
1148 cfg |= masked << buf_id;
1149 gsc_write(cfg, GSC_OUT_BASE_ADDR_Y_MASK);
1150 gsc_write(cfg, GSC_OUT_BASE_ADDR_CB_MASK);
1151 gsc_write(cfg, GSC_OUT_BASE_ADDR_CR_MASK);
1152
1153 /* interrupt enable */
1154 if (buf_type == IPP_BUF_ENQUEUE &&
1155 gsc_dst_get_buf_seq(ctx) >= GSC_BUF_START)
1156 gsc_handle_irq(ctx, true, false, true);
1157
1158 /* interrupt disable */
1159 if (buf_type == IPP_BUF_DEQUEUE &&
1160 gsc_dst_get_buf_seq(ctx) <= GSC_BUF_STOP)
1161 gsc_handle_irq(ctx, false, false, true);
1162
1163err_unlock:
1164 mutex_unlock(&ctx->lock);
1165 return ret;
1166}
1167
1168static int gsc_dst_set_addr(struct device *dev,
1169 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
1170 enum drm_exynos_ipp_buf_type buf_type)
1171{
1172 struct gsc_context *ctx = get_gsc_context(dev);
1173 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1174 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1175 struct drm_exynos_ipp_property *property;
1176
1177 if (!c_node) {
1178 DRM_ERROR("failed to get c_node.\n");
1179 return -EFAULT;
1180 }
1181
1182 property = &c_node->property;
1183 if (!property) {
1184 DRM_ERROR("failed to get property.\n");
1185 return -EFAULT;
1186 }
1187
1188 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
1189 property->prop_id, buf_id, buf_type);
1190
1191 if (buf_id > GSC_MAX_DST) {
1192 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
1193 return -EINVAL;
1194 }
1195
1196 /* address register set */
1197 switch (buf_type) {
1198 case IPP_BUF_ENQUEUE:
1199 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
1200 GSC_OUT_BASE_ADDR_Y(buf_id));
1201 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1202 GSC_OUT_BASE_ADDR_CB(buf_id));
1203 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1204 GSC_OUT_BASE_ADDR_CR(buf_id));
1205 break;
1206 case IPP_BUF_DEQUEUE:
1207 gsc_write(0x0, GSC_OUT_BASE_ADDR_Y(buf_id));
1208 gsc_write(0x0, GSC_OUT_BASE_ADDR_CB(buf_id));
1209 gsc_write(0x0, GSC_OUT_BASE_ADDR_CR(buf_id));
1210 break;
1211 default:
1212 /* bypass */
1213 break;
1214 }
1215
1216 return gsc_dst_set_buf_seq(ctx, buf_id, buf_type);
1217}
1218
1219static struct exynos_drm_ipp_ops gsc_dst_ops = {
1220 .set_fmt = gsc_dst_set_fmt,
1221 .set_transf = gsc_dst_set_transf,
1222 .set_size = gsc_dst_set_size,
1223 .set_addr = gsc_dst_set_addr,
1224};
1225
1226static int gsc_clk_ctrl(struct gsc_context *ctx, bool enable)
1227{
1228 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
1229
1230 if (enable) {
1231 clk_enable(ctx->gsc_clk);
1232 ctx->suspended = false;
1233 } else {
1234 clk_disable(ctx->gsc_clk);
1235 ctx->suspended = true;
1236 }
1237
1238 return 0;
1239}
1240
1241static int gsc_get_src_buf_index(struct gsc_context *ctx)
1242{
1243 u32 cfg, curr_index, i;
1244 u32 buf_id = GSC_MAX_SRC;
1245 int ret;
1246
1247 DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
1248
1249 cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
1250 curr_index = GSC_IN_CURR_GET_INDEX(cfg);
1251
1252 for (i = curr_index; i < GSC_MAX_SRC; i++) {
1253 if (!((cfg >> i) & 0x1)) {
1254 buf_id = i;
1255 break;
1256 }
1257 }
1258
1259 if (buf_id == GSC_MAX_SRC) {
1260 DRM_ERROR("failed to get in buffer index.\n");
1261 return -EINVAL;
1262 }
1263
1264 ret = gsc_src_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE);
1265 if (ret < 0) {
1266 DRM_ERROR("failed to dequeue.\n");
1267 return ret;
1268 }
1269
1270 DRM_DEBUG_KMS("%s:cfg[0x%x]curr_index[%d]buf_id[%d]\n", __func__, cfg,
1271 curr_index, buf_id);
1272
1273 return buf_id;
1274}
1275
1276static int gsc_get_dst_buf_index(struct gsc_context *ctx)
1277{
1278 u32 cfg, curr_index, i;
1279 u32 buf_id = GSC_MAX_DST;
1280 int ret;
1281
1282 DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
1283
1284 cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK);
1285 curr_index = GSC_OUT_CURR_GET_INDEX(cfg);
1286
1287 for (i = curr_index; i < GSC_MAX_DST; i++) {
1288 if (!((cfg >> i) & 0x1)) {
1289 buf_id = i;
1290 break;
1291 }
1292 }
1293
1294 if (buf_id == GSC_MAX_DST) {
1295 DRM_ERROR("failed to get out buffer index.\n");
1296 return -EINVAL;
1297 }
1298
1299 ret = gsc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE);
1300 if (ret < 0) {
1301 DRM_ERROR("failed to dequeue.\n");
1302 return ret;
1303 }
1304
1305 DRM_DEBUG_KMS("%s:cfg[0x%x]curr_index[%d]buf_id[%d]\n", __func__, cfg,
1306 curr_index, buf_id);
1307
1308 return buf_id;
1309}
1310
1311static irqreturn_t gsc_irq_handler(int irq, void *dev_id)
1312{
1313 struct gsc_context *ctx = dev_id;
1314 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1315 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1316 struct drm_exynos_ipp_event_work *event_work =
1317 c_node->event_work;
1318 u32 status;
1319 int buf_id[EXYNOS_DRM_OPS_MAX];
1320
1321 DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
1322
1323 status = gsc_read(GSC_IRQ);
1324 if (status & GSC_IRQ_STATUS_OR_IRQ) {
1325 dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n",
1326 ctx->id, status);
1327 return IRQ_NONE;
1328 }
1329
1330 if (status & GSC_IRQ_STATUS_OR_FRM_DONE) {
1331 dev_dbg(ippdrv->dev, "occured frame done at %d, status 0x%x.\n",
1332 ctx->id, status);
1333
1334 buf_id[EXYNOS_DRM_OPS_SRC] = gsc_get_src_buf_index(ctx);
1335 if (buf_id[EXYNOS_DRM_OPS_SRC] < 0)
1336 return IRQ_HANDLED;
1337
1338 buf_id[EXYNOS_DRM_OPS_DST] = gsc_get_dst_buf_index(ctx);
1339 if (buf_id[EXYNOS_DRM_OPS_DST] < 0)
1340 return IRQ_HANDLED;
1341
1342 DRM_DEBUG_KMS("%s:buf_id_src[%d]buf_id_dst[%d]\n", __func__,
1343 buf_id[EXYNOS_DRM_OPS_SRC], buf_id[EXYNOS_DRM_OPS_DST]);
1344
1345 event_work->ippdrv = ippdrv;
1346 event_work->buf_id[EXYNOS_DRM_OPS_SRC] =
1347 buf_id[EXYNOS_DRM_OPS_SRC];
1348 event_work->buf_id[EXYNOS_DRM_OPS_DST] =
1349 buf_id[EXYNOS_DRM_OPS_DST];
1350 queue_work(ippdrv->event_workq,
1351 (struct work_struct *)event_work);
1352 }
1353
1354 return IRQ_HANDLED;
1355}
1356
1357static int gsc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
1358{
1359 struct drm_exynos_ipp_prop_list *prop_list;
1360
1361 DRM_DEBUG_KMS("%s\n", __func__);
1362
1363 prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
1364 if (!prop_list) {
1365 DRM_ERROR("failed to alloc property list.\n");
1366 return -ENOMEM;
1367 }
1368
1369 prop_list->version = 1;
1370 prop_list->writeback = 1;
1371 prop_list->refresh_min = GSC_REFRESH_MIN;
1372 prop_list->refresh_max = GSC_REFRESH_MAX;
1373 prop_list->flip = (1 << EXYNOS_DRM_FLIP_VERTICAL) |
1374 (1 << EXYNOS_DRM_FLIP_HORIZONTAL);
1375 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
1376 (1 << EXYNOS_DRM_DEGREE_90) |
1377 (1 << EXYNOS_DRM_DEGREE_180) |
1378 (1 << EXYNOS_DRM_DEGREE_270);
1379 prop_list->csc = 1;
1380 prop_list->crop = 1;
1381 prop_list->crop_max.hsize = GSC_CROP_MAX;
1382 prop_list->crop_max.vsize = GSC_CROP_MAX;
1383 prop_list->crop_min.hsize = GSC_CROP_MIN;
1384 prop_list->crop_min.vsize = GSC_CROP_MIN;
1385 prop_list->scale = 1;
1386 prop_list->scale_max.hsize = GSC_SCALE_MAX;
1387 prop_list->scale_max.vsize = GSC_SCALE_MAX;
1388 prop_list->scale_min.hsize = GSC_SCALE_MIN;
1389 prop_list->scale_min.vsize = GSC_SCALE_MIN;
1390
1391 ippdrv->prop_list = prop_list;
1392
1393 return 0;
1394}
1395
1396static inline bool gsc_check_drm_flip(enum drm_exynos_flip flip)
1397{
1398 switch (flip) {
1399 case EXYNOS_DRM_FLIP_NONE:
1400 case EXYNOS_DRM_FLIP_VERTICAL:
1401 case EXYNOS_DRM_FLIP_HORIZONTAL:
1402 case EXYNOS_DRM_FLIP_VERTICAL | EXYNOS_DRM_FLIP_HORIZONTAL:
1403 return true;
1404 default:
1405 DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
1406 return false;
1407 }
1408}
1409
1410static int gsc_ippdrv_check_property(struct device *dev,
1411 struct drm_exynos_ipp_property *property)
1412{
1413 struct gsc_context *ctx = get_gsc_context(dev);
1414 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1415 struct drm_exynos_ipp_prop_list *pp = ippdrv->prop_list;
1416 struct drm_exynos_ipp_config *config;
1417 struct drm_exynos_pos *pos;
1418 struct drm_exynos_sz *sz;
1419 bool swap;
1420 int i;
1421
1422 DRM_DEBUG_KMS("%s\n", __func__);
1423
1424 for_each_ipp_ops(i) {
1425 if ((i == EXYNOS_DRM_OPS_SRC) &&
1426 (property->cmd == IPP_CMD_WB))
1427 continue;
1428
1429 config = &property->config[i];
1430 pos = &config->pos;
1431 sz = &config->sz;
1432
1433 /* check for flip */
1434 if (!gsc_check_drm_flip(config->flip)) {
1435 DRM_ERROR("invalid flip.\n");
1436 goto err_property;
1437 }
1438
1439 /* check for degree */
1440 switch (config->degree) {
1441 case EXYNOS_DRM_DEGREE_90:
1442 case EXYNOS_DRM_DEGREE_270:
1443 swap = true;
1444 break;
1445 case EXYNOS_DRM_DEGREE_0:
1446 case EXYNOS_DRM_DEGREE_180:
1447 swap = false;
1448 break;
1449 default:
1450 DRM_ERROR("invalid degree.\n");
1451 goto err_property;
1452 }
1453
1454 /* check for buffer bound */
1455 if ((pos->x + pos->w > sz->hsize) ||
1456 (pos->y + pos->h > sz->vsize)) {
1457 DRM_ERROR("out of buf bound.\n");
1458 goto err_property;
1459 }
1460
1461 /* check for crop */
1462 if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) {
1463 if (swap) {
1464 if ((pos->h < pp->crop_min.hsize) ||
1465 (sz->vsize > pp->crop_max.hsize) ||
1466 (pos->w < pp->crop_min.vsize) ||
1467 (sz->hsize > pp->crop_max.vsize)) {
1468 DRM_ERROR("out of crop size.\n");
1469 goto err_property;
1470 }
1471 } else {
1472 if ((pos->w < pp->crop_min.hsize) ||
1473 (sz->hsize > pp->crop_max.hsize) ||
1474 (pos->h < pp->crop_min.vsize) ||
1475 (sz->vsize > pp->crop_max.vsize)) {
1476 DRM_ERROR("out of crop size.\n");
1477 goto err_property;
1478 }
1479 }
1480 }
1481
1482 /* check for scale */
1483 if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) {
1484 if (swap) {
1485 if ((pos->h < pp->scale_min.hsize) ||
1486 (sz->vsize > pp->scale_max.hsize) ||
1487 (pos->w < pp->scale_min.vsize) ||
1488 (sz->hsize > pp->scale_max.vsize)) {
1489 DRM_ERROR("out of scale size.\n");
1490 goto err_property;
1491 }
1492 } else {
1493 if ((pos->w < pp->scale_min.hsize) ||
1494 (sz->hsize > pp->scale_max.hsize) ||
1495 (pos->h < pp->scale_min.vsize) ||
1496 (sz->vsize > pp->scale_max.vsize)) {
1497 DRM_ERROR("out of scale size.\n");
1498 goto err_property;
1499 }
1500 }
1501 }
1502 }
1503
1504 return 0;
1505
1506err_property:
1507 for_each_ipp_ops(i) {
1508 if ((i == EXYNOS_DRM_OPS_SRC) &&
1509 (property->cmd == IPP_CMD_WB))
1510 continue;
1511
1512 config = &property->config[i];
1513 pos = &config->pos;
1514 sz = &config->sz;
1515
1516 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1517 i ? "dst" : "src", config->flip, config->degree,
1518 pos->x, pos->y, pos->w, pos->h,
1519 sz->hsize, sz->vsize);
1520 }
1521
1522 return -EINVAL;
1523}
1524
1525
1526static int gsc_ippdrv_reset(struct device *dev)
1527{
1528 struct gsc_context *ctx = get_gsc_context(dev);
1529 struct gsc_scaler *sc = &ctx->sc;
1530 int ret;
1531
1532 DRM_DEBUG_KMS("%s\n", __func__);
1533
1534 /* reset h/w block */
1535 ret = gsc_sw_reset(ctx);
1536 if (ret < 0) {
1537 dev_err(dev, "failed to reset hardware.\n");
1538 return ret;
1539 }
1540
1541 /* scaler setting */
1542 memset(&ctx->sc, 0x0, sizeof(ctx->sc));
1543 sc->range = true;
1544
1545 return 0;
1546}
1547
1548static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1549{
1550 struct gsc_context *ctx = get_gsc_context(dev);
1551 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1552 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1553 struct drm_exynos_ipp_property *property;
1554 struct drm_exynos_ipp_config *config;
1555 struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX];
1556 struct drm_exynos_ipp_set_wb set_wb;
1557 u32 cfg;
1558 int ret, i;
1559
1560 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1561
1562 if (!c_node) {
1563 DRM_ERROR("failed to get c_node.\n");
1564 return -EINVAL;
1565 }
1566
1567 property = &c_node->property;
1568 if (!property) {
1569 DRM_ERROR("failed to get property.\n");
1570 return -EINVAL;
1571 }
1572
1573 gsc_handle_irq(ctx, true, false, true);
1574
1575 for_each_ipp_ops(i) {
1576 config = &property->config[i];
1577 img_pos[i] = config->pos;
1578 }
1579
1580 switch (cmd) {
1581 case IPP_CMD_M2M:
1582 /* enable one shot */
1583 cfg = gsc_read(GSC_ENABLE);
1584 cfg &= ~(GSC_ENABLE_ON_CLEAR_MASK |
1585 GSC_ENABLE_CLK_GATE_MODE_MASK);
1586 cfg |= GSC_ENABLE_ON_CLEAR_ONESHOT;
1587 gsc_write(cfg, GSC_ENABLE);
1588
1589 /* src dma memory */
1590 cfg = gsc_read(GSC_IN_CON);
1591 cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
1592 cfg |= GSC_IN_PATH_MEMORY;
1593 gsc_write(cfg, GSC_IN_CON);
1594
1595 /* dst dma memory */
1596 cfg = gsc_read(GSC_OUT_CON);
1597 cfg |= GSC_OUT_PATH_MEMORY;
1598 gsc_write(cfg, GSC_OUT_CON);
1599 break;
1600 case IPP_CMD_WB:
1601 set_wb.enable = 1;
1602 set_wb.refresh = property->refresh_rate;
1603 gsc_set_gscblk_fimd_wb(ctx, set_wb.enable);
1604 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1605
1606 /* src local path */
1607 cfg = readl(GSC_IN_CON);
1608 cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
1609 cfg |= (GSC_IN_PATH_LOCAL | GSC_IN_LOCAL_FIMD_WB);
1610 gsc_write(cfg, GSC_IN_CON);
1611
1612 /* dst dma memory */
1613 cfg = gsc_read(GSC_OUT_CON);
1614 cfg |= GSC_OUT_PATH_MEMORY;
1615 gsc_write(cfg, GSC_OUT_CON);
1616 break;
1617 case IPP_CMD_OUTPUT:
1618 /* src dma memory */
1619 cfg = gsc_read(GSC_IN_CON);
1620 cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
1621 cfg |= GSC_IN_PATH_MEMORY;
1622 gsc_write(cfg, GSC_IN_CON);
1623
1624 /* dst local path */
1625 cfg = gsc_read(GSC_OUT_CON);
1626 cfg |= GSC_OUT_PATH_MEMORY;
1627 gsc_write(cfg, GSC_OUT_CON);
1628 break;
1629 default:
1630 ret = -EINVAL;
1631 dev_err(dev, "invalid operations.\n");
1632 return ret;
1633 }
1634
1635 ret = gsc_set_prescaler(ctx, &ctx->sc,
1636 &img_pos[EXYNOS_DRM_OPS_SRC],
1637 &img_pos[EXYNOS_DRM_OPS_DST]);
1638 if (ret) {
1639 dev_err(dev, "failed to set precalser.\n");
1640 return ret;
1641 }
1642
1643 gsc_set_scaler(ctx, &ctx->sc);
1644
1645 cfg = gsc_read(GSC_ENABLE);
1646 cfg |= GSC_ENABLE_ON;
1647 gsc_write(cfg, GSC_ENABLE);
1648
1649 return 0;
1650}
1651
1652static void gsc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1653{
1654 struct gsc_context *ctx = get_gsc_context(dev);
1655 struct drm_exynos_ipp_set_wb set_wb = {0, 0};
1656 u32 cfg;
1657
1658 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1659
1660 switch (cmd) {
1661 case IPP_CMD_M2M:
1662 /* bypass */
1663 break;
1664 case IPP_CMD_WB:
1665 gsc_set_gscblk_fimd_wb(ctx, set_wb.enable);
1666 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1667 break;
1668 case IPP_CMD_OUTPUT:
1669 default:
1670 dev_err(dev, "invalid operations.\n");
1671 break;
1672 }
1673
1674 gsc_handle_irq(ctx, false, false, true);
1675
1676 /* reset sequence */
1677 gsc_write(0xff, GSC_OUT_BASE_ADDR_Y_MASK);
1678 gsc_write(0xff, GSC_OUT_BASE_ADDR_CB_MASK);
1679 gsc_write(0xff, GSC_OUT_BASE_ADDR_CR_MASK);
1680
1681 cfg = gsc_read(GSC_ENABLE);
1682 cfg &= ~GSC_ENABLE_ON;
1683 gsc_write(cfg, GSC_ENABLE);
1684}
1685
1686static int __devinit gsc_probe(struct platform_device *pdev)
1687{
1688 struct device *dev = &pdev->dev;
1689 struct gsc_context *ctx;
1690 struct resource *res;
1691 struct exynos_drm_ippdrv *ippdrv;
1692 int ret;
1693
1694 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1695 if (!ctx)
1696 return -ENOMEM;
1697
1698 /* clock control */
1699 ctx->gsc_clk = clk_get(dev, "gscl");
1700 if (IS_ERR(ctx->gsc_clk)) {
1701 dev_err(dev, "failed to get gsc clock.\n");
1702 ret = PTR_ERR(ctx->gsc_clk);
1703 goto err_ctx;
1704 }
1705
1706 /* resource memory */
1707 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1708 if (!ctx->regs_res) {
1709 dev_err(dev, "failed to find registers.\n");
1710 ret = -ENOENT;
1711 goto err_clk;
1712 }
1713
1714 ctx->regs = devm_request_and_ioremap(dev, ctx->regs_res);
1715 if (!ctx->regs) {
1716 dev_err(dev, "failed to map registers.\n");
1717 ret = -ENXIO;
1718 goto err_clk;
1719 }
1720
1721 /* resource irq */
1722 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1723 if (!res) {
1724 dev_err(dev, "failed to request irq resource.\n");
1725 ret = -ENOENT;
1726 goto err_get_regs;
1727 }
1728
1729 ctx->irq = res->start;
1730 ret = request_threaded_irq(ctx->irq, NULL, gsc_irq_handler,
1731 IRQF_ONESHOT, "drm_gsc", ctx);
1732 if (ret < 0) {
1733 dev_err(dev, "failed to request irq.\n");
1734 goto err_get_regs;
1735 }
1736
1737 /* context initailization */
1738 ctx->id = pdev->id;
1739
1740 ippdrv = &ctx->ippdrv;
1741 ippdrv->dev = dev;
1742 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &gsc_src_ops;
1743 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &gsc_dst_ops;
1744 ippdrv->check_property = gsc_ippdrv_check_property;
1745 ippdrv->reset = gsc_ippdrv_reset;
1746 ippdrv->start = gsc_ippdrv_start;
1747 ippdrv->stop = gsc_ippdrv_stop;
1748 ret = gsc_init_prop_list(ippdrv);
1749 if (ret < 0) {
1750 dev_err(dev, "failed to init property list.\n");
1751 goto err_get_irq;
1752 }
1753
1754 DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
1755 (int)ippdrv);
1756
1757 mutex_init(&ctx->lock);
1758 platform_set_drvdata(pdev, ctx);
1759
1760 pm_runtime_set_active(dev);
1761 pm_runtime_enable(dev);
1762
1763 ret = exynos_drm_ippdrv_register(ippdrv);
1764 if (ret < 0) {
1765 dev_err(dev, "failed to register drm gsc device.\n");
1766 goto err_ippdrv_register;
1767 }
1768
1769 dev_info(&pdev->dev, "drm gsc registered successfully.\n");
1770
1771 return 0;
1772
1773err_ippdrv_register:
1774 devm_kfree(dev, ippdrv->prop_list);
1775 pm_runtime_disable(dev);
1776err_get_irq:
1777 free_irq(ctx->irq, ctx);
1778err_get_regs:
1779 devm_iounmap(dev, ctx->regs);
1780err_clk:
1781 clk_put(ctx->gsc_clk);
1782err_ctx:
1783 devm_kfree(dev, ctx);
1784 return ret;
1785}
1786
1787static int __devexit gsc_remove(struct platform_device *pdev)
1788{
1789 struct device *dev = &pdev->dev;
1790 struct gsc_context *ctx = get_gsc_context(dev);
1791 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1792
1793 devm_kfree(dev, ippdrv->prop_list);
1794 exynos_drm_ippdrv_unregister(ippdrv);
1795 mutex_destroy(&ctx->lock);
1796
1797 pm_runtime_set_suspended(dev);
1798 pm_runtime_disable(dev);
1799
1800 free_irq(ctx->irq, ctx);
1801 devm_iounmap(dev, ctx->regs);
1802
1803 clk_put(ctx->gsc_clk);
1804
1805 devm_kfree(dev, ctx);
1806
1807 return 0;
1808}
1809
1810#ifdef CONFIG_PM_SLEEP
1811static int gsc_suspend(struct device *dev)
1812{
1813 struct gsc_context *ctx = get_gsc_context(dev);
1814
1815 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1816
1817 if (pm_runtime_suspended(dev))
1818 return 0;
1819
1820 return gsc_clk_ctrl(ctx, false);
1821}
1822
1823static int gsc_resume(struct device *dev)
1824{
1825 struct gsc_context *ctx = get_gsc_context(dev);
1826
1827 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1828
1829 if (!pm_runtime_suspended(dev))
1830 return gsc_clk_ctrl(ctx, true);
1831
1832 return 0;
1833}
1834#endif
1835
1836#ifdef CONFIG_PM_RUNTIME
1837static int gsc_runtime_suspend(struct device *dev)
1838{
1839 struct gsc_context *ctx = get_gsc_context(dev);
1840
1841 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1842
1843 return gsc_clk_ctrl(ctx, false);
1844}
1845
1846static int gsc_runtime_resume(struct device *dev)
1847{
1848 struct gsc_context *ctx = get_gsc_context(dev);
1849
1850 DRM_DEBUG_KMS("%s:id[%d]\n", __FILE__, ctx->id);
1851
1852 return gsc_clk_ctrl(ctx, true);
1853}
1854#endif
1855
1856static const struct dev_pm_ops gsc_pm_ops = {
1857 SET_SYSTEM_SLEEP_PM_OPS(gsc_suspend, gsc_resume)
1858 SET_RUNTIME_PM_OPS(gsc_runtime_suspend, gsc_runtime_resume, NULL)
1859};
1860
1861struct platform_driver gsc_driver = {
1862 .probe = gsc_probe,
1863 .remove = __devexit_p(gsc_remove),
1864 .driver = {
1865 .name = "exynos-drm-gsc",
1866 .owner = THIS_MODULE,
1867 .pm = &gsc_pm_ops,
1868 },
1869};
1870
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.h b/drivers/gpu/drm/exynos/exynos_drm_gsc.h
new file mode 100644
index 000000000000..b3c3bc618c0f
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.h
@@ -0,0 +1,38 @@
1/*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 *
4 * Authors:
5 * Eunchul Kim <chulspro.kim@samsung.com>
6 * Jinyoung Jeon <jy0.jeon@samsung.com>
7 * Sangmin Lee <lsmin.lee@samsung.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29#ifndef _EXYNOS_DRM_GSC_H_
30#define _EXYNOS_DRM_GSC_H_
31
32/*
33 * TODO
34 * FIMD output interface notifier callback.
35 * Mixer output interface notifier callback.
36 */
37
38#endif /* _EXYNOS_DRM_GSC_H_ */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 2d11e70b601a..55793c46e3c2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -29,6 +29,9 @@
29#define get_ctx_from_subdrv(subdrv) container_of(subdrv,\ 29#define get_ctx_from_subdrv(subdrv) container_of(subdrv,\
30 struct drm_hdmi_context, subdrv); 30 struct drm_hdmi_context, subdrv);
31 31
32/* platform device pointer for common drm hdmi device. */
33static struct platform_device *exynos_drm_hdmi_pdev;
34
32/* Common hdmi subdrv needs to access the hdmi and mixer though context. 35/* Common hdmi subdrv needs to access the hdmi and mixer though context.
33* These should be initialied by the repective drivers */ 36* These should be initialied by the repective drivers */
34static struct exynos_drm_hdmi_context *hdmi_ctx; 37static struct exynos_drm_hdmi_context *hdmi_ctx;
@@ -46,6 +49,25 @@ struct drm_hdmi_context {
46 bool enabled[MIXER_WIN_NR]; 49 bool enabled[MIXER_WIN_NR];
47}; 50};
48 51
52int exynos_platform_device_hdmi_register(void)
53{
54 if (exynos_drm_hdmi_pdev)
55 return -EEXIST;
56
57 exynos_drm_hdmi_pdev = platform_device_register_simple(
58 "exynos-drm-hdmi", -1, NULL, 0);
59 if (IS_ERR_OR_NULL(exynos_drm_hdmi_pdev))
60 return PTR_ERR(exynos_drm_hdmi_pdev);
61
62 return 0;
63}
64
65void exynos_platform_device_hdmi_unregister(void)
66{
67 if (exynos_drm_hdmi_pdev)
68 platform_device_unregister(exynos_drm_hdmi_pdev);
69}
70
49void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx) 71void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx)
50{ 72{
51 if (ctx) 73 if (ctx)
@@ -157,6 +179,16 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
157 return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx); 179 return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
158} 180}
159 181
182static void drm_hdmi_wait_for_vblank(struct device *subdrv_dev)
183{
184 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
185
186 DRM_DEBUG_KMS("%s\n", __FILE__);
187
188 if (mixer_ops && mixer_ops->wait_for_vblank)
189 mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
190}
191
160static void drm_hdmi_mode_fixup(struct device *subdrv_dev, 192static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
161 struct drm_connector *connector, 193 struct drm_connector *connector,
162 const struct drm_display_mode *mode, 194 const struct drm_display_mode *mode,
@@ -238,6 +270,7 @@ static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
238 .apply = drm_hdmi_apply, 270 .apply = drm_hdmi_apply,
239 .enable_vblank = drm_hdmi_enable_vblank, 271 .enable_vblank = drm_hdmi_enable_vblank,
240 .disable_vblank = drm_hdmi_disable_vblank, 272 .disable_vblank = drm_hdmi_disable_vblank,
273 .wait_for_vblank = drm_hdmi_wait_for_vblank,
241 .mode_fixup = drm_hdmi_mode_fixup, 274 .mode_fixup = drm_hdmi_mode_fixup,
242 .mode_set = drm_hdmi_mode_set, 275 .mode_set = drm_hdmi_mode_set,
243 .get_max_resol = drm_hdmi_get_max_resol, 276 .get_max_resol = drm_hdmi_get_max_resol,
@@ -291,21 +324,10 @@ static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
291 ctx->enabled[win] = false; 324 ctx->enabled[win] = false;
292} 325}
293 326
294static void drm_mixer_wait_for_vblank(struct device *subdrv_dev)
295{
296 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
297
298 DRM_DEBUG_KMS("%s\n", __FILE__);
299
300 if (mixer_ops && mixer_ops->wait_for_vblank)
301 mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
302}
303
304static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = { 327static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
305 .mode_set = drm_mixer_mode_set, 328 .mode_set = drm_mixer_mode_set,
306 .commit = drm_mixer_commit, 329 .commit = drm_mixer_commit,
307 .disable = drm_mixer_disable, 330 .disable = drm_mixer_disable,
308 .wait_for_vblank = drm_mixer_wait_for_vblank,
309}; 331};
310 332
311static struct exynos_drm_manager hdmi_manager = { 333static struct exynos_drm_manager hdmi_manager = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index 54b522353e48..fcc3093ec8fe 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -65,10 +65,10 @@ struct exynos_mixer_ops {
65 int (*iommu_on)(void *ctx, bool enable); 65 int (*iommu_on)(void *ctx, bool enable);
66 int (*enable_vblank)(void *ctx, int pipe); 66 int (*enable_vblank)(void *ctx, int pipe);
67 void (*disable_vblank)(void *ctx); 67 void (*disable_vblank)(void *ctx);
68 void (*wait_for_vblank)(void *ctx);
68 void (*dpms)(void *ctx, int mode); 69 void (*dpms)(void *ctx, int mode);
69 70
70 /* overlay */ 71 /* overlay */
71 void (*wait_for_vblank)(void *ctx);
72 void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay); 72 void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
73 void (*win_commit)(void *ctx, int zpos); 73 void (*win_commit)(void *ctx, int zpos);
74 void (*win_disable)(void *ctx, int zpos); 74 void (*win_disable)(void *ctx, int zpos);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
index 09db1983eb1a..2482b7f96341 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
@@ -56,8 +56,8 @@ int drm_create_iommu_mapping(struct drm_device *drm_dev)
56 mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start, 56 mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start,
57 priv->da_space_size, 57 priv->da_space_size,
58 priv->da_space_order); 58 priv->da_space_order);
59 if (!mapping) 59 if (IS_ERR(mapping))
60 return -ENOMEM; 60 return PTR_ERR(mapping);
61 61
62 dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), 62 dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
63 GFP_KERNEL); 63 GFP_KERNEL);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
new file mode 100644
index 000000000000..49eebe948ed2
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -0,0 +1,2060 @@
1/*
2 * Copyright (C) 2012 Samsung Electronics Co.Ltd
3 * Authors:
4 * Eunchul Kim <chulspro.kim@samsung.com>
5 * Jinyoung Jeon <jy0.jeon@samsung.com>
6 * Sangmin Lee <lsmin.lee@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/types.h>
18#include <linux/clk.h>
19#include <linux/pm_runtime.h>
20#include <plat/map-base.h>
21
22#include <drm/drmP.h>
23#include <drm/exynos_drm.h>
24#include "exynos_drm_drv.h"
25#include "exynos_drm_gem.h"
26#include "exynos_drm_ipp.h"
27#include "exynos_drm_iommu.h"
28
29/*
30 * IPP is stand for Image Post Processing and
31 * supports image scaler/rotator and input/output DMA operations.
32 * using FIMC, GSC, Rotator, so on.
33 * IPP is integration device driver of same attribute h/w
34 */
35
36/*
37 * TODO
38 * 1. expand command control id.
39 * 2. integrate property and config.
40 * 3. removed send_event id check routine.
41 * 4. compare send_event id if needed.
42 * 5. free subdrv_remove notifier callback list if needed.
43 * 6. need to check subdrv_open about multi-open.
44 * 7. need to power_on implement power and sysmmu ctrl.
45 */
46
47#define get_ipp_context(dev) platform_get_drvdata(to_platform_device(dev))
48#define ipp_is_m2m_cmd(c) (c == IPP_CMD_M2M)
49
50/*
51 * A structure of event.
52 *
53 * @base: base of event.
54 * @event: ipp event.
55 */
56struct drm_exynos_ipp_send_event {
57 struct drm_pending_event base;
58 struct drm_exynos_ipp_event event;
59};
60
61/*
62 * A structure of memory node.
63 *
64 * @list: list head to memory queue information.
65 * @ops_id: id of operations.
66 * @prop_id: id of property.
67 * @buf_id: id of buffer.
68 * @buf_info: gem objects and dma address, size.
69 * @filp: a pointer to drm_file.
70 */
71struct drm_exynos_ipp_mem_node {
72 struct list_head list;
73 enum drm_exynos_ops_id ops_id;
74 u32 prop_id;
75 u32 buf_id;
76 struct drm_exynos_ipp_buf_info buf_info;
77 struct drm_file *filp;
78};
79
80/*
81 * A structure of ipp context.
82 *
83 * @subdrv: prepare initialization using subdrv.
84 * @ipp_lock: lock for synchronization of access to ipp_idr.
85 * @prop_lock: lock for synchronization of access to prop_idr.
86 * @ipp_idr: ipp driver idr.
87 * @prop_idr: property idr.
88 * @event_workq: event work queue.
89 * @cmd_workq: command work queue.
90 */
91struct ipp_context {
92 struct exynos_drm_subdrv subdrv;
93 struct mutex ipp_lock;
94 struct mutex prop_lock;
95 struct idr ipp_idr;
96 struct idr prop_idr;
97 struct workqueue_struct *event_workq;
98 struct workqueue_struct *cmd_workq;
99};
100
101static LIST_HEAD(exynos_drm_ippdrv_list);
102static DEFINE_MUTEX(exynos_drm_ippdrv_lock);
103static BLOCKING_NOTIFIER_HEAD(exynos_drm_ippnb_list);
104
105int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
106{
107 DRM_DEBUG_KMS("%s\n", __func__);
108
109 if (!ippdrv)
110 return -EINVAL;
111
112 mutex_lock(&exynos_drm_ippdrv_lock);
113 list_add_tail(&ippdrv->drv_list, &exynos_drm_ippdrv_list);
114 mutex_unlock(&exynos_drm_ippdrv_lock);
115
116 return 0;
117}
118
119int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
120{
121 DRM_DEBUG_KMS("%s\n", __func__);
122
123 if (!ippdrv)
124 return -EINVAL;
125
126 mutex_lock(&exynos_drm_ippdrv_lock);
127 list_del(&ippdrv->drv_list);
128 mutex_unlock(&exynos_drm_ippdrv_lock);
129
130 return 0;
131}
132
133static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj,
134 u32 *idp)
135{
136 int ret;
137
138 DRM_DEBUG_KMS("%s\n", __func__);
139
140again:
141 /* ensure there is space available to allocate a handle */
142 if (idr_pre_get(id_idr, GFP_KERNEL) == 0) {
143 DRM_ERROR("failed to get idr.\n");
144 return -ENOMEM;
145 }
146
147 /* do the allocation under our mutexlock */
148 mutex_lock(lock);
149 ret = idr_get_new_above(id_idr, obj, 1, (int *)idp);
150 mutex_unlock(lock);
151 if (ret == -EAGAIN)
152 goto again;
153
154 return ret;
155}
156
157static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id)
158{
159 void *obj;
160
161 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, id);
162
163 mutex_lock(lock);
164
165 /* find object using handle */
166 obj = idr_find(id_idr, id);
167 if (!obj) {
168 DRM_ERROR("failed to find object.\n");
169 mutex_unlock(lock);
170 return ERR_PTR(-ENODEV);
171 }
172
173 mutex_unlock(lock);
174
175 return obj;
176}
177
178static inline bool ipp_check_dedicated(struct exynos_drm_ippdrv *ippdrv,
179 enum drm_exynos_ipp_cmd cmd)
180{
181 /*
182 * check dedicated flag and WB, OUTPUT operation with
183 * power on state.
184 */
185 if (ippdrv->dedicated || (!ipp_is_m2m_cmd(cmd) &&
186 !pm_runtime_suspended(ippdrv->dev)))
187 return true;
188
189 return false;
190}
191
192static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
193 struct drm_exynos_ipp_property *property)
194{
195 struct exynos_drm_ippdrv *ippdrv;
196 u32 ipp_id = property->ipp_id;
197
198 DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, ipp_id);
199
200 if (ipp_id) {
201 /* find ipp driver using idr */
202 ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock,
203 ipp_id);
204 if (IS_ERR_OR_NULL(ippdrv)) {
205 DRM_ERROR("not found ipp%d driver.\n", ipp_id);
206 return ippdrv;
207 }
208
209 /*
210 * WB, OUTPUT opertion not supported multi-operation.
211 * so, make dedicated state at set property ioctl.
212 * when ipp driver finished operations, clear dedicated flags.
213 */
214 if (ipp_check_dedicated(ippdrv, property->cmd)) {
215 DRM_ERROR("already used choose device.\n");
216 return ERR_PTR(-EBUSY);
217 }
218
219 /*
220 * This is necessary to find correct device in ipp drivers.
221 * ipp drivers have different abilities,
222 * so need to check property.
223 */
224 if (ippdrv->check_property &&
225 ippdrv->check_property(ippdrv->dev, property)) {
226 DRM_ERROR("not support property.\n");
227 return ERR_PTR(-EINVAL);
228 }
229
230 return ippdrv;
231 } else {
232 /*
233 * This case is search all ipp driver for finding.
234 * user application don't set ipp_id in this case,
235 * so ipp subsystem search correct driver in driver list.
236 */
237 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
238 if (ipp_check_dedicated(ippdrv, property->cmd)) {
239 DRM_DEBUG_KMS("%s:used device.\n", __func__);
240 continue;
241 }
242
243 if (ippdrv->check_property &&
244 ippdrv->check_property(ippdrv->dev, property)) {
245 DRM_DEBUG_KMS("%s:not support property.\n",
246 __func__);
247 continue;
248 }
249
250 return ippdrv;
251 }
252
253 DRM_ERROR("not support ipp driver operations.\n");
254 }
255
256 return ERR_PTR(-ENODEV);
257}
258
259static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)
260{
261 struct exynos_drm_ippdrv *ippdrv;
262 struct drm_exynos_ipp_cmd_node *c_node;
263 int count = 0;
264
265 DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
266
267 if (list_empty(&exynos_drm_ippdrv_list)) {
268 DRM_DEBUG_KMS("%s:ippdrv_list is empty.\n", __func__);
269 return ERR_PTR(-ENODEV);
270 }
271
272 /*
273 * This case is search ipp driver by prop_id handle.
274 * sometimes, ipp subsystem find driver by prop_id.
275 * e.g PAUSE state, queue buf, command contro.
276 */
277 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
278 DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]\n", __func__,
279 count++, (int)ippdrv);
280
281 if (!list_empty(&ippdrv->cmd_list)) {
282 list_for_each_entry(c_node, &ippdrv->cmd_list, list)
283 if (c_node->property.prop_id == prop_id)
284 return ippdrv;
285 }
286 }
287
288 return ERR_PTR(-ENODEV);
289}
290
291int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
292 struct drm_file *file)
293{
294 struct drm_exynos_file_private *file_priv = file->driver_priv;
295 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
296 struct device *dev = priv->dev;
297 struct ipp_context *ctx = get_ipp_context(dev);
298 struct drm_exynos_ipp_prop_list *prop_list = data;
299 struct exynos_drm_ippdrv *ippdrv;
300 int count = 0;
301
302 DRM_DEBUG_KMS("%s\n", __func__);
303
304 if (!ctx) {
305 DRM_ERROR("invalid context.\n");
306 return -EINVAL;
307 }
308
309 if (!prop_list) {
310 DRM_ERROR("invalid property parameter.\n");
311 return -EINVAL;
312 }
313
314 DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, prop_list->ipp_id);
315
316 if (!prop_list->ipp_id) {
317 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list)
318 count++;
319 /*
320 * Supports ippdrv list count for user application.
321 * First step user application getting ippdrv count.
322 * and second step getting ippdrv capability using ipp_id.
323 */
324 prop_list->count = count;
325 } else {
326 /*
327 * Getting ippdrv capability by ipp_id.
328 * some deivce not supported wb, output interface.
329 * so, user application detect correct ipp driver
330 * using this ioctl.
331 */
332 ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock,
333 prop_list->ipp_id);
334 if (!ippdrv) {
335 DRM_ERROR("not found ipp%d driver.\n",
336 prop_list->ipp_id);
337 return -EINVAL;
338 }
339
340 prop_list = ippdrv->prop_list;
341 }
342
343 return 0;
344}
345
346static void ipp_print_property(struct drm_exynos_ipp_property *property,
347 int idx)
348{
349 struct drm_exynos_ipp_config *config = &property->config[idx];
350 struct drm_exynos_pos *pos = &config->pos;
351 struct drm_exynos_sz *sz = &config->sz;
352
353 DRM_DEBUG_KMS("%s:prop_id[%d]ops[%s]fmt[0x%x]\n",
354 __func__, property->prop_id, idx ? "dst" : "src", config->fmt);
355
356 DRM_DEBUG_KMS("%s:pos[%d %d %d %d]sz[%d %d]f[%d]r[%d]\n",
357 __func__, pos->x, pos->y, pos->w, pos->h,
358 sz->hsize, sz->vsize, config->flip, config->degree);
359}
360
361static int ipp_find_and_set_property(struct drm_exynos_ipp_property *property)
362{
363 struct exynos_drm_ippdrv *ippdrv;
364 struct drm_exynos_ipp_cmd_node *c_node;
365 u32 prop_id = property->prop_id;
366
367 DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
368
369 ippdrv = ipp_find_drv_by_handle(prop_id);
370 if (IS_ERR_OR_NULL(ippdrv)) {
371 DRM_ERROR("failed to get ipp driver.\n");
372 return -EINVAL;
373 }
374
375 /*
376 * Find command node using command list in ippdrv.
377 * when we find this command no using prop_id.
378 * return property information set in this command node.
379 */
380 list_for_each_entry(c_node, &ippdrv->cmd_list, list) {
381 if ((c_node->property.prop_id == prop_id) &&
382 (c_node->state == IPP_STATE_STOP)) {
383 DRM_DEBUG_KMS("%s:found cmd[%d]ippdrv[0x%x]\n",
384 __func__, property->cmd, (int)ippdrv);
385
386 c_node->property = *property;
387 return 0;
388 }
389 }
390
391 DRM_ERROR("failed to search property.\n");
392
393 return -EINVAL;
394}
395
396static struct drm_exynos_ipp_cmd_work *ipp_create_cmd_work(void)
397{
398 struct drm_exynos_ipp_cmd_work *cmd_work;
399
400 DRM_DEBUG_KMS("%s\n", __func__);
401
402 cmd_work = kzalloc(sizeof(*cmd_work), GFP_KERNEL);
403 if (!cmd_work) {
404 DRM_ERROR("failed to alloc cmd_work.\n");
405 return ERR_PTR(-ENOMEM);
406 }
407
408 INIT_WORK((struct work_struct *)cmd_work, ipp_sched_cmd);
409
410 return cmd_work;
411}
412
413static struct drm_exynos_ipp_event_work *ipp_create_event_work(void)
414{
415 struct drm_exynos_ipp_event_work *event_work;
416
417 DRM_DEBUG_KMS("%s\n", __func__);
418
419 event_work = kzalloc(sizeof(*event_work), GFP_KERNEL);
420 if (!event_work) {
421 DRM_ERROR("failed to alloc event_work.\n");
422 return ERR_PTR(-ENOMEM);
423 }
424
425 INIT_WORK((struct work_struct *)event_work, ipp_sched_event);
426
427 return event_work;
428}
429
430int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
431 struct drm_file *file)
432{
433 struct drm_exynos_file_private *file_priv = file->driver_priv;
434 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
435 struct device *dev = priv->dev;
436 struct ipp_context *ctx = get_ipp_context(dev);
437 struct drm_exynos_ipp_property *property = data;
438 struct exynos_drm_ippdrv *ippdrv;
439 struct drm_exynos_ipp_cmd_node *c_node;
440 int ret, i;
441
442 DRM_DEBUG_KMS("%s\n", __func__);
443
444 if (!ctx) {
445 DRM_ERROR("invalid context.\n");
446 return -EINVAL;
447 }
448
449 if (!property) {
450 DRM_ERROR("invalid property parameter.\n");
451 return -EINVAL;
452 }
453
454 /*
455 * This is log print for user application property.
456 * user application set various property.
457 */
458 for_each_ipp_ops(i)
459 ipp_print_property(property, i);
460
461 /*
462 * set property ioctl generated new prop_id.
463 * but in this case already asigned prop_id using old set property.
464 * e.g PAUSE state. this case supports find current prop_id and use it
465 * instead of allocation.
466 */
467 if (property->prop_id) {
468 DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
469 return ipp_find_and_set_property(property);
470 }
471
472 /* find ipp driver using ipp id */
473 ippdrv = ipp_find_driver(ctx, property);
474 if (IS_ERR_OR_NULL(ippdrv)) {
475 DRM_ERROR("failed to get ipp driver.\n");
476 return -EINVAL;
477 }
478
479 /* allocate command node */
480 c_node = kzalloc(sizeof(*c_node), GFP_KERNEL);
481 if (!c_node) {
482 DRM_ERROR("failed to allocate map node.\n");
483 return -ENOMEM;
484 }
485
486 /* create property id */
487 ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node,
488 &property->prop_id);
489 if (ret) {
490 DRM_ERROR("failed to create id.\n");
491 goto err_clear;
492 }
493
494 DRM_DEBUG_KMS("%s:created prop_id[%d]cmd[%d]ippdrv[0x%x]\n",
495 __func__, property->prop_id, property->cmd, (int)ippdrv);
496
497 /* stored property information and ippdrv in private data */
498 c_node->priv = priv;
499 c_node->property = *property;
500 c_node->state = IPP_STATE_IDLE;
501
502 c_node->start_work = ipp_create_cmd_work();
503 if (IS_ERR_OR_NULL(c_node->start_work)) {
504 DRM_ERROR("failed to create start work.\n");
505 goto err_clear;
506 }
507
508 c_node->stop_work = ipp_create_cmd_work();
509 if (IS_ERR_OR_NULL(c_node->stop_work)) {
510 DRM_ERROR("failed to create stop work.\n");
511 goto err_free_start;
512 }
513
514 c_node->event_work = ipp_create_event_work();
515 if (IS_ERR_OR_NULL(c_node->event_work)) {
516 DRM_ERROR("failed to create event work.\n");
517 goto err_free_stop;
518 }
519
520 mutex_init(&c_node->cmd_lock);
521 mutex_init(&c_node->mem_lock);
522 mutex_init(&c_node->event_lock);
523
524 init_completion(&c_node->start_complete);
525 init_completion(&c_node->stop_complete);
526
527 for_each_ipp_ops(i)
528 INIT_LIST_HEAD(&c_node->mem_list[i]);
529
530 INIT_LIST_HEAD(&c_node->event_list);
531 list_splice_init(&priv->event_list, &c_node->event_list);
532 list_add_tail(&c_node->list, &ippdrv->cmd_list);
533
534 /* make dedicated state without m2m */
535 if (!ipp_is_m2m_cmd(property->cmd))
536 ippdrv->dedicated = true;
537
538 return 0;
539
540err_free_stop:
541 kfree(c_node->stop_work);
542err_free_start:
543 kfree(c_node->start_work);
544err_clear:
545 kfree(c_node);
546 return ret;
547}
548
549static void ipp_clean_cmd_node(struct drm_exynos_ipp_cmd_node *c_node)
550{
551 DRM_DEBUG_KMS("%s\n", __func__);
552
553 /* delete list */
554 list_del(&c_node->list);
555
556 /* destroy mutex */
557 mutex_destroy(&c_node->cmd_lock);
558 mutex_destroy(&c_node->mem_lock);
559 mutex_destroy(&c_node->event_lock);
560
561 /* free command node */
562 kfree(c_node->start_work);
563 kfree(c_node->stop_work);
564 kfree(c_node->event_work);
565 kfree(c_node);
566}
567
568static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
569{
570 struct drm_exynos_ipp_property *property = &c_node->property;
571 struct drm_exynos_ipp_mem_node *m_node;
572 struct list_head *head;
573 int ret, i, count[EXYNOS_DRM_OPS_MAX] = { 0, };
574
575 DRM_DEBUG_KMS("%s\n", __func__);
576
577 mutex_lock(&c_node->mem_lock);
578
579 for_each_ipp_ops(i) {
580 /* source/destination memory list */
581 head = &c_node->mem_list[i];
582
583 if (list_empty(head)) {
584 DRM_DEBUG_KMS("%s:%s memory empty.\n", __func__,
585 i ? "dst" : "src");
586 continue;
587 }
588
589 /* find memory node entry */
590 list_for_each_entry(m_node, head, list) {
591 DRM_DEBUG_KMS("%s:%s,count[%d]m_node[0x%x]\n", __func__,
592 i ? "dst" : "src", count[i], (int)m_node);
593 count[i]++;
594 }
595 }
596
597 DRM_DEBUG_KMS("%s:min[%d]max[%d]\n", __func__,
598 min(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]),
599 max(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]));
600
601 /*
602 * M2M operations should be need paired memory address.
603 * so, need to check minimum count about src, dst.
604 * other case not use paired memory, so use maximum count
605 */
606 if (ipp_is_m2m_cmd(property->cmd))
607 ret = min(count[EXYNOS_DRM_OPS_SRC],
608 count[EXYNOS_DRM_OPS_DST]);
609 else
610 ret = max(count[EXYNOS_DRM_OPS_SRC],
611 count[EXYNOS_DRM_OPS_DST]);
612
613 mutex_unlock(&c_node->mem_lock);
614
615 return ret;
616}
617
618static struct drm_exynos_ipp_mem_node
619 *ipp_find_mem_node(struct drm_exynos_ipp_cmd_node *c_node,
620 struct drm_exynos_ipp_queue_buf *qbuf)
621{
622 struct drm_exynos_ipp_mem_node *m_node;
623 struct list_head *head;
624 int count = 0;
625
626 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, qbuf->buf_id);
627
628 /* source/destination memory list */
629 head = &c_node->mem_list[qbuf->ops_id];
630
631 /* find memory node from memory list */
632 list_for_each_entry(m_node, head, list) {
633 DRM_DEBUG_KMS("%s:count[%d]m_node[0x%x]\n",
634 __func__, count++, (int)m_node);
635
636 /* compare buffer id */
637 if (m_node->buf_id == qbuf->buf_id)
638 return m_node;
639 }
640
641 return NULL;
642}
643
644static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
645 struct drm_exynos_ipp_cmd_node *c_node,
646 struct drm_exynos_ipp_mem_node *m_node)
647{
648 struct exynos_drm_ipp_ops *ops = NULL;
649 int ret = 0;
650
651 DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)m_node);
652
653 if (!m_node) {
654 DRM_ERROR("invalid queue node.\n");
655 return -EFAULT;
656 }
657
658 mutex_lock(&c_node->mem_lock);
659
660 DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, m_node->ops_id);
661
662 /* get operations callback */
663 ops = ippdrv->ops[m_node->ops_id];
664 if (!ops) {
665 DRM_ERROR("not support ops.\n");
666 ret = -EFAULT;
667 goto err_unlock;
668 }
669
670 /* set address and enable irq */
671 if (ops->set_addr) {
672 ret = ops->set_addr(ippdrv->dev, &m_node->buf_info,
673 m_node->buf_id, IPP_BUF_ENQUEUE);
674 if (ret) {
675 DRM_ERROR("failed to set addr.\n");
676 goto err_unlock;
677 }
678 }
679
680err_unlock:
681 mutex_unlock(&c_node->mem_lock);
682 return ret;
683}
684
685static struct drm_exynos_ipp_mem_node
686 *ipp_get_mem_node(struct drm_device *drm_dev,
687 struct drm_file *file,
688 struct drm_exynos_ipp_cmd_node *c_node,
689 struct drm_exynos_ipp_queue_buf *qbuf)
690{
691 struct drm_exynos_ipp_mem_node *m_node;
692 struct drm_exynos_ipp_buf_info buf_info;
693 void *addr;
694 int i;
695
696 DRM_DEBUG_KMS("%s\n", __func__);
697
698 mutex_lock(&c_node->mem_lock);
699
700 m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
701 if (!m_node) {
702 DRM_ERROR("failed to allocate queue node.\n");
703 goto err_unlock;
704 }
705
706 /* clear base address for error handling */
707 memset(&buf_info, 0x0, sizeof(buf_info));
708
709 /* operations, buffer id */
710 m_node->ops_id = qbuf->ops_id;
711 m_node->prop_id = qbuf->prop_id;
712 m_node->buf_id = qbuf->buf_id;
713
714 DRM_DEBUG_KMS("%s:m_node[0x%x]ops_id[%d]\n", __func__,
715 (int)m_node, qbuf->ops_id);
716 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]\n", __func__,
717 qbuf->prop_id, m_node->buf_id);
718
719 for_each_ipp_planar(i) {
720 DRM_DEBUG_KMS("%s:i[%d]handle[0x%x]\n", __func__,
721 i, qbuf->handle[i]);
722
723 /* get dma address by handle */
724 if (qbuf->handle[i]) {
725 addr = exynos_drm_gem_get_dma_addr(drm_dev,
726 qbuf->handle[i], file);
727 if (IS_ERR(addr)) {
728 DRM_ERROR("failed to get addr.\n");
729 goto err_clear;
730 }
731
732 buf_info.handles[i] = qbuf->handle[i];
733 buf_info.base[i] = *(dma_addr_t *) addr;
734 DRM_DEBUG_KMS("%s:i[%d]base[0x%x]hd[0x%x]\n",
735 __func__, i, buf_info.base[i],
736 (int)buf_info.handles[i]);
737 }
738 }
739
740 m_node->filp = file;
741 m_node->buf_info = buf_info;
742 list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]);
743
744 mutex_unlock(&c_node->mem_lock);
745 return m_node;
746
747err_clear:
748 kfree(m_node);
749err_unlock:
750 mutex_unlock(&c_node->mem_lock);
751 return ERR_PTR(-EFAULT);
752}
753
754static int ipp_put_mem_node(struct drm_device *drm_dev,
755 struct drm_exynos_ipp_cmd_node *c_node,
756 struct drm_exynos_ipp_mem_node *m_node)
757{
758 int i;
759
760 DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)m_node);
761
762 if (!m_node) {
763 DRM_ERROR("invalid dequeue node.\n");
764 return -EFAULT;
765 }
766
767 if (list_empty(&m_node->list)) {
768 DRM_ERROR("empty memory node.\n");
769 return -ENOMEM;
770 }
771
772 mutex_lock(&c_node->mem_lock);
773
774 DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, m_node->ops_id);
775
776 /* put gem buffer */
777 for_each_ipp_planar(i) {
778 unsigned long handle = m_node->buf_info.handles[i];
779 if (handle)
780 exynos_drm_gem_put_dma_addr(drm_dev, handle,
781 m_node->filp);
782 }
783
784 /* delete list in queue */
785 list_del(&m_node->list);
786 kfree(m_node);
787
788 mutex_unlock(&c_node->mem_lock);
789
790 return 0;
791}
792
793static void ipp_free_event(struct drm_pending_event *event)
794{
795 kfree(event);
796}
797
798static int ipp_get_event(struct drm_device *drm_dev,
799 struct drm_file *file,
800 struct drm_exynos_ipp_cmd_node *c_node,
801 struct drm_exynos_ipp_queue_buf *qbuf)
802{
803 struct drm_exynos_ipp_send_event *e;
804 unsigned long flags;
805
806 DRM_DEBUG_KMS("%s:ops_id[%d]buf_id[%d]\n", __func__,
807 qbuf->ops_id, qbuf->buf_id);
808
809 e = kzalloc(sizeof(*e), GFP_KERNEL);
810
811 if (!e) {
812 DRM_ERROR("failed to allocate event.\n");
813 spin_lock_irqsave(&drm_dev->event_lock, flags);
814 file->event_space += sizeof(e->event);
815 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
816 return -ENOMEM;
817 }
818
819 /* make event */
820 e->event.base.type = DRM_EXYNOS_IPP_EVENT;
821 e->event.base.length = sizeof(e->event);
822 e->event.user_data = qbuf->user_data;
823 e->event.prop_id = qbuf->prop_id;
824 e->event.buf_id[EXYNOS_DRM_OPS_DST] = qbuf->buf_id;
825 e->base.event = &e->event.base;
826 e->base.file_priv = file;
827 e->base.destroy = ipp_free_event;
828 list_add_tail(&e->base.link, &c_node->event_list);
829
830 return 0;
831}
832
833static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
834 struct drm_exynos_ipp_queue_buf *qbuf)
835{
836 struct drm_exynos_ipp_send_event *e, *te;
837 int count = 0;
838
839 DRM_DEBUG_KMS("%s\n", __func__);
840
841 if (list_empty(&c_node->event_list)) {
842 DRM_DEBUG_KMS("%s:event_list is empty.\n", __func__);
843 return;
844 }
845
846 list_for_each_entry_safe(e, te, &c_node->event_list, base.link) {
847 DRM_DEBUG_KMS("%s:count[%d]e[0x%x]\n",
848 __func__, count++, (int)e);
849
850 /*
851 * quf == NULL condition means all event deletion.
852 * stop operations want to delete all event list.
853 * another case delete only same buf id.
854 */
855 if (!qbuf) {
856 /* delete list */
857 list_del(&e->base.link);
858 kfree(e);
859 }
860
861 /* compare buffer id */
862 if (qbuf && (qbuf->buf_id ==
863 e->event.buf_id[EXYNOS_DRM_OPS_DST])) {
864 /* delete list */
865 list_del(&e->base.link);
866 kfree(e);
867 return;
868 }
869 }
870}
871
872void ipp_handle_cmd_work(struct device *dev,
873 struct exynos_drm_ippdrv *ippdrv,
874 struct drm_exynos_ipp_cmd_work *cmd_work,
875 struct drm_exynos_ipp_cmd_node *c_node)
876{
877 struct ipp_context *ctx = get_ipp_context(dev);
878
879 cmd_work->ippdrv = ippdrv;
880 cmd_work->c_node = c_node;
881 queue_work(ctx->cmd_workq, (struct work_struct *)cmd_work);
882}
883
884static int ipp_queue_buf_with_run(struct device *dev,
885 struct drm_exynos_ipp_cmd_node *c_node,
886 struct drm_exynos_ipp_mem_node *m_node,
887 struct drm_exynos_ipp_queue_buf *qbuf)
888{
889 struct exynos_drm_ippdrv *ippdrv;
890 struct drm_exynos_ipp_property *property;
891 struct exynos_drm_ipp_ops *ops;
892 int ret;
893
894 DRM_DEBUG_KMS("%s\n", __func__);
895
896 ippdrv = ipp_find_drv_by_handle(qbuf->prop_id);
897 if (IS_ERR_OR_NULL(ippdrv)) {
898 DRM_ERROR("failed to get ipp driver.\n");
899 return -EFAULT;
900 }
901
902 ops = ippdrv->ops[qbuf->ops_id];
903 if (!ops) {
904 DRM_ERROR("failed to get ops.\n");
905 return -EFAULT;
906 }
907
908 property = &c_node->property;
909
910 if (c_node->state != IPP_STATE_START) {
911 DRM_DEBUG_KMS("%s:bypass for invalid state.\n" , __func__);
912 return 0;
913 }
914
915 if (!ipp_check_mem_list(c_node)) {
916 DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
917 return 0;
918 }
919
920 /*
921 * If set destination buffer and enabled clock,
922 * then m2m operations need start operations at queue_buf
923 */
924 if (ipp_is_m2m_cmd(property->cmd)) {
925 struct drm_exynos_ipp_cmd_work *cmd_work = c_node->start_work;
926
927 cmd_work->ctrl = IPP_CTRL_PLAY;
928 ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
929 } else {
930 ret = ipp_set_mem_node(ippdrv, c_node, m_node);
931 if (ret) {
932 DRM_ERROR("failed to set m node.\n");
933 return ret;
934 }
935 }
936
937 return 0;
938}
939
940static void ipp_clean_queue_buf(struct drm_device *drm_dev,
941 struct drm_exynos_ipp_cmd_node *c_node,
942 struct drm_exynos_ipp_queue_buf *qbuf)
943{
944 struct drm_exynos_ipp_mem_node *m_node, *tm_node;
945
946 DRM_DEBUG_KMS("%s\n", __func__);
947
948 if (!list_empty(&c_node->mem_list[qbuf->ops_id])) {
949 /* delete list */
950 list_for_each_entry_safe(m_node, tm_node,
951 &c_node->mem_list[qbuf->ops_id], list) {
952 if (m_node->buf_id == qbuf->buf_id &&
953 m_node->ops_id == qbuf->ops_id)
954 ipp_put_mem_node(drm_dev, c_node, m_node);
955 }
956 }
957}
958
959int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
960 struct drm_file *file)
961{
962 struct drm_exynos_file_private *file_priv = file->driver_priv;
963 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
964 struct device *dev = priv->dev;
965 struct ipp_context *ctx = get_ipp_context(dev);
966 struct drm_exynos_ipp_queue_buf *qbuf = data;
967 struct drm_exynos_ipp_cmd_node *c_node;
968 struct drm_exynos_ipp_mem_node *m_node;
969 int ret;
970
971 DRM_DEBUG_KMS("%s\n", __func__);
972
973 if (!qbuf) {
974 DRM_ERROR("invalid buf parameter.\n");
975 return -EINVAL;
976 }
977
978 if (qbuf->ops_id >= EXYNOS_DRM_OPS_MAX) {
979 DRM_ERROR("invalid ops parameter.\n");
980 return -EINVAL;
981 }
982
983 DRM_DEBUG_KMS("%s:prop_id[%d]ops_id[%s]buf_id[%d]buf_type[%d]\n",
984 __func__, qbuf->prop_id, qbuf->ops_id ? "dst" : "src",
985 qbuf->buf_id, qbuf->buf_type);
986
987 /* find command node */
988 c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
989 qbuf->prop_id);
990 if (!c_node) {
991 DRM_ERROR("failed to get command node.\n");
992 return -EFAULT;
993 }
994
995 /* buffer control */
996 switch (qbuf->buf_type) {
997 case IPP_BUF_ENQUEUE:
998 /* get memory node */
999 m_node = ipp_get_mem_node(drm_dev, file, c_node, qbuf);
1000 if (IS_ERR(m_node)) {
1001 DRM_ERROR("failed to get m_node.\n");
1002 return PTR_ERR(m_node);
1003 }
1004
1005 /*
1006 * first step get event for destination buffer.
1007 * and second step when M2M case run with destination buffer
1008 * if needed.
1009 */
1010 if (qbuf->ops_id == EXYNOS_DRM_OPS_DST) {
1011 /* get event for destination buffer */
1012 ret = ipp_get_event(drm_dev, file, c_node, qbuf);
1013 if (ret) {
1014 DRM_ERROR("failed to get event.\n");
1015 goto err_clean_node;
1016 }
1017
1018 /*
1019 * M2M case run play control for streaming feature.
1020 * other case set address and waiting.
1021 */
1022 ret = ipp_queue_buf_with_run(dev, c_node, m_node, qbuf);
1023 if (ret) {
1024 DRM_ERROR("failed to run command.\n");
1025 goto err_clean_node;
1026 }
1027 }
1028 break;
1029 case IPP_BUF_DEQUEUE:
1030 mutex_lock(&c_node->cmd_lock);
1031
1032 /* put event for destination buffer */
1033 if (qbuf->ops_id == EXYNOS_DRM_OPS_DST)
1034 ipp_put_event(c_node, qbuf);
1035
1036 ipp_clean_queue_buf(drm_dev, c_node, qbuf);
1037
1038 mutex_unlock(&c_node->cmd_lock);
1039 break;
1040 default:
1041 DRM_ERROR("invalid buffer control.\n");
1042 return -EINVAL;
1043 }
1044
1045 return 0;
1046
1047err_clean_node:
1048 DRM_ERROR("clean memory nodes.\n");
1049
1050 ipp_clean_queue_buf(drm_dev, c_node, qbuf);
1051 return ret;
1052}
1053
1054static bool exynos_drm_ipp_check_valid(struct device *dev,
1055 enum drm_exynos_ipp_ctrl ctrl, enum drm_exynos_ipp_state state)
1056{
1057 DRM_DEBUG_KMS("%s\n", __func__);
1058
1059 if (ctrl != IPP_CTRL_PLAY) {
1060 if (pm_runtime_suspended(dev)) {
1061 DRM_ERROR("pm:runtime_suspended.\n");
1062 goto err_status;
1063 }
1064 }
1065
1066 switch (ctrl) {
1067 case IPP_CTRL_PLAY:
1068 if (state != IPP_STATE_IDLE)
1069 goto err_status;
1070 break;
1071 case IPP_CTRL_STOP:
1072 if (state == IPP_STATE_STOP)
1073 goto err_status;
1074 break;
1075 case IPP_CTRL_PAUSE:
1076 if (state != IPP_STATE_START)
1077 goto err_status;
1078 break;
1079 case IPP_CTRL_RESUME:
1080 if (state != IPP_STATE_STOP)
1081 goto err_status;
1082 break;
1083 default:
1084 DRM_ERROR("invalid state.\n");
1085 goto err_status;
1086 break;
1087 }
1088
1089 return true;
1090
1091err_status:
1092 DRM_ERROR("invalid status:ctrl[%d]state[%d]\n", ctrl, state);
1093 return false;
1094}
1095
1096int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
1097 struct drm_file *file)
1098{
1099 struct drm_exynos_file_private *file_priv = file->driver_priv;
1100 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
1101 struct exynos_drm_ippdrv *ippdrv = NULL;
1102 struct device *dev = priv->dev;
1103 struct ipp_context *ctx = get_ipp_context(dev);
1104 struct drm_exynos_ipp_cmd_ctrl *cmd_ctrl = data;
1105 struct drm_exynos_ipp_cmd_work *cmd_work;
1106 struct drm_exynos_ipp_cmd_node *c_node;
1107
1108 DRM_DEBUG_KMS("%s\n", __func__);
1109
1110 if (!ctx) {
1111 DRM_ERROR("invalid context.\n");
1112 return -EINVAL;
1113 }
1114
1115 if (!cmd_ctrl) {
1116 DRM_ERROR("invalid control parameter.\n");
1117 return -EINVAL;
1118 }
1119
1120 DRM_DEBUG_KMS("%s:ctrl[%d]prop_id[%d]\n", __func__,
1121 cmd_ctrl->ctrl, cmd_ctrl->prop_id);
1122
1123 ippdrv = ipp_find_drv_by_handle(cmd_ctrl->prop_id);
1124 if (IS_ERR(ippdrv)) {
1125 DRM_ERROR("failed to get ipp driver.\n");
1126 return PTR_ERR(ippdrv);
1127 }
1128
1129 c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
1130 cmd_ctrl->prop_id);
1131 if (!c_node) {
1132 DRM_ERROR("invalid command node list.\n");
1133 return -EINVAL;
1134 }
1135
1136 if (!exynos_drm_ipp_check_valid(ippdrv->dev, cmd_ctrl->ctrl,
1137 c_node->state)) {
1138 DRM_ERROR("invalid state.\n");
1139 return -EINVAL;
1140 }
1141
1142 switch (cmd_ctrl->ctrl) {
1143 case IPP_CTRL_PLAY:
1144 if (pm_runtime_suspended(ippdrv->dev))
1145 pm_runtime_get_sync(ippdrv->dev);
1146 c_node->state = IPP_STATE_START;
1147
1148 cmd_work = c_node->start_work;
1149 cmd_work->ctrl = cmd_ctrl->ctrl;
1150 ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
1151 c_node->state = IPP_STATE_START;
1152 break;
1153 case IPP_CTRL_STOP:
1154 cmd_work = c_node->stop_work;
1155 cmd_work->ctrl = cmd_ctrl->ctrl;
1156 ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
1157
1158 if (!wait_for_completion_timeout(&c_node->stop_complete,
1159 msecs_to_jiffies(300))) {
1160 DRM_ERROR("timeout stop:prop_id[%d]\n",
1161 c_node->property.prop_id);
1162 }
1163
1164 c_node->state = IPP_STATE_STOP;
1165 ippdrv->dedicated = false;
1166 ipp_clean_cmd_node(c_node);
1167
1168 if (list_empty(&ippdrv->cmd_list))
1169 pm_runtime_put_sync(ippdrv->dev);
1170 break;
1171 case IPP_CTRL_PAUSE:
1172 cmd_work = c_node->stop_work;
1173 cmd_work->ctrl = cmd_ctrl->ctrl;
1174 ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
1175
1176 if (!wait_for_completion_timeout(&c_node->stop_complete,
1177 msecs_to_jiffies(200))) {
1178 DRM_ERROR("timeout stop:prop_id[%d]\n",
1179 c_node->property.prop_id);
1180 }
1181
1182 c_node->state = IPP_STATE_STOP;
1183 break;
1184 case IPP_CTRL_RESUME:
1185 c_node->state = IPP_STATE_START;
1186 cmd_work = c_node->start_work;
1187 cmd_work->ctrl = cmd_ctrl->ctrl;
1188 ipp_handle_cmd_work(dev, ippdrv, cmd_work, c_node);
1189 break;
1190 default:
1191 DRM_ERROR("could not support this state currently.\n");
1192 return -EINVAL;
1193 }
1194
1195 DRM_DEBUG_KMS("%s:done ctrl[%d]prop_id[%d]\n", __func__,
1196 cmd_ctrl->ctrl, cmd_ctrl->prop_id);
1197
1198 return 0;
1199}
1200
1201int exynos_drm_ippnb_register(struct notifier_block *nb)
1202{
1203 return blocking_notifier_chain_register(
1204 &exynos_drm_ippnb_list, nb);
1205}
1206
1207int exynos_drm_ippnb_unregister(struct notifier_block *nb)
1208{
1209 return blocking_notifier_chain_unregister(
1210 &exynos_drm_ippnb_list, nb);
1211}
1212
1213int exynos_drm_ippnb_send_event(unsigned long val, void *v)
1214{
1215 return blocking_notifier_call_chain(
1216 &exynos_drm_ippnb_list, val, v);
1217}
1218
1219static int ipp_set_property(struct exynos_drm_ippdrv *ippdrv,
1220 struct drm_exynos_ipp_property *property)
1221{
1222 struct exynos_drm_ipp_ops *ops = NULL;
1223 bool swap = false;
1224 int ret, i;
1225
1226 if (!property) {
1227 DRM_ERROR("invalid property parameter.\n");
1228 return -EINVAL;
1229 }
1230
1231 DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
1232
1233 /* reset h/w block */
1234 if (ippdrv->reset &&
1235 ippdrv->reset(ippdrv->dev)) {
1236 DRM_ERROR("failed to reset.\n");
1237 return -EINVAL;
1238 }
1239
1240 /* set source,destination operations */
1241 for_each_ipp_ops(i) {
1242 struct drm_exynos_ipp_config *config =
1243 &property->config[i];
1244
1245 ops = ippdrv->ops[i];
1246 if (!ops || !config) {
1247 DRM_ERROR("not support ops and config.\n");
1248 return -EINVAL;
1249 }
1250
1251 /* set format */
1252 if (ops->set_fmt) {
1253 ret = ops->set_fmt(ippdrv->dev, config->fmt);
1254 if (ret) {
1255 DRM_ERROR("not support format.\n");
1256 return ret;
1257 }
1258 }
1259
1260 /* set transform for rotation, flip */
1261 if (ops->set_transf) {
1262 ret = ops->set_transf(ippdrv->dev, config->degree,
1263 config->flip, &swap);
1264 if (ret) {
1265 DRM_ERROR("not support tranf.\n");
1266 return -EINVAL;
1267 }
1268 }
1269
1270 /* set size */
1271 if (ops->set_size) {
1272 ret = ops->set_size(ippdrv->dev, swap, &config->pos,
1273 &config->sz);
1274 if (ret) {
1275 DRM_ERROR("not support size.\n");
1276 return ret;
1277 }
1278 }
1279 }
1280
1281 return 0;
1282}
1283
1284static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
1285 struct drm_exynos_ipp_cmd_node *c_node)
1286{
1287 struct drm_exynos_ipp_mem_node *m_node;
1288 struct drm_exynos_ipp_property *property = &c_node->property;
1289 struct list_head *head;
1290 int ret, i;
1291
1292 DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
1293
1294 /* store command info in ippdrv */
1295 ippdrv->cmd = c_node;
1296
1297 if (!ipp_check_mem_list(c_node)) {
1298 DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
1299 return -ENOMEM;
1300 }
1301
1302 /* set current property in ippdrv */
1303 ret = ipp_set_property(ippdrv, property);
1304 if (ret) {
1305 DRM_ERROR("failed to set property.\n");
1306 ippdrv->cmd = NULL;
1307 return ret;
1308 }
1309
1310 /* check command */
1311 switch (property->cmd) {
1312 case IPP_CMD_M2M:
1313 for_each_ipp_ops(i) {
1314 /* source/destination memory list */
1315 head = &c_node->mem_list[i];
1316
1317 m_node = list_first_entry(head,
1318 struct drm_exynos_ipp_mem_node, list);
1319 if (!m_node) {
1320 DRM_ERROR("failed to get node.\n");
1321 ret = -EFAULT;
1322 return ret;
1323 }
1324
1325 DRM_DEBUG_KMS("%s:m_node[0x%x]\n",
1326 __func__, (int)m_node);
1327
1328 ret = ipp_set_mem_node(ippdrv, c_node, m_node);
1329 if (ret) {
1330 DRM_ERROR("failed to set m node.\n");
1331 return ret;
1332 }
1333 }
1334 break;
1335 case IPP_CMD_WB:
1336 /* destination memory list */
1337 head = &c_node->mem_list[EXYNOS_DRM_OPS_DST];
1338
1339 list_for_each_entry(m_node, head, list) {
1340 ret = ipp_set_mem_node(ippdrv, c_node, m_node);
1341 if (ret) {
1342 DRM_ERROR("failed to set m node.\n");
1343 return ret;
1344 }
1345 }
1346 break;
1347 case IPP_CMD_OUTPUT:
1348 /* source memory list */
1349 head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC];
1350
1351 list_for_each_entry(m_node, head, list) {
1352 ret = ipp_set_mem_node(ippdrv, c_node, m_node);
1353 if (ret) {
1354 DRM_ERROR("failed to set m node.\n");
1355 return ret;
1356 }
1357 }
1358 break;
1359 default:
1360 DRM_ERROR("invalid operations.\n");
1361 return -EINVAL;
1362 }
1363
1364 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, property->cmd);
1365
1366 /* start operations */
1367 if (ippdrv->start) {
1368 ret = ippdrv->start(ippdrv->dev, property->cmd);
1369 if (ret) {
1370 DRM_ERROR("failed to start ops.\n");
1371 return ret;
1372 }
1373 }
1374
1375 return 0;
1376}
1377
1378static int ipp_stop_property(struct drm_device *drm_dev,
1379 struct exynos_drm_ippdrv *ippdrv,
1380 struct drm_exynos_ipp_cmd_node *c_node)
1381{
1382 struct drm_exynos_ipp_mem_node *m_node, *tm_node;
1383 struct drm_exynos_ipp_property *property = &c_node->property;
1384 struct list_head *head;
1385 int ret = 0, i;
1386
1387 DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
1388
1389 /* put event */
1390 ipp_put_event(c_node, NULL);
1391
1392 /* check command */
1393 switch (property->cmd) {
1394 case IPP_CMD_M2M:
1395 for_each_ipp_ops(i) {
1396 /* source/destination memory list */
1397 head = &c_node->mem_list[i];
1398
1399 if (list_empty(head)) {
1400 DRM_DEBUG_KMS("%s:mem_list is empty.\n",
1401 __func__);
1402 break;
1403 }
1404
1405 list_for_each_entry_safe(m_node, tm_node,
1406 head, list) {
1407 ret = ipp_put_mem_node(drm_dev, c_node,
1408 m_node);
1409 if (ret) {
1410 DRM_ERROR("failed to put m_node.\n");
1411 goto err_clear;
1412 }
1413 }
1414 }
1415 break;
1416 case IPP_CMD_WB:
1417 /* destination memory list */
1418 head = &c_node->mem_list[EXYNOS_DRM_OPS_DST];
1419
1420 if (list_empty(head)) {
1421 DRM_DEBUG_KMS("%s:mem_list is empty.\n", __func__);
1422 break;
1423 }
1424
1425 list_for_each_entry_safe(m_node, tm_node, head, list) {
1426 ret = ipp_put_mem_node(drm_dev, c_node, m_node);
1427 if (ret) {
1428 DRM_ERROR("failed to put m_node.\n");
1429 goto err_clear;
1430 }
1431 }
1432 break;
1433 case IPP_CMD_OUTPUT:
1434 /* source memory list */
1435 head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC];
1436
1437 if (list_empty(head)) {
1438 DRM_DEBUG_KMS("%s:mem_list is empty.\n", __func__);
1439 break;
1440 }
1441
1442 list_for_each_entry_safe(m_node, tm_node, head, list) {
1443 ret = ipp_put_mem_node(drm_dev, c_node, m_node);
1444 if (ret) {
1445 DRM_ERROR("failed to put m_node.\n");
1446 goto err_clear;
1447 }
1448 }
1449 break;
1450 default:
1451 DRM_ERROR("invalid operations.\n");
1452 ret = -EINVAL;
1453 goto err_clear;
1454 }
1455
1456err_clear:
1457 /* stop operations */
1458 if (ippdrv->stop)
1459 ippdrv->stop(ippdrv->dev, property->cmd);
1460
1461 return ret;
1462}
1463
1464void ipp_sched_cmd(struct work_struct *work)
1465{
1466 struct drm_exynos_ipp_cmd_work *cmd_work =
1467 (struct drm_exynos_ipp_cmd_work *)work;
1468 struct exynos_drm_ippdrv *ippdrv;
1469 struct drm_exynos_ipp_cmd_node *c_node;
1470 struct drm_exynos_ipp_property *property;
1471 int ret;
1472
1473 DRM_DEBUG_KMS("%s\n", __func__);
1474
1475 ippdrv = cmd_work->ippdrv;
1476 if (!ippdrv) {
1477 DRM_ERROR("invalid ippdrv list.\n");
1478 return;
1479 }
1480
1481 c_node = cmd_work->c_node;
1482 if (!c_node) {
1483 DRM_ERROR("invalid command node list.\n");
1484 return;
1485 }
1486
1487 mutex_lock(&c_node->cmd_lock);
1488
1489 property = &c_node->property;
1490 if (!property) {
1491 DRM_ERROR("failed to get property:prop_id[%d]\n",
1492 c_node->property.prop_id);
1493 goto err_unlock;
1494 }
1495
1496 switch (cmd_work->ctrl) {
1497 case IPP_CTRL_PLAY:
1498 case IPP_CTRL_RESUME:
1499 ret = ipp_start_property(ippdrv, c_node);
1500 if (ret) {
1501 DRM_ERROR("failed to start property:prop_id[%d]\n",
1502 c_node->property.prop_id);
1503 goto err_unlock;
1504 }
1505
1506 /*
1507 * M2M case supports wait_completion of transfer.
1508 * because M2M case supports single unit operation
1509 * with multiple queue.
1510 * M2M need to wait completion of data transfer.
1511 */
1512 if (ipp_is_m2m_cmd(property->cmd)) {
1513 if (!wait_for_completion_timeout
1514 (&c_node->start_complete, msecs_to_jiffies(200))) {
1515 DRM_ERROR("timeout event:prop_id[%d]\n",
1516 c_node->property.prop_id);
1517 goto err_unlock;
1518 }
1519 }
1520 break;
1521 case IPP_CTRL_STOP:
1522 case IPP_CTRL_PAUSE:
1523 ret = ipp_stop_property(ippdrv->drm_dev, ippdrv,
1524 c_node);
1525 if (ret) {
1526 DRM_ERROR("failed to stop property.\n");
1527 goto err_unlock;
1528 }
1529
1530 complete(&c_node->stop_complete);
1531 break;
1532 default:
1533 DRM_ERROR("unknown control type\n");
1534 break;
1535 }
1536
1537 DRM_DEBUG_KMS("%s:ctrl[%d] done.\n", __func__, cmd_work->ctrl);
1538
1539err_unlock:
1540 mutex_unlock(&c_node->cmd_lock);
1541}
1542
1543static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
1544 struct drm_exynos_ipp_cmd_node *c_node, int *buf_id)
1545{
1546 struct drm_device *drm_dev = ippdrv->drm_dev;
1547 struct drm_exynos_ipp_property *property = &c_node->property;
1548 struct drm_exynos_ipp_mem_node *m_node;
1549 struct drm_exynos_ipp_queue_buf qbuf;
1550 struct drm_exynos_ipp_send_event *e;
1551 struct list_head *head;
1552 struct timeval now;
1553 unsigned long flags;
1554 u32 tbuf_id[EXYNOS_DRM_OPS_MAX] = {0, };
1555 int ret, i;
1556
1557 for_each_ipp_ops(i)
1558 DRM_DEBUG_KMS("%s:%s buf_id[%d]\n", __func__,
1559 i ? "dst" : "src", buf_id[i]);
1560
1561 if (!drm_dev) {
1562 DRM_ERROR("failed to get drm_dev.\n");
1563 return -EINVAL;
1564 }
1565
1566 if (!property) {
1567 DRM_ERROR("failed to get property.\n");
1568 return -EINVAL;
1569 }
1570
1571 if (list_empty(&c_node->event_list)) {
1572 DRM_DEBUG_KMS("%s:event list is empty.\n", __func__);
1573 return 0;
1574 }
1575
1576 if (!ipp_check_mem_list(c_node)) {
1577 DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
1578 return 0;
1579 }
1580
1581 /* check command */
1582 switch (property->cmd) {
1583 case IPP_CMD_M2M:
1584 for_each_ipp_ops(i) {
1585 /* source/destination memory list */
1586 head = &c_node->mem_list[i];
1587
1588 m_node = list_first_entry(head,
1589 struct drm_exynos_ipp_mem_node, list);
1590 if (!m_node) {
1591 DRM_ERROR("empty memory node.\n");
1592 return -ENOMEM;
1593 }
1594
1595 tbuf_id[i] = m_node->buf_id;
1596 DRM_DEBUG_KMS("%s:%s buf_id[%d]\n", __func__,
1597 i ? "dst" : "src", tbuf_id[i]);
1598
1599 ret = ipp_put_mem_node(drm_dev, c_node, m_node);
1600 if (ret)
1601 DRM_ERROR("failed to put m_node.\n");
1602 }
1603 break;
1604 case IPP_CMD_WB:
1605 /* clear buf for finding */
1606 memset(&qbuf, 0x0, sizeof(qbuf));
1607 qbuf.ops_id = EXYNOS_DRM_OPS_DST;
1608 qbuf.buf_id = buf_id[EXYNOS_DRM_OPS_DST];
1609
1610 /* get memory node entry */
1611 m_node = ipp_find_mem_node(c_node, &qbuf);
1612 if (!m_node) {
1613 DRM_ERROR("empty memory node.\n");
1614 return -ENOMEM;
1615 }
1616
1617 tbuf_id[EXYNOS_DRM_OPS_DST] = m_node->buf_id;
1618
1619 ret = ipp_put_mem_node(drm_dev, c_node, m_node);
1620 if (ret)
1621 DRM_ERROR("failed to put m_node.\n");
1622 break;
1623 case IPP_CMD_OUTPUT:
1624 /* source memory list */
1625 head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC];
1626
1627 m_node = list_first_entry(head,
1628 struct drm_exynos_ipp_mem_node, list);
1629 if (!m_node) {
1630 DRM_ERROR("empty memory node.\n");
1631 return -ENOMEM;
1632 }
1633
1634 tbuf_id[EXYNOS_DRM_OPS_SRC] = m_node->buf_id;
1635
1636 ret = ipp_put_mem_node(drm_dev, c_node, m_node);
1637 if (ret)
1638 DRM_ERROR("failed to put m_node.\n");
1639 break;
1640 default:
1641 DRM_ERROR("invalid operations.\n");
1642 return -EINVAL;
1643 }
1644
1645 if (tbuf_id[EXYNOS_DRM_OPS_DST] != buf_id[EXYNOS_DRM_OPS_DST])
1646 DRM_ERROR("failed to match buf_id[%d %d]prop_id[%d]\n",
1647 tbuf_id[1], buf_id[1], property->prop_id);
1648
1649 /*
1650 * command node have event list of destination buffer
1651 * If destination buffer enqueue to mem list,
1652 * then we make event and link to event list tail.
1653 * so, we get first event for first enqueued buffer.
1654 */
1655 e = list_first_entry(&c_node->event_list,
1656 struct drm_exynos_ipp_send_event, base.link);
1657
1658 if (!e) {
1659 DRM_ERROR("empty event.\n");
1660 return -EINVAL;
1661 }
1662
1663 do_gettimeofday(&now);
1664 DRM_DEBUG_KMS("%s:tv_sec[%ld]tv_usec[%ld]\n"
1665 , __func__, now.tv_sec, now.tv_usec);
1666 e->event.tv_sec = now.tv_sec;
1667 e->event.tv_usec = now.tv_usec;
1668 e->event.prop_id = property->prop_id;
1669
1670 /* set buffer id about source destination */
1671 for_each_ipp_ops(i)
1672 e->event.buf_id[i] = tbuf_id[i];
1673
1674 spin_lock_irqsave(&drm_dev->event_lock, flags);
1675 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
1676 wake_up_interruptible(&e->base.file_priv->event_wait);
1677 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
1678
1679 DRM_DEBUG_KMS("%s:done cmd[%d]prop_id[%d]buf_id[%d]\n", __func__,
1680 property->cmd, property->prop_id, tbuf_id[EXYNOS_DRM_OPS_DST]);
1681
1682 return 0;
1683}
1684
1685void ipp_sched_event(struct work_struct *work)
1686{
1687 struct drm_exynos_ipp_event_work *event_work =
1688 (struct drm_exynos_ipp_event_work *)work;
1689 struct exynos_drm_ippdrv *ippdrv;
1690 struct drm_exynos_ipp_cmd_node *c_node;
1691 int ret;
1692
1693 if (!event_work) {
1694 DRM_ERROR("failed to get event_work.\n");
1695 return;
1696 }
1697
1698 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__,
1699 event_work->buf_id[EXYNOS_DRM_OPS_DST]);
1700
1701 ippdrv = event_work->ippdrv;
1702 if (!ippdrv) {
1703 DRM_ERROR("failed to get ipp driver.\n");
1704 return;
1705 }
1706
1707 c_node = ippdrv->cmd;
1708 if (!c_node) {
1709 DRM_ERROR("failed to get command node.\n");
1710 return;
1711 }
1712
1713 /*
1714 * IPP supports command thread, event thread synchronization.
1715 * If IPP close immediately from user land, then IPP make
1716 * synchronization with command thread, so make complete event.
1717 * or going out operations.
1718 */
1719 if (c_node->state != IPP_STATE_START) {
1720 DRM_DEBUG_KMS("%s:bypass state[%d]prop_id[%d]\n",
1721 __func__, c_node->state, c_node->property.prop_id);
1722 goto err_completion;
1723 }
1724
1725 mutex_lock(&c_node->event_lock);
1726
1727 ret = ipp_send_event(ippdrv, c_node, event_work->buf_id);
1728 if (ret) {
1729 DRM_ERROR("failed to send event.\n");
1730 goto err_completion;
1731 }
1732
1733err_completion:
1734 if (ipp_is_m2m_cmd(c_node->property.cmd))
1735 complete(&c_node->start_complete);
1736
1737 mutex_unlock(&c_node->event_lock);
1738}
1739
1740static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
1741{
1742 struct ipp_context *ctx = get_ipp_context(dev);
1743 struct exynos_drm_ippdrv *ippdrv;
1744 int ret, count = 0;
1745
1746 DRM_DEBUG_KMS("%s\n", __func__);
1747
1748 /* get ipp driver entry */
1749 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
1750 ippdrv->drm_dev = drm_dev;
1751
1752 ret = ipp_create_id(&ctx->ipp_idr, &ctx->ipp_lock, ippdrv,
1753 &ippdrv->ipp_id);
1754 if (ret) {
1755 DRM_ERROR("failed to create id.\n");
1756 goto err_idr;
1757 }
1758
1759 DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]ipp_id[%d]\n", __func__,
1760 count++, (int)ippdrv, ippdrv->ipp_id);
1761
1762 if (ippdrv->ipp_id == 0) {
1763 DRM_ERROR("failed to get ipp_id[%d]\n",
1764 ippdrv->ipp_id);
1765 goto err_idr;
1766 }
1767
1768 /* store parent device for node */
1769 ippdrv->parent_dev = dev;
1770
1771 /* store event work queue and handler */
1772 ippdrv->event_workq = ctx->event_workq;
1773 ippdrv->sched_event = ipp_sched_event;
1774 INIT_LIST_HEAD(&ippdrv->cmd_list);
1775
1776 if (is_drm_iommu_supported(drm_dev)) {
1777 ret = drm_iommu_attach_device(drm_dev, ippdrv->dev);
1778 if (ret) {
1779 DRM_ERROR("failed to activate iommu\n");
1780 goto err_iommu;
1781 }
1782 }
1783 }
1784
1785 return 0;
1786
1787err_iommu:
1788 /* get ipp driver entry */
1789 list_for_each_entry_reverse(ippdrv, &exynos_drm_ippdrv_list, drv_list)
1790 if (is_drm_iommu_supported(drm_dev))
1791 drm_iommu_detach_device(drm_dev, ippdrv->dev);
1792
1793err_idr:
1794 idr_remove_all(&ctx->ipp_idr);
1795 idr_remove_all(&ctx->prop_idr);
1796 idr_destroy(&ctx->ipp_idr);
1797 idr_destroy(&ctx->prop_idr);
1798 return ret;
1799}
1800
1801static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
1802{
1803 struct exynos_drm_ippdrv *ippdrv;
1804
1805 DRM_DEBUG_KMS("%s\n", __func__);
1806
1807 /* get ipp driver entry */
1808 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
1809 if (is_drm_iommu_supported(drm_dev))
1810 drm_iommu_detach_device(drm_dev, ippdrv->dev);
1811
1812 ippdrv->drm_dev = NULL;
1813 exynos_drm_ippdrv_unregister(ippdrv);
1814 }
1815}
1816
1817static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
1818 struct drm_file *file)
1819{
1820 struct drm_exynos_file_private *file_priv = file->driver_priv;
1821 struct exynos_drm_ipp_private *priv;
1822
1823 DRM_DEBUG_KMS("%s\n", __func__);
1824
1825 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1826 if (!priv) {
1827 DRM_ERROR("failed to allocate priv.\n");
1828 return -ENOMEM;
1829 }
1830 priv->dev = dev;
1831 file_priv->ipp_priv = priv;
1832
1833 INIT_LIST_HEAD(&priv->event_list);
1834
1835 DRM_DEBUG_KMS("%s:done priv[0x%x]\n", __func__, (int)priv);
1836
1837 return 0;
1838}
1839
1840static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
1841 struct drm_file *file)
1842{
1843 struct drm_exynos_file_private *file_priv = file->driver_priv;
1844 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
1845 struct exynos_drm_ippdrv *ippdrv = NULL;
1846 struct drm_exynos_ipp_cmd_node *c_node, *tc_node;
1847 int count = 0;
1848
1849 DRM_DEBUG_KMS("%s:for priv[0x%x]\n", __func__, (int)priv);
1850
1851 if (list_empty(&exynos_drm_ippdrv_list)) {
1852 DRM_DEBUG_KMS("%s:ippdrv_list is empty.\n", __func__);
1853 goto err_clear;
1854 }
1855
1856 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
1857 if (list_empty(&ippdrv->cmd_list))
1858 continue;
1859
1860 list_for_each_entry_safe(c_node, tc_node,
1861 &ippdrv->cmd_list, list) {
1862 DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]\n",
1863 __func__, count++, (int)ippdrv);
1864
1865 if (c_node->priv == priv) {
1866 /*
1867 * userland goto unnormal state. process killed.
1868 * and close the file.
1869 * so, IPP didn't called stop cmd ctrl.
1870 * so, we are make stop operation in this state.
1871 */
1872 if (c_node->state == IPP_STATE_START) {
1873 ipp_stop_property(drm_dev, ippdrv,
1874 c_node);
1875 c_node->state = IPP_STATE_STOP;
1876 }
1877
1878 ippdrv->dedicated = false;
1879 ipp_clean_cmd_node(c_node);
1880 if (list_empty(&ippdrv->cmd_list))
1881 pm_runtime_put_sync(ippdrv->dev);
1882 }
1883 }
1884 }
1885
1886err_clear:
1887 kfree(priv);
1888 return;
1889}
1890
1891static int __devinit ipp_probe(struct platform_device *pdev)
1892{
1893 struct device *dev = &pdev->dev;
1894 struct ipp_context *ctx;
1895 struct exynos_drm_subdrv *subdrv;
1896 int ret;
1897
1898 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1899 if (!ctx)
1900 return -ENOMEM;
1901
1902 DRM_DEBUG_KMS("%s\n", __func__);
1903
1904 mutex_init(&ctx->ipp_lock);
1905 mutex_init(&ctx->prop_lock);
1906
1907 idr_init(&ctx->ipp_idr);
1908 idr_init(&ctx->prop_idr);
1909
1910 /*
1911 * create single thread for ipp event
1912 * IPP supports event thread for IPP drivers.
1913 * IPP driver send event_work to this thread.
1914 * and IPP event thread send event to user process.
1915 */
1916 ctx->event_workq = create_singlethread_workqueue("ipp_event");
1917 if (!ctx->event_workq) {
1918 dev_err(dev, "failed to create event workqueue\n");
1919 ret = -EINVAL;
1920 goto err_clear;
1921 }
1922
1923 /*
1924 * create single thread for ipp command
1925 * IPP supports command thread for user process.
1926 * user process make command node using set property ioctl.
1927 * and make start_work and send this work to command thread.
1928 * and then this command thread start property.
1929 */
1930 ctx->cmd_workq = create_singlethread_workqueue("ipp_cmd");
1931 if (!ctx->cmd_workq) {
1932 dev_err(dev, "failed to create cmd workqueue\n");
1933 ret = -EINVAL;
1934 goto err_event_workq;
1935 }
1936
1937 /* set sub driver informations */
1938 subdrv = &ctx->subdrv;
1939 subdrv->dev = dev;
1940 subdrv->probe = ipp_subdrv_probe;
1941 subdrv->remove = ipp_subdrv_remove;
1942 subdrv->open = ipp_subdrv_open;
1943 subdrv->close = ipp_subdrv_close;
1944
1945 platform_set_drvdata(pdev, ctx);
1946
1947 ret = exynos_drm_subdrv_register(subdrv);
1948 if (ret < 0) {
1949 DRM_ERROR("failed to register drm ipp device.\n");
1950 goto err_cmd_workq;
1951 }
1952
1953 dev_info(&pdev->dev, "drm ipp registered successfully.\n");
1954
1955 return 0;
1956
1957err_cmd_workq:
1958 destroy_workqueue(ctx->cmd_workq);
1959err_event_workq:
1960 destroy_workqueue(ctx->event_workq);
1961err_clear:
1962 kfree(ctx);
1963 return ret;
1964}
1965
1966static int __devexit ipp_remove(struct platform_device *pdev)
1967{
1968 struct ipp_context *ctx = platform_get_drvdata(pdev);
1969
1970 DRM_DEBUG_KMS("%s\n", __func__);
1971
1972 /* unregister sub driver */
1973 exynos_drm_subdrv_unregister(&ctx->subdrv);
1974
1975 /* remove,destroy ipp idr */
1976 idr_remove_all(&ctx->ipp_idr);
1977 idr_remove_all(&ctx->prop_idr);
1978 idr_destroy(&ctx->ipp_idr);
1979 idr_destroy(&ctx->prop_idr);
1980
1981 mutex_destroy(&ctx->ipp_lock);
1982 mutex_destroy(&ctx->prop_lock);
1983
1984 /* destroy command, event work queue */
1985 destroy_workqueue(ctx->cmd_workq);
1986 destroy_workqueue(ctx->event_workq);
1987
1988 kfree(ctx);
1989
1990 return 0;
1991}
1992
1993static int ipp_power_ctrl(struct ipp_context *ctx, bool enable)
1994{
1995 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
1996
1997 return 0;
1998}
1999
2000#ifdef CONFIG_PM_SLEEP
2001static int ipp_suspend(struct device *dev)
2002{
2003 struct ipp_context *ctx = get_ipp_context(dev);
2004
2005 DRM_DEBUG_KMS("%s\n", __func__);
2006
2007 if (pm_runtime_suspended(dev))
2008 return 0;
2009
2010 return ipp_power_ctrl(ctx, false);
2011}
2012
2013static int ipp_resume(struct device *dev)
2014{
2015 struct ipp_context *ctx = get_ipp_context(dev);
2016
2017 DRM_DEBUG_KMS("%s\n", __func__);
2018
2019 if (!pm_runtime_suspended(dev))
2020 return ipp_power_ctrl(ctx, true);
2021
2022 return 0;
2023}
2024#endif
2025
2026#ifdef CONFIG_PM_RUNTIME
2027static int ipp_runtime_suspend(struct device *dev)
2028{
2029 struct ipp_context *ctx = get_ipp_context(dev);
2030
2031 DRM_DEBUG_KMS("%s\n", __func__);
2032
2033 return ipp_power_ctrl(ctx, false);
2034}
2035
2036static int ipp_runtime_resume(struct device *dev)
2037{
2038 struct ipp_context *ctx = get_ipp_context(dev);
2039
2040 DRM_DEBUG_KMS("%s\n", __func__);
2041
2042 return ipp_power_ctrl(ctx, true);
2043}
2044#endif
2045
2046static const struct dev_pm_ops ipp_pm_ops = {
2047 SET_SYSTEM_SLEEP_PM_OPS(ipp_suspend, ipp_resume)
2048 SET_RUNTIME_PM_OPS(ipp_runtime_suspend, ipp_runtime_resume, NULL)
2049};
2050
2051struct platform_driver ipp_driver = {
2052 .probe = ipp_probe,
2053 .remove = __devexit_p(ipp_remove),
2054 .driver = {
2055 .name = "exynos-drm-ipp",
2056 .owner = THIS_MODULE,
2057 .pm = &ipp_pm_ops,
2058 },
2059};
2060
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
new file mode 100644
index 000000000000..28ffac95386c
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
@@ -0,0 +1,266 @@
1/*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 *
4 * Authors:
5 * Eunchul Kim <chulspro.kim@samsung.com>
6 * Jinyoung Jeon <jy0.jeon@samsung.com>
7 * Sangmin Lee <lsmin.lee@samsung.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29#ifndef _EXYNOS_DRM_IPP_H_
30#define _EXYNOS_DRM_IPP_H_
31
32#define for_each_ipp_ops(pos) \
33 for (pos = 0; pos < EXYNOS_DRM_OPS_MAX; pos++)
34#define for_each_ipp_planar(pos) \
35 for (pos = 0; pos < EXYNOS_DRM_PLANAR_MAX; pos++)
36
37#define IPP_GET_LCD_WIDTH _IOR('F', 302, int)
38#define IPP_GET_LCD_HEIGHT _IOR('F', 303, int)
39#define IPP_SET_WRITEBACK _IOW('F', 304, u32)
40
41/* definition of state */
42enum drm_exynos_ipp_state {
43 IPP_STATE_IDLE,
44 IPP_STATE_START,
45 IPP_STATE_STOP,
46};
47
48/*
49 * A structure of command work information.
50 * @work: work structure.
51 * @ippdrv: current work ippdrv.
52 * @c_node: command node information.
53 * @ctrl: command control.
54 */
55struct drm_exynos_ipp_cmd_work {
56 struct work_struct work;
57 struct exynos_drm_ippdrv *ippdrv;
58 struct drm_exynos_ipp_cmd_node *c_node;
59 enum drm_exynos_ipp_ctrl ctrl;
60};
61
62/*
63 * A structure of command node.
64 *
65 * @priv: IPP private infomation.
66 * @list: list head to command queue information.
67 * @event_list: list head of event.
68 * @mem_list: list head to source,destination memory queue information.
69 * @cmd_lock: lock for synchronization of access to ioctl.
70 * @mem_lock: lock for synchronization of access to memory nodes.
71 * @event_lock: lock for synchronization of access to scheduled event.
72 * @start_complete: completion of start of command.
73 * @stop_complete: completion of stop of command.
74 * @property: property information.
75 * @start_work: start command work structure.
76 * @stop_work: stop command work structure.
77 * @event_work: event work structure.
78 * @state: state of command node.
79 */
80struct drm_exynos_ipp_cmd_node {
81 struct exynos_drm_ipp_private *priv;
82 struct list_head list;
83 struct list_head event_list;
84 struct list_head mem_list[EXYNOS_DRM_OPS_MAX];
85 struct mutex cmd_lock;
86 struct mutex mem_lock;
87 struct mutex event_lock;
88 struct completion start_complete;
89 struct completion stop_complete;
90 struct drm_exynos_ipp_property property;
91 struct drm_exynos_ipp_cmd_work *start_work;
92 struct drm_exynos_ipp_cmd_work *stop_work;
93 struct drm_exynos_ipp_event_work *event_work;
94 enum drm_exynos_ipp_state state;
95};
96
97/*
98 * A structure of buffer information.
99 *
100 * @gem_objs: Y, Cb, Cr each gem object.
101 * @base: Y, Cb, Cr each planar address.
102 */
103struct drm_exynos_ipp_buf_info {
104 unsigned long handles[EXYNOS_DRM_PLANAR_MAX];
105 dma_addr_t base[EXYNOS_DRM_PLANAR_MAX];
106};
107
108/*
109 * A structure of wb setting infomation.
110 *
111 * @enable: enable flag for wb.
112 * @refresh: HZ of the refresh rate.
113 */
114struct drm_exynos_ipp_set_wb {
115 __u32 enable;
116 __u32 refresh;
117};
118
119/*
120 * A structure of event work information.
121 *
122 * @work: work structure.
123 * @ippdrv: current work ippdrv.
124 * @buf_id: id of src, dst buffer.
125 */
126struct drm_exynos_ipp_event_work {
127 struct work_struct work;
128 struct exynos_drm_ippdrv *ippdrv;
129 u32 buf_id[EXYNOS_DRM_OPS_MAX];
130};
131
132/*
133 * A structure of source,destination operations.
134 *
135 * @set_fmt: set format of image.
136 * @set_transf: set transform(rotations, flip).
137 * @set_size: set size of region.
138 * @set_addr: set address for dma.
139 */
140struct exynos_drm_ipp_ops {
141 int (*set_fmt)(struct device *dev, u32 fmt);
142 int (*set_transf)(struct device *dev,
143 enum drm_exynos_degree degree,
144 enum drm_exynos_flip flip, bool *swap);
145 int (*set_size)(struct device *dev, int swap,
146 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz);
147 int (*set_addr)(struct device *dev,
148 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
149 enum drm_exynos_ipp_buf_type buf_type);
150};
151
152/*
153 * A structure of ipp driver.
154 *
155 * @drv_list: list head for registed sub driver information.
156 * @parent_dev: parent device information.
157 * @dev: platform device.
158 * @drm_dev: drm device.
159 * @ipp_id: id of ipp driver.
160 * @dedicated: dedicated ipp device.
161 * @ops: source, destination operations.
162 * @event_workq: event work queue.
163 * @cmd: current command information.
164 * @cmd_list: list head for command information.
165 * @prop_list: property informations of current ipp driver.
166 * @check_property: check property about format, size, buffer.
167 * @reset: reset ipp block.
168 * @start: ipp each device start.
169 * @stop: ipp each device stop.
170 * @sched_event: work schedule handler.
171 */
172struct exynos_drm_ippdrv {
173 struct list_head drv_list;
174 struct device *parent_dev;
175 struct device *dev;
176 struct drm_device *drm_dev;
177 u32 ipp_id;
178 bool dedicated;
179 struct exynos_drm_ipp_ops *ops[EXYNOS_DRM_OPS_MAX];
180 struct workqueue_struct *event_workq;
181 struct drm_exynos_ipp_cmd_node *cmd;
182 struct list_head cmd_list;
183 struct drm_exynos_ipp_prop_list *prop_list;
184
185 int (*check_property)(struct device *dev,
186 struct drm_exynos_ipp_property *property);
187 int (*reset)(struct device *dev);
188 int (*start)(struct device *dev, enum drm_exynos_ipp_cmd cmd);
189 void (*stop)(struct device *dev, enum drm_exynos_ipp_cmd cmd);
190 void (*sched_event)(struct work_struct *work);
191};
192
193#ifdef CONFIG_DRM_EXYNOS_IPP
194extern int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv);
195extern int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv);
196extern int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
197 struct drm_file *file);
198extern int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
199 struct drm_file *file);
200extern int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
201 struct drm_file *file);
202extern int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
203 struct drm_file *file);
204extern int exynos_drm_ippnb_register(struct notifier_block *nb);
205extern int exynos_drm_ippnb_unregister(struct notifier_block *nb);
206extern int exynos_drm_ippnb_send_event(unsigned long val, void *v);
207extern void ipp_sched_cmd(struct work_struct *work);
208extern void ipp_sched_event(struct work_struct *work);
209
210#else
211static inline int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
212{
213 return -ENODEV;
214}
215
216static inline int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
217{
218 return -ENODEV;
219}
220
221static inline int exynos_drm_ipp_get_property(struct drm_device *drm_dev,
222 void *data,
223 struct drm_file *file_priv)
224{
225 return -ENOTTY;
226}
227
228static inline int exynos_drm_ipp_set_property(struct drm_device *drm_dev,
229 void *data,
230 struct drm_file *file_priv)
231{
232 return -ENOTTY;
233}
234
235static inline int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev,
236 void *data,
237 struct drm_file *file)
238{
239 return -ENOTTY;
240}
241
242static inline int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev,
243 void *data,
244 struct drm_file *file)
245{
246 return -ENOTTY;
247}
248
249static inline int exynos_drm_ippnb_register(struct notifier_block *nb)
250{
251 return -ENODEV;
252}
253
254static inline int exynos_drm_ippnb_unregister(struct notifier_block *nb)
255{
256 return -ENODEV;
257}
258
259static inline int exynos_drm_ippnb_send_event(unsigned long val, void *v)
260{
261 return -ENOTTY;
262}
263#endif
264
265#endif /* _EXYNOS_DRM_IPP_H_ */
266
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 862ca1eb2102..83efc662d65a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -40,7 +40,7 @@ static const uint32_t formats[] = {
40 * CRTC ---------------- 40 * CRTC ----------------
41 * ^ start ^ end 41 * ^ start ^ end
42 * 42 *
43 * There are six cases from a to b. 43 * There are six cases from a to f.
44 * 44 *
45 * <----- SCREEN -----> 45 * <----- SCREEN ----->
46 * 0 last 46 * 0 last
@@ -93,11 +93,9 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
93 } 93 }
94 94
95 overlay->dma_addr[i] = buffer->dma_addr; 95 overlay->dma_addr[i] = buffer->dma_addr;
96 overlay->vaddr[i] = buffer->kvaddr;
97 96
98 DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n", 97 DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
99 i, (unsigned long)overlay->vaddr[i], 98 i, (unsigned long)overlay->dma_addr[i]);
100 (unsigned long)overlay->dma_addr[i]);
101 } 99 }
102 100
103 actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay); 101 actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay);
@@ -106,16 +104,12 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
106 if (crtc_x < 0) { 104 if (crtc_x < 0) {
107 if (actual_w) 105 if (actual_w)
108 src_x -= crtc_x; 106 src_x -= crtc_x;
109 else
110 src_x += crtc_w;
111 crtc_x = 0; 107 crtc_x = 0;
112 } 108 }
113 109
114 if (crtc_y < 0) { 110 if (crtc_y < 0) {
115 if (actual_h) 111 if (actual_h)
116 src_y -= crtc_y; 112 src_y -= crtc_y;
117 else
118 src_y += crtc_h;
119 crtc_y = 0; 113 crtc_y = 0;
120 } 114 }
121 115
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
new file mode 100644
index 000000000000..1c2366083c70
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -0,0 +1,855 @@
1/*
2 * Copyright (C) 2012 Samsung Electronics Co.Ltd
3 * Authors:
4 * YoungJun Cho <yj44.cho@samsung.com>
5 * Eunchul Kim <chulspro.kim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundationr
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/err.h>
15#include <linux/interrupt.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18#include <linux/clk.h>
19#include <linux/pm_runtime.h>
20
21#include <drm/drmP.h>
22#include <drm/exynos_drm.h>
23#include "regs-rotator.h"
24#include "exynos_drm.h"
25#include "exynos_drm_ipp.h"
26
27/*
28 * Rotator supports image crop/rotator and input/output DMA operations.
29 * input DMA reads image data from the memory.
30 * output DMA writes image data to memory.
31 *
32 * M2M operation : supports crop/scale/rotation/csc so on.
33 * Memory ----> Rotator H/W ----> Memory.
34 */
35
36/*
37 * TODO
38 * 1. check suspend/resume api if needed.
39 * 2. need to check use case platform_device_id.
40 * 3. check src/dst size with, height.
41 * 4. need to add supported list in prop_list.
42 */
43
44#define get_rot_context(dev) platform_get_drvdata(to_platform_device(dev))
45#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
46 struct rot_context, ippdrv);
47#define rot_read(offset) readl(rot->regs + (offset))
48#define rot_write(cfg, offset) writel(cfg, rot->regs + (offset))
49
50enum rot_irq_status {
51 ROT_IRQ_STATUS_COMPLETE = 8,
52 ROT_IRQ_STATUS_ILLEGAL = 9,
53};
54
55/*
56 * A structure of limitation.
57 *
58 * @min_w: minimum width.
59 * @min_h: minimum height.
60 * @max_w: maximum width.
61 * @max_h: maximum height.
62 * @align: align size.
63 */
64struct rot_limit {
65 u32 min_w;
66 u32 min_h;
67 u32 max_w;
68 u32 max_h;
69 u32 align;
70};
71
72/*
73 * A structure of limitation table.
74 *
75 * @ycbcr420_2p: case of YUV.
76 * @rgb888: case of RGB.
77 */
78struct rot_limit_table {
79 struct rot_limit ycbcr420_2p;
80 struct rot_limit rgb888;
81};
82
83/*
84 * A structure of rotator context.
85 * @ippdrv: prepare initialization using ippdrv.
86 * @regs_res: register resources.
87 * @regs: memory mapped io registers.
88 * @clock: rotator gate clock.
89 * @limit_tbl: limitation of rotator.
90 * @irq: irq number.
91 * @cur_buf_id: current operation buffer id.
92 * @suspended: suspended state.
93 */
94struct rot_context {
95 struct exynos_drm_ippdrv ippdrv;
96 struct resource *regs_res;
97 void __iomem *regs;
98 struct clk *clock;
99 struct rot_limit_table *limit_tbl;
100 int irq;
101 int cur_buf_id[EXYNOS_DRM_OPS_MAX];
102 bool suspended;
103};
104
105static void rotator_reg_set_irq(struct rot_context *rot, bool enable)
106{
107 u32 val = rot_read(ROT_CONFIG);
108
109 if (enable == true)
110 val |= ROT_CONFIG_IRQ;
111 else
112 val &= ~ROT_CONFIG_IRQ;
113
114 rot_write(val, ROT_CONFIG);
115}
116
117static u32 rotator_reg_get_fmt(struct rot_context *rot)
118{
119 u32 val = rot_read(ROT_CONTROL);
120
121 val &= ROT_CONTROL_FMT_MASK;
122
123 return val;
124}
125
126static enum rot_irq_status rotator_reg_get_irq_status(struct rot_context *rot)
127{
128 u32 val = rot_read(ROT_STATUS);
129
130 val = ROT_STATUS_IRQ(val);
131
132 if (val == ROT_STATUS_IRQ_VAL_COMPLETE)
133 return ROT_IRQ_STATUS_COMPLETE;
134
135 return ROT_IRQ_STATUS_ILLEGAL;
136}
137
138static irqreturn_t rotator_irq_handler(int irq, void *arg)
139{
140 struct rot_context *rot = arg;
141 struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
142 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
143 struct drm_exynos_ipp_event_work *event_work = c_node->event_work;
144 enum rot_irq_status irq_status;
145 u32 val;
146
147 /* Get execution result */
148 irq_status = rotator_reg_get_irq_status(rot);
149
150 /* clear status */
151 val = rot_read(ROT_STATUS);
152 val |= ROT_STATUS_IRQ_PENDING((u32)irq_status);
153 rot_write(val, ROT_STATUS);
154
155 if (irq_status == ROT_IRQ_STATUS_COMPLETE) {
156 event_work->ippdrv = ippdrv;
157 event_work->buf_id[EXYNOS_DRM_OPS_DST] =
158 rot->cur_buf_id[EXYNOS_DRM_OPS_DST];
159 queue_work(ippdrv->event_workq,
160 (struct work_struct *)event_work);
161 } else
162 DRM_ERROR("the SFR is set illegally\n");
163
164 return IRQ_HANDLED;
165}
166
167static void rotator_align_size(struct rot_context *rot, u32 fmt, u32 *hsize,
168 u32 *vsize)
169{
170 struct rot_limit_table *limit_tbl = rot->limit_tbl;
171 struct rot_limit *limit;
172 u32 mask, val;
173
174 /* Get size limit */
175 if (fmt == ROT_CONTROL_FMT_RGB888)
176 limit = &limit_tbl->rgb888;
177 else
178 limit = &limit_tbl->ycbcr420_2p;
179
180 /* Get mask for rounding to nearest aligned val */
181 mask = ~((1 << limit->align) - 1);
182
183 /* Set aligned width */
184 val = ROT_ALIGN(*hsize, limit->align, mask);
185 if (val < limit->min_w)
186 *hsize = ROT_MIN(limit->min_w, mask);
187 else if (val > limit->max_w)
188 *hsize = ROT_MAX(limit->max_w, mask);
189 else
190 *hsize = val;
191
192 /* Set aligned height */
193 val = ROT_ALIGN(*vsize, limit->align, mask);
194 if (val < limit->min_h)
195 *vsize = ROT_MIN(limit->min_h, mask);
196 else if (val > limit->max_h)
197 *vsize = ROT_MAX(limit->max_h, mask);
198 else
199 *vsize = val;
200}
201
202static int rotator_src_set_fmt(struct device *dev, u32 fmt)
203{
204 struct rot_context *rot = dev_get_drvdata(dev);
205 u32 val;
206
207 val = rot_read(ROT_CONTROL);
208 val &= ~ROT_CONTROL_FMT_MASK;
209
210 switch (fmt) {
211 case DRM_FORMAT_NV12:
212 val |= ROT_CONTROL_FMT_YCBCR420_2P;
213 break;
214 case DRM_FORMAT_XRGB8888:
215 val |= ROT_CONTROL_FMT_RGB888;
216 break;
217 default:
218 DRM_ERROR("invalid image format\n");
219 return -EINVAL;
220 }
221
222 rot_write(val, ROT_CONTROL);
223
224 return 0;
225}
226
227static inline bool rotator_check_reg_fmt(u32 fmt)
228{
229 if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) ||
230 (fmt == ROT_CONTROL_FMT_RGB888))
231 return true;
232
233 return false;
234}
235
236static int rotator_src_set_size(struct device *dev, int swap,
237 struct drm_exynos_pos *pos,
238 struct drm_exynos_sz *sz)
239{
240 struct rot_context *rot = dev_get_drvdata(dev);
241 u32 fmt, hsize, vsize;
242 u32 val;
243
244 /* Get format */
245 fmt = rotator_reg_get_fmt(rot);
246 if (!rotator_check_reg_fmt(fmt)) {
247 DRM_ERROR("%s:invalid format.\n", __func__);
248 return -EINVAL;
249 }
250
251 /* Align buffer size */
252 hsize = sz->hsize;
253 vsize = sz->vsize;
254 rotator_align_size(rot, fmt, &hsize, &vsize);
255
256 /* Set buffer size configuration */
257 val = ROT_SET_BUF_SIZE_H(vsize) | ROT_SET_BUF_SIZE_W(hsize);
258 rot_write(val, ROT_SRC_BUF_SIZE);
259
260 /* Set crop image position configuration */
261 val = ROT_CROP_POS_Y(pos->y) | ROT_CROP_POS_X(pos->x);
262 rot_write(val, ROT_SRC_CROP_POS);
263 val = ROT_SRC_CROP_SIZE_H(pos->h) | ROT_SRC_CROP_SIZE_W(pos->w);
264 rot_write(val, ROT_SRC_CROP_SIZE);
265
266 return 0;
267}
268
269static int rotator_src_set_addr(struct device *dev,
270 struct drm_exynos_ipp_buf_info *buf_info,
271 u32 buf_id, enum drm_exynos_ipp_buf_type buf_type)
272{
273 struct rot_context *rot = dev_get_drvdata(dev);
274 dma_addr_t addr[EXYNOS_DRM_PLANAR_MAX];
275 u32 val, fmt, hsize, vsize;
276 int i;
277
278 /* Set current buf_id */
279 rot->cur_buf_id[EXYNOS_DRM_OPS_SRC] = buf_id;
280
281 switch (buf_type) {
282 case IPP_BUF_ENQUEUE:
283 /* Set address configuration */
284 for_each_ipp_planar(i)
285 addr[i] = buf_info->base[i];
286
287 /* Get format */
288 fmt = rotator_reg_get_fmt(rot);
289 if (!rotator_check_reg_fmt(fmt)) {
290 DRM_ERROR("%s:invalid format.\n", __func__);
291 return -EINVAL;
292 }
293
294 /* Re-set cb planar for NV12 format */
295 if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) &&
296 !addr[EXYNOS_DRM_PLANAR_CB]) {
297
298 val = rot_read(ROT_SRC_BUF_SIZE);
299 hsize = ROT_GET_BUF_SIZE_W(val);
300 vsize = ROT_GET_BUF_SIZE_H(val);
301
302 /* Set cb planar */
303 addr[EXYNOS_DRM_PLANAR_CB] =
304 addr[EXYNOS_DRM_PLANAR_Y] + hsize * vsize;
305 }
306
307 for_each_ipp_planar(i)
308 rot_write(addr[i], ROT_SRC_BUF_ADDR(i));
309 break;
310 case IPP_BUF_DEQUEUE:
311 for_each_ipp_planar(i)
312 rot_write(0x0, ROT_SRC_BUF_ADDR(i));
313 break;
314 default:
315 /* Nothing to do */
316 break;
317 }
318
319 return 0;
320}
321
322static int rotator_dst_set_transf(struct device *dev,
323 enum drm_exynos_degree degree,
324 enum drm_exynos_flip flip, bool *swap)
325{
326 struct rot_context *rot = dev_get_drvdata(dev);
327 u32 val;
328
329 /* Set transform configuration */
330 val = rot_read(ROT_CONTROL);
331 val &= ~ROT_CONTROL_FLIP_MASK;
332
333 switch (flip) {
334 case EXYNOS_DRM_FLIP_VERTICAL:
335 val |= ROT_CONTROL_FLIP_VERTICAL;
336 break;
337 case EXYNOS_DRM_FLIP_HORIZONTAL:
338 val |= ROT_CONTROL_FLIP_HORIZONTAL;
339 break;
340 default:
341 /* Flip None */
342 break;
343 }
344
345 val &= ~ROT_CONTROL_ROT_MASK;
346
347 switch (degree) {
348 case EXYNOS_DRM_DEGREE_90:
349 val |= ROT_CONTROL_ROT_90;
350 break;
351 case EXYNOS_DRM_DEGREE_180:
352 val |= ROT_CONTROL_ROT_180;
353 break;
354 case EXYNOS_DRM_DEGREE_270:
355 val |= ROT_CONTROL_ROT_270;
356 break;
357 default:
358 /* Rotation 0 Degree */
359 break;
360 }
361
362 rot_write(val, ROT_CONTROL);
363
364 /* Check degree for setting buffer size swap */
365 if ((degree == EXYNOS_DRM_DEGREE_90) ||
366 (degree == EXYNOS_DRM_DEGREE_270))
367 *swap = true;
368 else
369 *swap = false;
370
371 return 0;
372}
373
374static int rotator_dst_set_size(struct device *dev, int swap,
375 struct drm_exynos_pos *pos,
376 struct drm_exynos_sz *sz)
377{
378 struct rot_context *rot = dev_get_drvdata(dev);
379 u32 val, fmt, hsize, vsize;
380
381 /* Get format */
382 fmt = rotator_reg_get_fmt(rot);
383 if (!rotator_check_reg_fmt(fmt)) {
384 DRM_ERROR("%s:invalid format.\n", __func__);
385 return -EINVAL;
386 }
387
388 /* Align buffer size */
389 hsize = sz->hsize;
390 vsize = sz->vsize;
391 rotator_align_size(rot, fmt, &hsize, &vsize);
392
393 /* Set buffer size configuration */
394 val = ROT_SET_BUF_SIZE_H(vsize) | ROT_SET_BUF_SIZE_W(hsize);
395 rot_write(val, ROT_DST_BUF_SIZE);
396
397 /* Set crop image position configuration */
398 val = ROT_CROP_POS_Y(pos->y) | ROT_CROP_POS_X(pos->x);
399 rot_write(val, ROT_DST_CROP_POS);
400
401 return 0;
402}
403
404static int rotator_dst_set_addr(struct device *dev,
405 struct drm_exynos_ipp_buf_info *buf_info,
406 u32 buf_id, enum drm_exynos_ipp_buf_type buf_type)
407{
408 struct rot_context *rot = dev_get_drvdata(dev);
409 dma_addr_t addr[EXYNOS_DRM_PLANAR_MAX];
410 u32 val, fmt, hsize, vsize;
411 int i;
412
413 /* Set current buf_id */
414 rot->cur_buf_id[EXYNOS_DRM_OPS_DST] = buf_id;
415
416 switch (buf_type) {
417 case IPP_BUF_ENQUEUE:
418 /* Set address configuration */
419 for_each_ipp_planar(i)
420 addr[i] = buf_info->base[i];
421
422 /* Get format */
423 fmt = rotator_reg_get_fmt(rot);
424 if (!rotator_check_reg_fmt(fmt)) {
425 DRM_ERROR("%s:invalid format.\n", __func__);
426 return -EINVAL;
427 }
428
429 /* Re-set cb planar for NV12 format */
430 if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) &&
431 !addr[EXYNOS_DRM_PLANAR_CB]) {
432 /* Get buf size */
433 val = rot_read(ROT_DST_BUF_SIZE);
434
435 hsize = ROT_GET_BUF_SIZE_W(val);
436 vsize = ROT_GET_BUF_SIZE_H(val);
437
438 /* Set cb planar */
439 addr[EXYNOS_DRM_PLANAR_CB] =
440 addr[EXYNOS_DRM_PLANAR_Y] + hsize * vsize;
441 }
442
443 for_each_ipp_planar(i)
444 rot_write(addr[i], ROT_DST_BUF_ADDR(i));
445 break;
446 case IPP_BUF_DEQUEUE:
447 for_each_ipp_planar(i)
448 rot_write(0x0, ROT_DST_BUF_ADDR(i));
449 break;
450 default:
451 /* Nothing to do */
452 break;
453 }
454
455 return 0;
456}
457
458static struct exynos_drm_ipp_ops rot_src_ops = {
459 .set_fmt = rotator_src_set_fmt,
460 .set_size = rotator_src_set_size,
461 .set_addr = rotator_src_set_addr,
462};
463
464static struct exynos_drm_ipp_ops rot_dst_ops = {
465 .set_transf = rotator_dst_set_transf,
466 .set_size = rotator_dst_set_size,
467 .set_addr = rotator_dst_set_addr,
468};
469
470static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
471{
472 struct drm_exynos_ipp_prop_list *prop_list;
473
474 DRM_DEBUG_KMS("%s\n", __func__);
475
476 prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
477 if (!prop_list) {
478 DRM_ERROR("failed to alloc property list.\n");
479 return -ENOMEM;
480 }
481
482 prop_list->version = 1;
483 prop_list->flip = (1 << EXYNOS_DRM_FLIP_VERTICAL) |
484 (1 << EXYNOS_DRM_FLIP_HORIZONTAL);
485 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
486 (1 << EXYNOS_DRM_DEGREE_90) |
487 (1 << EXYNOS_DRM_DEGREE_180) |
488 (1 << EXYNOS_DRM_DEGREE_270);
489 prop_list->csc = 0;
490 prop_list->crop = 0;
491 prop_list->scale = 0;
492
493 ippdrv->prop_list = prop_list;
494
495 return 0;
496}
497
498static inline bool rotator_check_drm_fmt(u32 fmt)
499{
500 switch (fmt) {
501 case DRM_FORMAT_XRGB8888:
502 case DRM_FORMAT_NV12:
503 return true;
504 default:
505 DRM_DEBUG_KMS("%s:not support format\n", __func__);
506 return false;
507 }
508}
509
510static inline bool rotator_check_drm_flip(enum drm_exynos_flip flip)
511{
512 switch (flip) {
513 case EXYNOS_DRM_FLIP_NONE:
514 case EXYNOS_DRM_FLIP_VERTICAL:
515 case EXYNOS_DRM_FLIP_HORIZONTAL:
516 return true;
517 default:
518 DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
519 return false;
520 }
521}
522
523static int rotator_ippdrv_check_property(struct device *dev,
524 struct drm_exynos_ipp_property *property)
525{
526 struct drm_exynos_ipp_config *src_config =
527 &property->config[EXYNOS_DRM_OPS_SRC];
528 struct drm_exynos_ipp_config *dst_config =
529 &property->config[EXYNOS_DRM_OPS_DST];
530 struct drm_exynos_pos *src_pos = &src_config->pos;
531 struct drm_exynos_pos *dst_pos = &dst_config->pos;
532 struct drm_exynos_sz *src_sz = &src_config->sz;
533 struct drm_exynos_sz *dst_sz = &dst_config->sz;
534 bool swap = false;
535
536 /* Check format configuration */
537 if (src_config->fmt != dst_config->fmt) {
538 DRM_DEBUG_KMS("%s:not support csc feature\n", __func__);
539 return -EINVAL;
540 }
541
542 if (!rotator_check_drm_fmt(dst_config->fmt)) {
543 DRM_DEBUG_KMS("%s:invalid format\n", __func__);
544 return -EINVAL;
545 }
546
547 /* Check transform configuration */
548 if (src_config->degree != EXYNOS_DRM_DEGREE_0) {
549 DRM_DEBUG_KMS("%s:not support source-side rotation\n",
550 __func__);
551 return -EINVAL;
552 }
553
554 switch (dst_config->degree) {
555 case EXYNOS_DRM_DEGREE_90:
556 case EXYNOS_DRM_DEGREE_270:
557 swap = true;
558 case EXYNOS_DRM_DEGREE_0:
559 case EXYNOS_DRM_DEGREE_180:
560 /* No problem */
561 break;
562 default:
563 DRM_DEBUG_KMS("%s:invalid degree\n", __func__);
564 return -EINVAL;
565 }
566
567 if (src_config->flip != EXYNOS_DRM_FLIP_NONE) {
568 DRM_DEBUG_KMS("%s:not support source-side flip\n", __func__);
569 return -EINVAL;
570 }
571
572 if (!rotator_check_drm_flip(dst_config->flip)) {
573 DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
574 return -EINVAL;
575 }
576
577 /* Check size configuration */
578 if ((src_pos->x + src_pos->w > src_sz->hsize) ||
579 (src_pos->y + src_pos->h > src_sz->vsize)) {
580 DRM_DEBUG_KMS("%s:out of source buffer bound\n", __func__);
581 return -EINVAL;
582 }
583
584 if (swap) {
585 if ((dst_pos->x + dst_pos->h > dst_sz->vsize) ||
586 (dst_pos->y + dst_pos->w > dst_sz->hsize)) {
587 DRM_DEBUG_KMS("%s:out of destination buffer bound\n",
588 __func__);
589 return -EINVAL;
590 }
591
592 if ((src_pos->w != dst_pos->h) || (src_pos->h != dst_pos->w)) {
593 DRM_DEBUG_KMS("%s:not support scale feature\n",
594 __func__);
595 return -EINVAL;
596 }
597 } else {
598 if ((dst_pos->x + dst_pos->w > dst_sz->hsize) ||
599 (dst_pos->y + dst_pos->h > dst_sz->vsize)) {
600 DRM_DEBUG_KMS("%s:out of destination buffer bound\n",
601 __func__);
602 return -EINVAL;
603 }
604
605 if ((src_pos->w != dst_pos->w) || (src_pos->h != dst_pos->h)) {
606 DRM_DEBUG_KMS("%s:not support scale feature\n",
607 __func__);
608 return -EINVAL;
609 }
610 }
611
612 return 0;
613}
614
615static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
616{
617 struct rot_context *rot = dev_get_drvdata(dev);
618 u32 val;
619
620 if (rot->suspended) {
621 DRM_ERROR("suspended state\n");
622 return -EPERM;
623 }
624
625 if (cmd != IPP_CMD_M2M) {
626 DRM_ERROR("not support cmd: %d\n", cmd);
627 return -EINVAL;
628 }
629
630 /* Set interrupt enable */
631 rotator_reg_set_irq(rot, true);
632
633 val = rot_read(ROT_CONTROL);
634 val |= ROT_CONTROL_START;
635
636 rot_write(val, ROT_CONTROL);
637
638 return 0;
639}
640
641static int __devinit rotator_probe(struct platform_device *pdev)
642{
643 struct device *dev = &pdev->dev;
644 struct rot_context *rot;
645 struct exynos_drm_ippdrv *ippdrv;
646 int ret;
647
648 rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL);
649 if (!rot) {
650 dev_err(dev, "failed to allocate rot\n");
651 return -ENOMEM;
652 }
653
654 rot->limit_tbl = (struct rot_limit_table *)
655 platform_get_device_id(pdev)->driver_data;
656
657 rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
658 if (!rot->regs_res) {
659 dev_err(dev, "failed to find registers\n");
660 ret = -ENOENT;
661 goto err_get_resource;
662 }
663
664 rot->regs = devm_request_and_ioremap(dev, rot->regs_res);
665 if (!rot->regs) {
666 dev_err(dev, "failed to map register\n");
667 ret = -ENXIO;
668 goto err_get_resource;
669 }
670
671 rot->irq = platform_get_irq(pdev, 0);
672 if (rot->irq < 0) {
673 dev_err(dev, "failed to get irq\n");
674 ret = rot->irq;
675 goto err_get_irq;
676 }
677
678 ret = request_threaded_irq(rot->irq, NULL, rotator_irq_handler,
679 IRQF_ONESHOT, "drm_rotator", rot);
680 if (ret < 0) {
681 dev_err(dev, "failed to request irq\n");
682 goto err_get_irq;
683 }
684
685 rot->clock = clk_get(dev, "rotator");
686 if (IS_ERR_OR_NULL(rot->clock)) {
687 dev_err(dev, "failed to get clock\n");
688 ret = PTR_ERR(rot->clock);
689 goto err_clk_get;
690 }
691
692 pm_runtime_enable(dev);
693
694 ippdrv = &rot->ippdrv;
695 ippdrv->dev = dev;
696 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &rot_src_ops;
697 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &rot_dst_ops;
698 ippdrv->check_property = rotator_ippdrv_check_property;
699 ippdrv->start = rotator_ippdrv_start;
700 ret = rotator_init_prop_list(ippdrv);
701 if (ret < 0) {
702 dev_err(dev, "failed to init property list.\n");
703 goto err_ippdrv_register;
704 }
705
706 DRM_DEBUG_KMS("%s:ippdrv[0x%x]\n", __func__, (int)ippdrv);
707
708 platform_set_drvdata(pdev, rot);
709
710 ret = exynos_drm_ippdrv_register(ippdrv);
711 if (ret < 0) {
712 dev_err(dev, "failed to register drm rotator device\n");
713 goto err_ippdrv_register;
714 }
715
716 dev_info(dev, "The exynos rotator is probed successfully\n");
717
718 return 0;
719
720err_ippdrv_register:
721 devm_kfree(dev, ippdrv->prop_list);
722 pm_runtime_disable(dev);
723 clk_put(rot->clock);
724err_clk_get:
725 free_irq(rot->irq, rot);
726err_get_irq:
727 devm_iounmap(dev, rot->regs);
728err_get_resource:
729 devm_kfree(dev, rot);
730 return ret;
731}
732
733static int __devexit rotator_remove(struct platform_device *pdev)
734{
735 struct device *dev = &pdev->dev;
736 struct rot_context *rot = dev_get_drvdata(dev);
737 struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
738
739 devm_kfree(dev, ippdrv->prop_list);
740 exynos_drm_ippdrv_unregister(ippdrv);
741
742 pm_runtime_disable(dev);
743 clk_put(rot->clock);
744
745 free_irq(rot->irq, rot);
746 devm_iounmap(dev, rot->regs);
747
748 devm_kfree(dev, rot);
749
750 return 0;
751}
752
753struct rot_limit_table rot_limit_tbl = {
754 .ycbcr420_2p = {
755 .min_w = 32,
756 .min_h = 32,
757 .max_w = SZ_32K,
758 .max_h = SZ_32K,
759 .align = 3,
760 },
761 .rgb888 = {
762 .min_w = 8,
763 .min_h = 8,
764 .max_w = SZ_8K,
765 .max_h = SZ_8K,
766 .align = 2,
767 },
768};
769
770struct platform_device_id rotator_driver_ids[] = {
771 {
772 .name = "exynos-rot",
773 .driver_data = (unsigned long)&rot_limit_tbl,
774 },
775 {},
776};
777
778static int rotator_clk_crtl(struct rot_context *rot, bool enable)
779{
780 DRM_DEBUG_KMS("%s\n", __func__);
781
782 if (enable) {
783 clk_enable(rot->clock);
784 rot->suspended = false;
785 } else {
786 clk_disable(rot->clock);
787 rot->suspended = true;
788 }
789
790 return 0;
791}
792
793
794#ifdef CONFIG_PM_SLEEP
795static int rotator_suspend(struct device *dev)
796{
797 struct rot_context *rot = dev_get_drvdata(dev);
798
799 DRM_DEBUG_KMS("%s\n", __func__);
800
801 if (pm_runtime_suspended(dev))
802 return 0;
803
804 return rotator_clk_crtl(rot, false);
805}
806
807static int rotator_resume(struct device *dev)
808{
809 struct rot_context *rot = dev_get_drvdata(dev);
810
811 DRM_DEBUG_KMS("%s\n", __func__);
812
813 if (!pm_runtime_suspended(dev))
814 return rotator_clk_crtl(rot, true);
815
816 return 0;
817}
818#endif
819
820#ifdef CONFIG_PM_RUNTIME
821static int rotator_runtime_suspend(struct device *dev)
822{
823 struct rot_context *rot = dev_get_drvdata(dev);
824
825 DRM_DEBUG_KMS("%s\n", __func__);
826
827 return rotator_clk_crtl(rot, false);
828}
829
830static int rotator_runtime_resume(struct device *dev)
831{
832 struct rot_context *rot = dev_get_drvdata(dev);
833
834 DRM_DEBUG_KMS("%s\n", __func__);
835
836 return rotator_clk_crtl(rot, true);
837}
838#endif
839
840static const struct dev_pm_ops rotator_pm_ops = {
841 SET_SYSTEM_SLEEP_PM_OPS(rotator_suspend, rotator_resume)
842 SET_RUNTIME_PM_OPS(rotator_runtime_suspend, rotator_runtime_resume,
843 NULL)
844};
845
846struct platform_driver rotator_driver = {
847 .probe = rotator_probe,
848 .remove = __devexit_p(rotator_remove),
849 .id_table = rotator_driver_ids,
850 .driver = {
851 .name = "exynos-rot",
852 .owner = THIS_MODULE,
853 .pm = &rotator_pm_ops,
854 },
855};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.h b/drivers/gpu/drm/exynos/exynos_drm_rotator.h
new file mode 100644
index 000000000000..a2d7a14a52b6
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.h
@@ -0,0 +1,33 @@
1/*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 *
4 * Authors:
5 * YoungJun Cho <yj44.cho@samsung.com>
6 * Eunchul Kim <chulspro.kim@samsung.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#ifndef _EXYNOS_DRM_ROTATOR_H_
29#define _EXYNOS_DRM_ROTATOR_H_
30
31/* TODO */
32
33#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 4b0c16bfd1da..99bfc38dfaa2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -39,7 +39,6 @@ struct vidi_win_data {
39 unsigned int fb_height; 39 unsigned int fb_height;
40 unsigned int bpp; 40 unsigned int bpp;
41 dma_addr_t dma_addr; 41 dma_addr_t dma_addr;
42 void __iomem *vaddr;
43 unsigned int buf_offsize; 42 unsigned int buf_offsize;
44 unsigned int line_size; /* bytes */ 43 unsigned int line_size; /* bytes */
45 bool enabled; 44 bool enabled;
@@ -294,7 +293,6 @@ static void vidi_win_mode_set(struct device *dev,
294 win_data->fb_width = overlay->fb_width; 293 win_data->fb_width = overlay->fb_width;
295 win_data->fb_height = overlay->fb_height; 294 win_data->fb_height = overlay->fb_height;
296 win_data->dma_addr = overlay->dma_addr[0] + offset; 295 win_data->dma_addr = overlay->dma_addr[0] + offset;
297 win_data->vaddr = overlay->vaddr[0] + offset;
298 win_data->bpp = overlay->bpp; 296 win_data->bpp = overlay->bpp;
299 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * 297 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
300 (overlay->bpp >> 3); 298 (overlay->bpp >> 3);
@@ -309,9 +307,7 @@ static void vidi_win_mode_set(struct device *dev,
309 win_data->offset_x, win_data->offset_y); 307 win_data->offset_x, win_data->offset_y);
310 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", 308 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
311 win_data->ovl_width, win_data->ovl_height); 309 win_data->ovl_width, win_data->ovl_height);
312 DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n", 310 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
313 (unsigned long)win_data->dma_addr,
314 (unsigned long)win_data->vaddr);
315 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", 311 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
316 overlay->fb_width, overlay->crtc_width); 312 overlay->fb_width, overlay->crtc_width);
317} 313}
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index bafb65389562..2c46b6c0b82c 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -2003,6 +2003,24 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
2003 mdelay(10); 2003 mdelay(10);
2004} 2004}
2005 2005
2006static void hdmiphy_poweron(struct hdmi_context *hdata)
2007{
2008 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2009
2010 if (hdata->type == HDMI_TYPE14)
2011 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
2012 HDMI_PHY_POWER_OFF_EN);
2013}
2014
2015static void hdmiphy_poweroff(struct hdmi_context *hdata)
2016{
2017 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2018
2019 if (hdata->type == HDMI_TYPE14)
2020 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
2021 HDMI_PHY_POWER_OFF_EN);
2022}
2023
2006static void hdmiphy_conf_apply(struct hdmi_context *hdata) 2024static void hdmiphy_conf_apply(struct hdmi_context *hdata)
2007{ 2025{
2008 const u8 *hdmiphy_data; 2026 const u8 *hdmiphy_data;
@@ -2171,12 +2189,12 @@ static void hdmi_poweron(struct hdmi_context *hdata)
2171 2189
2172 mutex_unlock(&hdata->hdmi_mutex); 2190 mutex_unlock(&hdata->hdmi_mutex);
2173 2191
2174 pm_runtime_get_sync(hdata->dev);
2175
2176 regulator_bulk_enable(res->regul_count, res->regul_bulk); 2192 regulator_bulk_enable(res->regul_count, res->regul_bulk);
2177 clk_enable(res->hdmiphy); 2193 clk_enable(res->hdmiphy);
2178 clk_enable(res->hdmi); 2194 clk_enable(res->hdmi);
2179 clk_enable(res->sclk_hdmi); 2195 clk_enable(res->sclk_hdmi);
2196
2197 hdmiphy_poweron(hdata);
2180} 2198}
2181 2199
2182static void hdmi_poweroff(struct hdmi_context *hdata) 2200static void hdmi_poweroff(struct hdmi_context *hdata)
@@ -2195,14 +2213,13 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
2195 * its reset state seems to meet the condition. 2213 * its reset state seems to meet the condition.
2196 */ 2214 */
2197 hdmiphy_conf_reset(hdata); 2215 hdmiphy_conf_reset(hdata);
2216 hdmiphy_poweroff(hdata);
2198 2217
2199 clk_disable(res->sclk_hdmi); 2218 clk_disable(res->sclk_hdmi);
2200 clk_disable(res->hdmi); 2219 clk_disable(res->hdmi);
2201 clk_disable(res->hdmiphy); 2220 clk_disable(res->hdmiphy);
2202 regulator_bulk_disable(res->regul_count, res->regul_bulk); 2221 regulator_bulk_disable(res->regul_count, res->regul_bulk);
2203 2222
2204 pm_runtime_put_sync(hdata->dev);
2205
2206 mutex_lock(&hdata->hdmi_mutex); 2223 mutex_lock(&hdata->hdmi_mutex);
2207 2224
2208 hdata->powered = false; 2225 hdata->powered = false;
@@ -2215,16 +2232,18 @@ static void hdmi_dpms(void *ctx, int mode)
2215{ 2232{
2216 struct hdmi_context *hdata = ctx; 2233 struct hdmi_context *hdata = ctx;
2217 2234
2218 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 2235 DRM_DEBUG_KMS("[%d] %s mode %d\n", __LINE__, __func__, mode);
2219 2236
2220 switch (mode) { 2237 switch (mode) {
2221 case DRM_MODE_DPMS_ON: 2238 case DRM_MODE_DPMS_ON:
2222 hdmi_poweron(hdata); 2239 if (pm_runtime_suspended(hdata->dev))
2240 pm_runtime_get_sync(hdata->dev);
2223 break; 2241 break;
2224 case DRM_MODE_DPMS_STANDBY: 2242 case DRM_MODE_DPMS_STANDBY:
2225 case DRM_MODE_DPMS_SUSPEND: 2243 case DRM_MODE_DPMS_SUSPEND:
2226 case DRM_MODE_DPMS_OFF: 2244 case DRM_MODE_DPMS_OFF:
2227 hdmi_poweroff(hdata); 2245 if (!pm_runtime_suspended(hdata->dev))
2246 pm_runtime_put_sync(hdata->dev);
2228 break; 2247 break;
2229 default: 2248 default:
2230 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); 2249 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -2421,6 +2440,7 @@ static struct platform_device_id hdmi_driver_types[] = {
2421 } 2440 }
2422}; 2441};
2423 2442
2443#ifdef CONFIG_OF
2424static struct of_device_id hdmi_match_types[] = { 2444static struct of_device_id hdmi_match_types[] = {
2425 { 2445 {
2426 .compatible = "samsung,exynos5-hdmi", 2446 .compatible = "samsung,exynos5-hdmi",
@@ -2429,6 +2449,7 @@ static struct of_device_id hdmi_match_types[] = {
2429 /* end node */ 2449 /* end node */
2430 } 2450 }
2431}; 2451};
2452#endif
2432 2453
2433static int __devinit hdmi_probe(struct platform_device *pdev) 2454static int __devinit hdmi_probe(struct platform_device *pdev)
2434{ 2455{
@@ -2481,6 +2502,8 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
2481 const struct of_device_id *match; 2502 const struct of_device_id *match;
2482 match = of_match_node(of_match_ptr(hdmi_match_types), 2503 match = of_match_node(of_match_ptr(hdmi_match_types),
2483 pdev->dev.of_node); 2504 pdev->dev.of_node);
2505 if (match == NULL)
2506 return -ENODEV;
2484 hdata->type = (enum hdmi_type)match->data; 2507 hdata->type = (enum hdmi_type)match->data;
2485 } else { 2508 } else {
2486 hdata->type = (enum hdmi_type)platform_get_device_id 2509 hdata->type = (enum hdmi_type)platform_get_device_id
@@ -2612,6 +2635,8 @@ static int hdmi_suspend(struct device *dev)
2612 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev); 2635 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2613 struct hdmi_context *hdata = ctx->ctx; 2636 struct hdmi_context *hdata = ctx->ctx;
2614 2637
2638 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2639
2615 disable_irq(hdata->internal_irq); 2640 disable_irq(hdata->internal_irq);
2616 disable_irq(hdata->external_irq); 2641 disable_irq(hdata->external_irq);
2617 2642
@@ -2619,6 +2644,11 @@ static int hdmi_suspend(struct device *dev)
2619 if (ctx->drm_dev) 2644 if (ctx->drm_dev)
2620 drm_helper_hpd_irq_event(ctx->drm_dev); 2645 drm_helper_hpd_irq_event(ctx->drm_dev);
2621 2646
2647 if (pm_runtime_suspended(dev)) {
2648 DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
2649 return 0;
2650 }
2651
2622 hdmi_poweroff(hdata); 2652 hdmi_poweroff(hdata);
2623 2653
2624 return 0; 2654 return 0;
@@ -2629,13 +2659,52 @@ static int hdmi_resume(struct device *dev)
2629 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev); 2659 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2630 struct hdmi_context *hdata = ctx->ctx; 2660 struct hdmi_context *hdata = ctx->ctx;
2631 2661
2662 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2663
2664 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2665
2632 enable_irq(hdata->external_irq); 2666 enable_irq(hdata->external_irq);
2633 enable_irq(hdata->internal_irq); 2667 enable_irq(hdata->internal_irq);
2668
2669 if (!pm_runtime_suspended(dev)) {
2670 DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
2671 return 0;
2672 }
2673
2674 hdmi_poweron(hdata);
2675
2676 return 0;
2677}
2678#endif
2679
2680#ifdef CONFIG_PM_RUNTIME
2681static int hdmi_runtime_suspend(struct device *dev)
2682{
2683 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2684 struct hdmi_context *hdata = ctx->ctx;
2685 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2686
2687 hdmi_poweroff(hdata);
2688
2689 return 0;
2690}
2691
2692static int hdmi_runtime_resume(struct device *dev)
2693{
2694 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2695 struct hdmi_context *hdata = ctx->ctx;
2696 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2697
2698 hdmi_poweron(hdata);
2699
2634 return 0; 2700 return 0;
2635} 2701}
2636#endif 2702#endif
2637 2703
2638static SIMPLE_DEV_PM_OPS(hdmi_pm_ops, hdmi_suspend, hdmi_resume); 2704static const struct dev_pm_ops hdmi_pm_ops = {
2705 SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
2706 SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
2707};
2639 2708
2640struct platform_driver hdmi_driver = { 2709struct platform_driver hdmi_driver = {
2641 .probe = hdmi_probe, 2710 .probe = hdmi_probe,
@@ -2645,6 +2714,6 @@ struct platform_driver hdmi_driver = {
2645 .name = "exynos-hdmi", 2714 .name = "exynos-hdmi",
2646 .owner = THIS_MODULE, 2715 .owner = THIS_MODULE,
2647 .pm = &hdmi_pm_ops, 2716 .pm = &hdmi_pm_ops,
2648 .of_match_table = hdmi_match_types, 2717 .of_match_table = of_match_ptr(hdmi_match_types),
2649 }, 2718 },
2650}; 2719};
diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy.c b/drivers/gpu/drm/exynos/exynos_hdmiphy.c
index 27d1720f1bbd..6206056f4a33 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmiphy.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmiphy.c
@@ -46,6 +46,7 @@ static const struct i2c_device_id hdmiphy_id[] = {
46 { }, 46 { },
47}; 47};
48 48
49#ifdef CONFIG_OF
49static struct of_device_id hdmiphy_match_types[] = { 50static struct of_device_id hdmiphy_match_types[] = {
50 { 51 {
51 .compatible = "samsung,exynos5-hdmiphy", 52 .compatible = "samsung,exynos5-hdmiphy",
@@ -53,12 +54,13 @@ static struct of_device_id hdmiphy_match_types[] = {
53 /* end node */ 54 /* end node */
54 } 55 }
55}; 56};
57#endif
56 58
57struct i2c_driver hdmiphy_driver = { 59struct i2c_driver hdmiphy_driver = {
58 .driver = { 60 .driver = {
59 .name = "exynos-hdmiphy", 61 .name = "exynos-hdmiphy",
60 .owner = THIS_MODULE, 62 .owner = THIS_MODULE,
61 .of_match_table = hdmiphy_match_types, 63 .of_match_table = of_match_ptr(hdmiphy_match_types),
62 }, 64 },
63 .id_table = hdmiphy_id, 65 .id_table = hdmiphy_id,
64 .probe = hdmiphy_probe, 66 .probe = hdmiphy_probe,
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 40a6e1906fbb..21db89530fc7 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -42,9 +42,7 @@
42 42
43struct hdmi_win_data { 43struct hdmi_win_data {
44 dma_addr_t dma_addr; 44 dma_addr_t dma_addr;
45 void __iomem *vaddr;
46 dma_addr_t chroma_dma_addr; 45 dma_addr_t chroma_dma_addr;
47 void __iomem *chroma_vaddr;
48 uint32_t pixel_format; 46 uint32_t pixel_format;
49 unsigned int bpp; 47 unsigned int bpp;
50 unsigned int crtc_x; 48 unsigned int crtc_x;
@@ -60,6 +58,8 @@ struct hdmi_win_data {
60 unsigned int mode_width; 58 unsigned int mode_width;
61 unsigned int mode_height; 59 unsigned int mode_height;
62 unsigned int scan_flags; 60 unsigned int scan_flags;
61 bool enabled;
62 bool resume;
63}; 63};
64 64
65struct mixer_resources { 65struct mixer_resources {
@@ -93,6 +93,8 @@ struct mixer_context {
93 struct hdmi_win_data win_data[MIXER_WIN_NR]; 93 struct hdmi_win_data win_data[MIXER_WIN_NR];
94 enum mixer_version_id mxr_ver; 94 enum mixer_version_id mxr_ver;
95 void *parent_ctx; 95 void *parent_ctx;
96 wait_queue_head_t wait_vsync_queue;
97 atomic_t wait_vsync_event;
96}; 98};
97 99
98struct mixer_drv_data { 100struct mixer_drv_data {
@@ -686,60 +688,6 @@ static int mixer_iommu_on(void *ctx, bool enable)
686 return 0; 688 return 0;
687} 689}
688 690
689static void mixer_poweron(struct mixer_context *ctx)
690{
691 struct mixer_resources *res = &ctx->mixer_res;
692
693 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
694
695 mutex_lock(&ctx->mixer_mutex);
696 if (ctx->powered) {
697 mutex_unlock(&ctx->mixer_mutex);
698 return;
699 }
700 ctx->powered = true;
701 mutex_unlock(&ctx->mixer_mutex);
702
703 pm_runtime_get_sync(ctx->dev);
704
705 clk_enable(res->mixer);
706 if (ctx->vp_enabled) {
707 clk_enable(res->vp);
708 clk_enable(res->sclk_mixer);
709 }
710
711 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
712 mixer_win_reset(ctx);
713}
714
715static void mixer_poweroff(struct mixer_context *ctx)
716{
717 struct mixer_resources *res = &ctx->mixer_res;
718
719 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
720
721 mutex_lock(&ctx->mixer_mutex);
722 if (!ctx->powered)
723 goto out;
724 mutex_unlock(&ctx->mixer_mutex);
725
726 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
727
728 clk_disable(res->mixer);
729 if (ctx->vp_enabled) {
730 clk_disable(res->vp);
731 clk_disable(res->sclk_mixer);
732 }
733
734 pm_runtime_put_sync(ctx->dev);
735
736 mutex_lock(&ctx->mixer_mutex);
737 ctx->powered = false;
738
739out:
740 mutex_unlock(&ctx->mixer_mutex);
741}
742
743static int mixer_enable_vblank(void *ctx, int pipe) 691static int mixer_enable_vblank(void *ctx, int pipe)
744{ 692{
745 struct mixer_context *mixer_ctx = ctx; 693 struct mixer_context *mixer_ctx = ctx;
@@ -767,39 +715,6 @@ static void mixer_disable_vblank(void *ctx)
767 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); 715 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
768} 716}
769 717
770static void mixer_dpms(void *ctx, int mode)
771{
772 struct mixer_context *mixer_ctx = ctx;
773
774 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
775
776 switch (mode) {
777 case DRM_MODE_DPMS_ON:
778 mixer_poweron(mixer_ctx);
779 break;
780 case DRM_MODE_DPMS_STANDBY:
781 case DRM_MODE_DPMS_SUSPEND:
782 case DRM_MODE_DPMS_OFF:
783 mixer_poweroff(mixer_ctx);
784 break;
785 default:
786 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
787 break;
788 }
789}
790
791static void mixer_wait_for_vblank(void *ctx)
792{
793 struct mixer_context *mixer_ctx = ctx;
794 struct mixer_resources *res = &mixer_ctx->mixer_res;
795 int ret;
796
797 ret = wait_for((mixer_reg_read(res, MXR_INT_STATUS) &
798 MXR_INT_STATUS_VSYNC), 50);
799 if (ret < 0)
800 DRM_DEBUG_KMS("vblank wait timed out.\n");
801}
802
803static void mixer_win_mode_set(void *ctx, 718static void mixer_win_mode_set(void *ctx,
804 struct exynos_drm_overlay *overlay) 719 struct exynos_drm_overlay *overlay)
805{ 720{
@@ -832,9 +747,7 @@ static void mixer_win_mode_set(void *ctx,
832 win_data = &mixer_ctx->win_data[win]; 747 win_data = &mixer_ctx->win_data[win];
833 748
834 win_data->dma_addr = overlay->dma_addr[0]; 749 win_data->dma_addr = overlay->dma_addr[0];
835 win_data->vaddr = overlay->vaddr[0];
836 win_data->chroma_dma_addr = overlay->dma_addr[1]; 750 win_data->chroma_dma_addr = overlay->dma_addr[1];
837 win_data->chroma_vaddr = overlay->vaddr[1];
838 win_data->pixel_format = overlay->pixel_format; 751 win_data->pixel_format = overlay->pixel_format;
839 win_data->bpp = overlay->bpp; 752 win_data->bpp = overlay->bpp;
840 753
@@ -866,6 +779,8 @@ static void mixer_win_commit(void *ctx, int win)
866 vp_video_buffer(mixer_ctx, win); 779 vp_video_buffer(mixer_ctx, win);
867 else 780 else
868 mixer_graph_buffer(mixer_ctx, win); 781 mixer_graph_buffer(mixer_ctx, win);
782
783 mixer_ctx->win_data[win].enabled = true;
869} 784}
870 785
871static void mixer_win_disable(void *ctx, int win) 786static void mixer_win_disable(void *ctx, int win)
@@ -876,6 +791,14 @@ static void mixer_win_disable(void *ctx, int win)
876 791
877 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); 792 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
878 793
794 mutex_lock(&mixer_ctx->mixer_mutex);
795 if (!mixer_ctx->powered) {
796 mutex_unlock(&mixer_ctx->mixer_mutex);
797 mixer_ctx->win_data[win].resume = false;
798 return;
799 }
800 mutex_unlock(&mixer_ctx->mixer_mutex);
801
879 spin_lock_irqsave(&res->reg_slock, flags); 802 spin_lock_irqsave(&res->reg_slock, flags);
880 mixer_vsync_set_update(mixer_ctx, false); 803 mixer_vsync_set_update(mixer_ctx, false);
881 804
@@ -883,6 +806,133 @@ static void mixer_win_disable(void *ctx, int win)
883 806
884 mixer_vsync_set_update(mixer_ctx, true); 807 mixer_vsync_set_update(mixer_ctx, true);
885 spin_unlock_irqrestore(&res->reg_slock, flags); 808 spin_unlock_irqrestore(&res->reg_slock, flags);
809
810 mixer_ctx->win_data[win].enabled = false;
811}
812
813static void mixer_wait_for_vblank(void *ctx)
814{
815 struct mixer_context *mixer_ctx = ctx;
816
817 mutex_lock(&mixer_ctx->mixer_mutex);
818 if (!mixer_ctx->powered) {
819 mutex_unlock(&mixer_ctx->mixer_mutex);
820 return;
821 }
822 mutex_unlock(&mixer_ctx->mixer_mutex);
823
824 atomic_set(&mixer_ctx->wait_vsync_event, 1);
825
826 /*
827 * wait for MIXER to signal VSYNC interrupt or return after
828 * timeout which is set to 50ms (refresh rate of 20).
829 */
830 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
831 !atomic_read(&mixer_ctx->wait_vsync_event),
832 DRM_HZ/20))
833 DRM_DEBUG_KMS("vblank wait timed out.\n");
834}
835
836static void mixer_window_suspend(struct mixer_context *ctx)
837{
838 struct hdmi_win_data *win_data;
839 int i;
840
841 for (i = 0; i < MIXER_WIN_NR; i++) {
842 win_data = &ctx->win_data[i];
843 win_data->resume = win_data->enabled;
844 mixer_win_disable(ctx, i);
845 }
846 mixer_wait_for_vblank(ctx);
847}
848
849static void mixer_window_resume(struct mixer_context *ctx)
850{
851 struct hdmi_win_data *win_data;
852 int i;
853
854 for (i = 0; i < MIXER_WIN_NR; i++) {
855 win_data = &ctx->win_data[i];
856 win_data->enabled = win_data->resume;
857 win_data->resume = false;
858 }
859}
860
861static void mixer_poweron(struct mixer_context *ctx)
862{
863 struct mixer_resources *res = &ctx->mixer_res;
864
865 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
866
867 mutex_lock(&ctx->mixer_mutex);
868 if (ctx->powered) {
869 mutex_unlock(&ctx->mixer_mutex);
870 return;
871 }
872 ctx->powered = true;
873 mutex_unlock(&ctx->mixer_mutex);
874
875 clk_enable(res->mixer);
876 if (ctx->vp_enabled) {
877 clk_enable(res->vp);
878 clk_enable(res->sclk_mixer);
879 }
880
881 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
882 mixer_win_reset(ctx);
883
884 mixer_window_resume(ctx);
885}
886
887static void mixer_poweroff(struct mixer_context *ctx)
888{
889 struct mixer_resources *res = &ctx->mixer_res;
890
891 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
892
893 mutex_lock(&ctx->mixer_mutex);
894 if (!ctx->powered)
895 goto out;
896 mutex_unlock(&ctx->mixer_mutex);
897
898 mixer_window_suspend(ctx);
899
900 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
901
902 clk_disable(res->mixer);
903 if (ctx->vp_enabled) {
904 clk_disable(res->vp);
905 clk_disable(res->sclk_mixer);
906 }
907
908 mutex_lock(&ctx->mixer_mutex);
909 ctx->powered = false;
910
911out:
912 mutex_unlock(&ctx->mixer_mutex);
913}
914
915static void mixer_dpms(void *ctx, int mode)
916{
917 struct mixer_context *mixer_ctx = ctx;
918
919 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
920
921 switch (mode) {
922 case DRM_MODE_DPMS_ON:
923 if (pm_runtime_suspended(mixer_ctx->dev))
924 pm_runtime_get_sync(mixer_ctx->dev);
925 break;
926 case DRM_MODE_DPMS_STANDBY:
927 case DRM_MODE_DPMS_SUSPEND:
928 case DRM_MODE_DPMS_OFF:
929 if (!pm_runtime_suspended(mixer_ctx->dev))
930 pm_runtime_put_sync(mixer_ctx->dev);
931 break;
932 default:
933 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
934 break;
935 }
886} 936}
887 937
888static struct exynos_mixer_ops mixer_ops = { 938static struct exynos_mixer_ops mixer_ops = {
@@ -890,10 +940,10 @@ static struct exynos_mixer_ops mixer_ops = {
890 .iommu_on = mixer_iommu_on, 940 .iommu_on = mixer_iommu_on,
891 .enable_vblank = mixer_enable_vblank, 941 .enable_vblank = mixer_enable_vblank,
892 .disable_vblank = mixer_disable_vblank, 942 .disable_vblank = mixer_disable_vblank,
943 .wait_for_vblank = mixer_wait_for_vblank,
893 .dpms = mixer_dpms, 944 .dpms = mixer_dpms,
894 945
895 /* overlay */ 946 /* overlay */
896 .wait_for_vblank = mixer_wait_for_vblank,
897 .win_mode_set = mixer_win_mode_set, 947 .win_mode_set = mixer_win_mode_set,
898 .win_commit = mixer_win_commit, 948 .win_commit = mixer_win_commit,
899 .win_disable = mixer_win_disable, 949 .win_disable = mixer_win_disable,
@@ -957,6 +1007,12 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
957 1007
958 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe); 1008 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
959 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe); 1009 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
1010
1011 /* set wait vsync event to zero and wake up queue. */
1012 if (atomic_read(&ctx->wait_vsync_event)) {
1013 atomic_set(&ctx->wait_vsync_event, 0);
1014 DRM_WAKEUP(&ctx->wait_vsync_queue);
1015 }
960 } 1016 }
961 1017
962out: 1018out:
@@ -1139,6 +1195,8 @@ static int __devinit mixer_probe(struct platform_device *pdev)
1139 drm_hdmi_ctx->ctx = (void *)ctx; 1195 drm_hdmi_ctx->ctx = (void *)ctx;
1140 ctx->vp_enabled = drv->is_vp_enabled; 1196 ctx->vp_enabled = drv->is_vp_enabled;
1141 ctx->mxr_ver = drv->version; 1197 ctx->mxr_ver = drv->version;
1198 DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
1199 atomic_set(&ctx->wait_vsync_event, 0);
1142 1200
1143 platform_set_drvdata(pdev, drm_hdmi_ctx); 1201 platform_set_drvdata(pdev, drm_hdmi_ctx);
1144 1202
@@ -1189,13 +1247,66 @@ static int mixer_suspend(struct device *dev)
1189 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev); 1247 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1190 struct mixer_context *ctx = drm_hdmi_ctx->ctx; 1248 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1191 1249
1250 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1251
1252 if (pm_runtime_suspended(dev)) {
1253 DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
1254 return 0;
1255 }
1256
1192 mixer_poweroff(ctx); 1257 mixer_poweroff(ctx);
1193 1258
1194 return 0; 1259 return 0;
1195} 1260}
1261
1262static int mixer_resume(struct device *dev)
1263{
1264 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1265 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1266
1267 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1268
1269 if (!pm_runtime_suspended(dev)) {
1270 DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
1271 return 0;
1272 }
1273
1274 mixer_poweron(ctx);
1275
1276 return 0;
1277}
1196#endif 1278#endif
1197 1279
1198static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL); 1280#ifdef CONFIG_PM_RUNTIME
1281static int mixer_runtime_suspend(struct device *dev)
1282{
1283 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1284 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1285
1286 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1287
1288 mixer_poweroff(ctx);
1289
1290 return 0;
1291}
1292
1293static int mixer_runtime_resume(struct device *dev)
1294{
1295 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1296 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1297
1298 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1299
1300 mixer_poweron(ctx);
1301
1302 return 0;
1303}
1304#endif
1305
1306static const struct dev_pm_ops mixer_pm_ops = {
1307 SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
1308 SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
1309};
1199 1310
1200struct platform_driver mixer_driver = { 1311struct platform_driver mixer_driver = {
1201 .driver = { 1312 .driver = {
diff --git a/drivers/gpu/drm/exynos/regs-fimc.h b/drivers/gpu/drm/exynos/regs-fimc.h
new file mode 100644
index 000000000000..b4f9ca1fd851
--- /dev/null
+++ b/drivers/gpu/drm/exynos/regs-fimc.h
@@ -0,0 +1,669 @@
1/* drivers/gpu/drm/exynos/regs-fimc.h
2 *
3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Register definition file for Samsung Camera Interface (FIMC) driver
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef EXYNOS_REGS_FIMC_H
14#define EXYNOS_REGS_FIMC_H
15
16/*
17 * Register part
18*/
19/* Input source format */
20#define EXYNOS_CISRCFMT (0x00)
21/* Window offset */
22#define EXYNOS_CIWDOFST (0x04)
23/* Global control */
24#define EXYNOS_CIGCTRL (0x08)
25/* Window offset 2 */
26#define EXYNOS_CIWDOFST2 (0x14)
27/* Y 1st frame start address for output DMA */
28#define EXYNOS_CIOYSA1 (0x18)
29/* Y 2nd frame start address for output DMA */
30#define EXYNOS_CIOYSA2 (0x1c)
31/* Y 3rd frame start address for output DMA */
32#define EXYNOS_CIOYSA3 (0x20)
33/* Y 4th frame start address for output DMA */
34#define EXYNOS_CIOYSA4 (0x24)
35/* Cb 1st frame start address for output DMA */
36#define EXYNOS_CIOCBSA1 (0x28)
37/* Cb 2nd frame start address for output DMA */
38#define EXYNOS_CIOCBSA2 (0x2c)
39/* Cb 3rd frame start address for output DMA */
40#define EXYNOS_CIOCBSA3 (0x30)
41/* Cb 4th frame start address for output DMA */
42#define EXYNOS_CIOCBSA4 (0x34)
43/* Cr 1st frame start address for output DMA */
44#define EXYNOS_CIOCRSA1 (0x38)
45/* Cr 2nd frame start address for output DMA */
46#define EXYNOS_CIOCRSA2 (0x3c)
47/* Cr 3rd frame start address for output DMA */
48#define EXYNOS_CIOCRSA3 (0x40)
49/* Cr 4th frame start address for output DMA */
50#define EXYNOS_CIOCRSA4 (0x44)
51/* Target image format */
52#define EXYNOS_CITRGFMT (0x48)
53/* Output DMA control */
54#define EXYNOS_CIOCTRL (0x4c)
55/* Pre-scaler control 1 */
56#define EXYNOS_CISCPRERATIO (0x50)
57/* Pre-scaler control 2 */
58#define EXYNOS_CISCPREDST (0x54)
59/* Main scaler control */
60#define EXYNOS_CISCCTRL (0x58)
61/* Target area */
62#define EXYNOS_CITAREA (0x5c)
63/* Status */
64#define EXYNOS_CISTATUS (0x64)
65/* Status2 */
66#define EXYNOS_CISTATUS2 (0x68)
67/* Image capture enable command */
68#define EXYNOS_CIIMGCPT (0xc0)
69/* Capture sequence */
70#define EXYNOS_CICPTSEQ (0xc4)
71/* Image effects */
72#define EXYNOS_CIIMGEFF (0xd0)
73/* Y frame start address for input DMA */
74#define EXYNOS_CIIYSA0 (0xd4)
75/* Cb frame start address for input DMA */
76#define EXYNOS_CIICBSA0 (0xd8)
77/* Cr frame start address for input DMA */
78#define EXYNOS_CIICRSA0 (0xdc)
79/* Input DMA Y Line Skip */
80#define EXYNOS_CIILINESKIP_Y (0xec)
81/* Input DMA Cb Line Skip */
82#define EXYNOS_CIILINESKIP_CB (0xf0)
83/* Input DMA Cr Line Skip */
84#define EXYNOS_CIILINESKIP_CR (0xf4)
85/* Real input DMA image size */
86#define EXYNOS_CIREAL_ISIZE (0xf8)
87/* Input DMA control */
88#define EXYNOS_MSCTRL (0xfc)
89/* Y frame start address for input DMA */
90#define EXYNOS_CIIYSA1 (0x144)
91/* Cb frame start address for input DMA */
92#define EXYNOS_CIICBSA1 (0x148)
93/* Cr frame start address for input DMA */
94#define EXYNOS_CIICRSA1 (0x14c)
95/* Output DMA Y offset */
96#define EXYNOS_CIOYOFF (0x168)
97/* Output DMA CB offset */
98#define EXYNOS_CIOCBOFF (0x16c)
99/* Output DMA CR offset */
100#define EXYNOS_CIOCROFF (0x170)
101/* Input DMA Y offset */
102#define EXYNOS_CIIYOFF (0x174)
103/* Input DMA CB offset */
104#define EXYNOS_CIICBOFF (0x178)
105/* Input DMA CR offset */
106#define EXYNOS_CIICROFF (0x17c)
107/* Input DMA original image size */
108#define EXYNOS_ORGISIZE (0x180)
109/* Output DMA original image size */
110#define EXYNOS_ORGOSIZE (0x184)
111/* Real output DMA image size */
112#define EXYNOS_CIEXTEN (0x188)
113/* DMA parameter */
114#define EXYNOS_CIDMAPARAM (0x18c)
115/* MIPI CSI image format */
116#define EXYNOS_CSIIMGFMT (0x194)
117/* FIMC Clock Source Select */
118#define EXYNOS_MISC_FIMC (0x198)
119
120/* Add for FIMC v5.1 */
121/* Output Frame Buffer Sequence */
122#define EXYNOS_CIFCNTSEQ (0x1fc)
123/* Y 5th frame start address for output DMA */
124#define EXYNOS_CIOYSA5 (0x200)
125/* Y 6th frame start address for output DMA */
126#define EXYNOS_CIOYSA6 (0x204)
127/* Y 7th frame start address for output DMA */
128#define EXYNOS_CIOYSA7 (0x208)
129/* Y 8th frame start address for output DMA */
130#define EXYNOS_CIOYSA8 (0x20c)
131/* Y 9th frame start address for output DMA */
132#define EXYNOS_CIOYSA9 (0x210)
133/* Y 10th frame start address for output DMA */
134#define EXYNOS_CIOYSA10 (0x214)
135/* Y 11th frame start address for output DMA */
136#define EXYNOS_CIOYSA11 (0x218)
137/* Y 12th frame start address for output DMA */
138#define EXYNOS_CIOYSA12 (0x21c)
139/* Y 13th frame start address for output DMA */
140#define EXYNOS_CIOYSA13 (0x220)
141/* Y 14th frame start address for output DMA */
142#define EXYNOS_CIOYSA14 (0x224)
143/* Y 15th frame start address for output DMA */
144#define EXYNOS_CIOYSA15 (0x228)
145/* Y 16th frame start address for output DMA */
146#define EXYNOS_CIOYSA16 (0x22c)
147/* Y 17th frame start address for output DMA */
148#define EXYNOS_CIOYSA17 (0x230)
149/* Y 18th frame start address for output DMA */
150#define EXYNOS_CIOYSA18 (0x234)
151/* Y 19th frame start address for output DMA */
152#define EXYNOS_CIOYSA19 (0x238)
153/* Y 20th frame start address for output DMA */
154#define EXYNOS_CIOYSA20 (0x23c)
155/* Y 21th frame start address for output DMA */
156#define EXYNOS_CIOYSA21 (0x240)
157/* Y 22th frame start address for output DMA */
158#define EXYNOS_CIOYSA22 (0x244)
159/* Y 23th frame start address for output DMA */
160#define EXYNOS_CIOYSA23 (0x248)
161/* Y 24th frame start address for output DMA */
162#define EXYNOS_CIOYSA24 (0x24c)
163/* Y 25th frame start address for output DMA */
164#define EXYNOS_CIOYSA25 (0x250)
165/* Y 26th frame start address for output DMA */
166#define EXYNOS_CIOYSA26 (0x254)
167/* Y 27th frame start address for output DMA */
168#define EXYNOS_CIOYSA27 (0x258)
169/* Y 28th frame start address for output DMA */
170#define EXYNOS_CIOYSA28 (0x25c)
171/* Y 29th frame start address for output DMA */
172#define EXYNOS_CIOYSA29 (0x260)
173/* Y 30th frame start address for output DMA */
174#define EXYNOS_CIOYSA30 (0x264)
175/* Y 31th frame start address for output DMA */
176#define EXYNOS_CIOYSA31 (0x268)
177/* Y 32th frame start address for output DMA */
178#define EXYNOS_CIOYSA32 (0x26c)
179
180/* CB 5th frame start address for output DMA */
181#define EXYNOS_CIOCBSA5 (0x270)
182/* CB 6th frame start address for output DMA */
183#define EXYNOS_CIOCBSA6 (0x274)
184/* CB 7th frame start address for output DMA */
185#define EXYNOS_CIOCBSA7 (0x278)
186/* CB 8th frame start address for output DMA */
187#define EXYNOS_CIOCBSA8 (0x27c)
188/* CB 9th frame start address for output DMA */
189#define EXYNOS_CIOCBSA9 (0x280)
190/* CB 10th frame start address for output DMA */
191#define EXYNOS_CIOCBSA10 (0x284)
192/* CB 11th frame start address for output DMA */
193#define EXYNOS_CIOCBSA11 (0x288)
194/* CB 12th frame start address for output DMA */
195#define EXYNOS_CIOCBSA12 (0x28c)
196/* CB 13th frame start address for output DMA */
197#define EXYNOS_CIOCBSA13 (0x290)
198/* CB 14th frame start address for output DMA */
199#define EXYNOS_CIOCBSA14 (0x294)
200/* CB 15th frame start address for output DMA */
201#define EXYNOS_CIOCBSA15 (0x298)
202/* CB 16th frame start address for output DMA */
203#define EXYNOS_CIOCBSA16 (0x29c)
204/* CB 17th frame start address for output DMA */
205#define EXYNOS_CIOCBSA17 (0x2a0)
206/* CB 18th frame start address for output DMA */
207#define EXYNOS_CIOCBSA18 (0x2a4)
208/* CB 19th frame start address for output DMA */
209#define EXYNOS_CIOCBSA19 (0x2a8)
210/* CB 20th frame start address for output DMA */
211#define EXYNOS_CIOCBSA20 (0x2ac)
212/* CB 21th frame start address for output DMA */
213#define EXYNOS_CIOCBSA21 (0x2b0)
214/* CB 22th frame start address for output DMA */
215#define EXYNOS_CIOCBSA22 (0x2b4)
216/* CB 23th frame start address for output DMA */
217#define EXYNOS_CIOCBSA23 (0x2b8)
218/* CB 24th frame start address for output DMA */
219#define EXYNOS_CIOCBSA24 (0x2bc)
220/* CB 25th frame start address for output DMA */
221#define EXYNOS_CIOCBSA25 (0x2c0)
222/* CB 26th frame start address for output DMA */
223#define EXYNOS_CIOCBSA26 (0x2c4)
224/* CB 27th frame start address for output DMA */
225#define EXYNOS_CIOCBSA27 (0x2c8)
226/* CB 28th frame start address for output DMA */
227#define EXYNOS_CIOCBSA28 (0x2cc)
228/* CB 29th frame start address for output DMA */
229#define EXYNOS_CIOCBSA29 (0x2d0)
230/* CB 30th frame start address for output DMA */
231#define EXYNOS_CIOCBSA30 (0x2d4)
232/* CB 31th frame start address for output DMA */
233#define EXYNOS_CIOCBSA31 (0x2d8)
234/* CB 32th frame start address for output DMA */
235#define EXYNOS_CIOCBSA32 (0x2dc)
236
237/* CR 5th frame start address for output DMA */
238#define EXYNOS_CIOCRSA5 (0x2e0)
239/* CR 6th frame start address for output DMA */
240#define EXYNOS_CIOCRSA6 (0x2e4)
241/* CR 7th frame start address for output DMA */
242#define EXYNOS_CIOCRSA7 (0x2e8)
243/* CR 8th frame start address for output DMA */
244#define EXYNOS_CIOCRSA8 (0x2ec)
245/* CR 9th frame start address for output DMA */
246#define EXYNOS_CIOCRSA9 (0x2f0)
247/* CR 10th frame start address for output DMA */
248#define EXYNOS_CIOCRSA10 (0x2f4)
249/* CR 11th frame start address for output DMA */
250#define EXYNOS_CIOCRSA11 (0x2f8)
251/* CR 12th frame start address for output DMA */
252#define EXYNOS_CIOCRSA12 (0x2fc)
253/* CR 13th frame start address for output DMA */
254#define EXYNOS_CIOCRSA13 (0x300)
255/* CR 14th frame start address for output DMA */
256#define EXYNOS_CIOCRSA14 (0x304)
257/* CR 15th frame start address for output DMA */
258#define EXYNOS_CIOCRSA15 (0x308)
259/* CR 16th frame start address for output DMA */
260#define EXYNOS_CIOCRSA16 (0x30c)
261/* CR 17th frame start address for output DMA */
262#define EXYNOS_CIOCRSA17 (0x310)
263/* CR 18th frame start address for output DMA */
264#define EXYNOS_CIOCRSA18 (0x314)
265/* CR 19th frame start address for output DMA */
266#define EXYNOS_CIOCRSA19 (0x318)
267/* CR 20th frame start address for output DMA */
268#define EXYNOS_CIOCRSA20 (0x31c)
269/* CR 21th frame start address for output DMA */
270#define EXYNOS_CIOCRSA21 (0x320)
271/* CR 22th frame start address for output DMA */
272#define EXYNOS_CIOCRSA22 (0x324)
273/* CR 23th frame start address for output DMA */
274#define EXYNOS_CIOCRSA23 (0x328)
275/* CR 24th frame start address for output DMA */
276#define EXYNOS_CIOCRSA24 (0x32c)
277/* CR 25th frame start address for output DMA */
278#define EXYNOS_CIOCRSA25 (0x330)
279/* CR 26th frame start address for output DMA */
280#define EXYNOS_CIOCRSA26 (0x334)
281/* CR 27th frame start address for output DMA */
282#define EXYNOS_CIOCRSA27 (0x338)
283/* CR 28th frame start address for output DMA */
284#define EXYNOS_CIOCRSA28 (0x33c)
285/* CR 29th frame start address for output DMA */
286#define EXYNOS_CIOCRSA29 (0x340)
287/* CR 30th frame start address for output DMA */
288#define EXYNOS_CIOCRSA30 (0x344)
289/* CR 31th frame start address for output DMA */
290#define EXYNOS_CIOCRSA31 (0x348)
291/* CR 32th frame start address for output DMA */
292#define EXYNOS_CIOCRSA32 (0x34c)
293
294/*
295 * Macro part
296*/
297/* frame start address 1 ~ 4, 5 ~ 32 */
298/* Number of Default PingPong Memory */
299#define DEF_PP 4
300#define EXYNOS_CIOYSA(__x) \
301 (((__x) < DEF_PP) ? \
302 (EXYNOS_CIOYSA1 + (__x) * 4) : \
303 (EXYNOS_CIOYSA5 + ((__x) - DEF_PP) * 4))
304#define EXYNOS_CIOCBSA(__x) \
305 (((__x) < DEF_PP) ? \
306 (EXYNOS_CIOCBSA1 + (__x) * 4) : \
307 (EXYNOS_CIOCBSA5 + ((__x) - DEF_PP) * 4))
308#define EXYNOS_CIOCRSA(__x) \
309 (((__x) < DEF_PP) ? \
310 (EXYNOS_CIOCRSA1 + (__x) * 4) : \
311 (EXYNOS_CIOCRSA5 + ((__x) - DEF_PP) * 4))
312/* Number of Default PingPong Memory */
313#define DEF_IPP 1
314#define EXYNOS_CIIYSA(__x) \
315 (((__x) < DEF_IPP) ? \
316 (EXYNOS_CIIYSA0) : (EXYNOS_CIIYSA1))
317#define EXYNOS_CIICBSA(__x) \
318 (((__x) < DEF_IPP) ? \
319 (EXYNOS_CIICBSA0) : (EXYNOS_CIICBSA1))
320#define EXYNOS_CIICRSA(__x) \
321 (((__x) < DEF_IPP) ? \
322 (EXYNOS_CIICRSA0) : (EXYNOS_CIICRSA1))
323
324#define EXYNOS_CISRCFMT_SOURCEHSIZE(x) ((x) << 16)
325#define EXYNOS_CISRCFMT_SOURCEVSIZE(x) ((x) << 0)
326
327#define EXYNOS_CIWDOFST_WINHOROFST(x) ((x) << 16)
328#define EXYNOS_CIWDOFST_WINVEROFST(x) ((x) << 0)
329
330#define EXYNOS_CIWDOFST2_WINHOROFST2(x) ((x) << 16)
331#define EXYNOS_CIWDOFST2_WINVEROFST2(x) ((x) << 0)
332
333#define EXYNOS_CITRGFMT_TARGETHSIZE(x) (((x) & 0x1fff) << 16)
334#define EXYNOS_CITRGFMT_TARGETVSIZE(x) (((x) & 0x1fff) << 0)
335
336#define EXYNOS_CISCPRERATIO_SHFACTOR(x) ((x) << 28)
337#define EXYNOS_CISCPRERATIO_PREHORRATIO(x) ((x) << 16)
338#define EXYNOS_CISCPRERATIO_PREVERRATIO(x) ((x) << 0)
339
340#define EXYNOS_CISCPREDST_PREDSTWIDTH(x) ((x) << 16)
341#define EXYNOS_CISCPREDST_PREDSTHEIGHT(x) ((x) << 0)
342
343#define EXYNOS_CISCCTRL_MAINHORRATIO(x) ((x) << 16)
344#define EXYNOS_CISCCTRL_MAINVERRATIO(x) ((x) << 0)
345
346#define EXYNOS_CITAREA_TARGET_AREA(x) ((x) << 0)
347
348#define EXYNOS_CISTATUS_GET_FRAME_COUNT(x) (((x) >> 26) & 0x3)
349#define EXYNOS_CISTATUS_GET_FRAME_END(x) (((x) >> 17) & 0x1)
350#define EXYNOS_CISTATUS_GET_LAST_CAPTURE_END(x) (((x) >> 16) & 0x1)
351#define EXYNOS_CISTATUS_GET_LCD_STATUS(x) (((x) >> 9) & 0x1)
352#define EXYNOS_CISTATUS_GET_ENVID_STATUS(x) (((x) >> 8) & 0x1)
353
354#define EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(x) (((x) >> 7) & 0x3f)
355#define EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(x) ((x) & 0x3f)
356
357#define EXYNOS_CIIMGEFF_FIN(x) ((x & 0x7) << 26)
358#define EXYNOS_CIIMGEFF_PAT_CB(x) ((x) << 13)
359#define EXYNOS_CIIMGEFF_PAT_CR(x) ((x) << 0)
360
361#define EXYNOS_CIILINESKIP(x) (((x) & 0xf) << 24)
362
363#define EXYNOS_CIREAL_ISIZE_HEIGHT(x) ((x) << 16)
364#define EXYNOS_CIREAL_ISIZE_WIDTH(x) ((x) << 0)
365
366#define EXYNOS_MSCTRL_SUCCESSIVE_COUNT(x) ((x) << 24)
367#define EXYNOS_MSCTRL_GET_INDMA_STATUS(x) ((x) & 0x1)
368
369#define EXYNOS_CIOYOFF_VERTICAL(x) ((x) << 16)
370#define EXYNOS_CIOYOFF_HORIZONTAL(x) ((x) << 0)
371
372#define EXYNOS_CIOCBOFF_VERTICAL(x) ((x) << 16)
373#define EXYNOS_CIOCBOFF_HORIZONTAL(x) ((x) << 0)
374
375#define EXYNOS_CIOCROFF_VERTICAL(x) ((x) << 16)
376#define EXYNOS_CIOCROFF_HORIZONTAL(x) ((x) << 0)
377
378#define EXYNOS_CIIYOFF_VERTICAL(x) ((x) << 16)
379#define EXYNOS_CIIYOFF_HORIZONTAL(x) ((x) << 0)
380
381#define EXYNOS_CIICBOFF_VERTICAL(x) ((x) << 16)
382#define EXYNOS_CIICBOFF_HORIZONTAL(x) ((x) << 0)
383
384#define EXYNOS_CIICROFF_VERTICAL(x) ((x) << 16)
385#define EXYNOS_CIICROFF_HORIZONTAL(x) ((x) << 0)
386
387#define EXYNOS_ORGISIZE_VERTICAL(x) ((x) << 16)
388#define EXYNOS_ORGISIZE_HORIZONTAL(x) ((x) << 0)
389
390#define EXYNOS_ORGOSIZE_VERTICAL(x) ((x) << 16)
391#define EXYNOS_ORGOSIZE_HORIZONTAL(x) ((x) << 0)
392
393#define EXYNOS_CIEXTEN_TARGETH_EXT(x) ((((x) & 0x2000) >> 13) << 26)
394#define EXYNOS_CIEXTEN_TARGETV_EXT(x) ((((x) & 0x2000) >> 13) << 24)
395#define EXYNOS_CIEXTEN_MAINHORRATIO_EXT(x) (((x) & 0x3F) << 10)
396#define EXYNOS_CIEXTEN_MAINVERRATIO_EXT(x) ((x) & 0x3F)
397
398/*
399 * Bit definition part
400*/
401/* Source format register */
402#define EXYNOS_CISRCFMT_ITU601_8BIT (1 << 31)
403#define EXYNOS_CISRCFMT_ITU656_8BIT (0 << 31)
404#define EXYNOS_CISRCFMT_ITU601_16BIT (1 << 29)
405#define EXYNOS_CISRCFMT_ORDER422_YCBYCR (0 << 14)
406#define EXYNOS_CISRCFMT_ORDER422_YCRYCB (1 << 14)
407#define EXYNOS_CISRCFMT_ORDER422_CBYCRY (2 << 14)
408#define EXYNOS_CISRCFMT_ORDER422_CRYCBY (3 << 14)
409/* ITU601 16bit only */
410#define EXYNOS_CISRCFMT_ORDER422_Y4CBCRCBCR (0 << 14)
411/* ITU601 16bit only */
412#define EXYNOS_CISRCFMT_ORDER422_Y4CRCBCRCB (1 << 14)
413
414/* Window offset register */
415#define EXYNOS_CIWDOFST_WINOFSEN (1 << 31)
416#define EXYNOS_CIWDOFST_CLROVFIY (1 << 30)
417#define EXYNOS_CIWDOFST_CLROVRLB (1 << 29)
418#define EXYNOS_CIWDOFST_WINHOROFST_MASK (0x7ff << 16)
419#define EXYNOS_CIWDOFST_CLROVFICB (1 << 15)
420#define EXYNOS_CIWDOFST_CLROVFICR (1 << 14)
421#define EXYNOS_CIWDOFST_WINVEROFST_MASK (0xfff << 0)
422
423/* Global control register */
424#define EXYNOS_CIGCTRL_SWRST (1 << 31)
425#define EXYNOS_CIGCTRL_CAMRST_A (1 << 30)
426#define EXYNOS_CIGCTRL_SELCAM_ITU_B (0 << 29)
427#define EXYNOS_CIGCTRL_SELCAM_ITU_A (1 << 29)
428#define EXYNOS_CIGCTRL_SELCAM_ITU_MASK (1 << 29)
429#define EXYNOS_CIGCTRL_TESTPATTERN_NORMAL (0 << 27)
430#define EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR (1 << 27)
431#define EXYNOS_CIGCTRL_TESTPATTERN_HOR_INC (2 << 27)
432#define EXYNOS_CIGCTRL_TESTPATTERN_VER_INC (3 << 27)
433#define EXYNOS_CIGCTRL_TESTPATTERN_MASK (3 << 27)
434#define EXYNOS_CIGCTRL_TESTPATTERN_SHIFT (27)
435#define EXYNOS_CIGCTRL_INVPOLPCLK (1 << 26)
436#define EXYNOS_CIGCTRL_INVPOLVSYNC (1 << 25)
437#define EXYNOS_CIGCTRL_INVPOLHREF (1 << 24)
438#define EXYNOS_CIGCTRL_IRQ_OVFEN (1 << 22)
439#define EXYNOS_CIGCTRL_HREF_MASK (1 << 21)
440#define EXYNOS_CIGCTRL_IRQ_EDGE (0 << 20)
441#define EXYNOS_CIGCTRL_IRQ_LEVEL (1 << 20)
442#define EXYNOS_CIGCTRL_IRQ_CLR (1 << 19)
443#define EXYNOS_CIGCTRL_IRQ_END_DISABLE (1 << 18)
444#define EXYNOS_CIGCTRL_IRQ_DISABLE (0 << 16)
445#define EXYNOS_CIGCTRL_IRQ_ENABLE (1 << 16)
446#define EXYNOS_CIGCTRL_SHADOW_DISABLE (1 << 12)
447#define EXYNOS_CIGCTRL_CAM_JPEG (1 << 8)
448#define EXYNOS_CIGCTRL_SELCAM_MIPI_B (0 << 7)
449#define EXYNOS_CIGCTRL_SELCAM_MIPI_A (1 << 7)
450#define EXYNOS_CIGCTRL_SELCAM_MIPI_MASK (1 << 7)
451#define EXYNOS_CIGCTRL_SELWB_CAMIF_CAMERA (0 << 6)
452#define EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK (1 << 6)
453#define EXYNOS_CIGCTRL_SELWRITEBACK_MASK (1 << 10)
454#define EXYNOS_CIGCTRL_SELWRITEBACK_A (1 << 10)
455#define EXYNOS_CIGCTRL_SELWRITEBACK_B (0 << 10)
456#define EXYNOS_CIGCTRL_SELWB_CAMIF_MASK (1 << 6)
457#define EXYNOS_CIGCTRL_CSC_ITU601 (0 << 5)
458#define EXYNOS_CIGCTRL_CSC_ITU709 (1 << 5)
459#define EXYNOS_CIGCTRL_CSC_MASK (1 << 5)
460#define EXYNOS_CIGCTRL_INVPOLHSYNC (1 << 4)
461#define EXYNOS_CIGCTRL_SELCAM_FIMC_ITU (0 << 3)
462#define EXYNOS_CIGCTRL_SELCAM_FIMC_MIPI (1 << 3)
463#define EXYNOS_CIGCTRL_SELCAM_FIMC_MASK (1 << 3)
464#define EXYNOS_CIGCTRL_PROGRESSIVE (0 << 0)
465#define EXYNOS_CIGCTRL_INTERLACE (1 << 0)
466
467/* Window offset2 register */
468#define EXYNOS_CIWDOFST_WINHOROFST2_MASK (0xfff << 16)
469#define EXYNOS_CIWDOFST_WINVEROFST2_MASK (0xfff << 16)
470
471/* Target format register */
472#define EXYNOS_CITRGFMT_INROT90_CLOCKWISE (1 << 31)
473#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420 (0 << 29)
474#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422 (1 << 29)
475#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE (2 << 29)
476#define EXYNOS_CITRGFMT_OUTFORMAT_RGB (3 << 29)
477#define EXYNOS_CITRGFMT_OUTFORMAT_MASK (3 << 29)
478#define EXYNOS_CITRGFMT_FLIP_SHIFT (14)
479#define EXYNOS_CITRGFMT_FLIP_NORMAL (0 << 14)
480#define EXYNOS_CITRGFMT_FLIP_X_MIRROR (1 << 14)
481#define EXYNOS_CITRGFMT_FLIP_Y_MIRROR (2 << 14)
482#define EXYNOS_CITRGFMT_FLIP_180 (3 << 14)
483#define EXYNOS_CITRGFMT_FLIP_MASK (3 << 14)
484#define EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE (1 << 13)
485#define EXYNOS_CITRGFMT_TARGETV_MASK (0x1fff << 0)
486#define EXYNOS_CITRGFMT_TARGETH_MASK (0x1fff << 16)
487
488/* Output DMA control register */
489#define EXYNOS_CIOCTRL_WEAVE_OUT (1 << 31)
490#define EXYNOS_CIOCTRL_WEAVE_MASK (1 << 31)
491#define EXYNOS_CIOCTRL_LASTENDEN (1 << 30)
492#define EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR (0 << 24)
493#define EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB (1 << 24)
494#define EXYNOS_CIOCTRL_ORDER2P_MSB_CRCB (2 << 24)
495#define EXYNOS_CIOCTRL_ORDER2P_MSB_CBCR (3 << 24)
496#define EXYNOS_CIOCTRL_ORDER2P_SHIFT (24)
497#define EXYNOS_CIOCTRL_ORDER2P_MASK (3 << 24)
498#define EXYNOS_CIOCTRL_YCBCR_3PLANE (0 << 3)
499#define EXYNOS_CIOCTRL_YCBCR_2PLANE (1 << 3)
500#define EXYNOS_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
501#define EXYNOS_CIOCTRL_LASTIRQ_ENABLE (1 << 2)
502#define EXYNOS_CIOCTRL_ALPHA_OUT (0xff << 4)
503#define EXYNOS_CIOCTRL_ORDER422_YCBYCR (0 << 0)
504#define EXYNOS_CIOCTRL_ORDER422_YCRYCB (1 << 0)
505#define EXYNOS_CIOCTRL_ORDER422_CBYCRY (2 << 0)
506#define EXYNOS_CIOCTRL_ORDER422_CRYCBY (3 << 0)
507#define EXYNOS_CIOCTRL_ORDER422_MASK (3 << 0)
508
509/* Main scaler control register */
510#define EXYNOS_CISCCTRL_SCALERBYPASS (1 << 31)
511#define EXYNOS_CISCCTRL_SCALEUP_H (1 << 30)
512#define EXYNOS_CISCCTRL_SCALEUP_V (1 << 29)
513#define EXYNOS_CISCCTRL_CSCR2Y_NARROW (0 << 28)
514#define EXYNOS_CISCCTRL_CSCR2Y_WIDE (1 << 28)
515#define EXYNOS_CISCCTRL_CSCY2R_NARROW (0 << 27)
516#define EXYNOS_CISCCTRL_CSCY2R_WIDE (1 << 27)
517#define EXYNOS_CISCCTRL_LCDPATHEN_FIFO (1 << 26)
518#define EXYNOS_CISCCTRL_PROGRESSIVE (0 << 25)
519#define EXYNOS_CISCCTRL_INTERLACE (1 << 25)
520#define EXYNOS_CISCCTRL_SCAN_MASK (1 << 25)
521#define EXYNOS_CISCCTRL_SCALERSTART (1 << 15)
522#define EXYNOS_CISCCTRL_INRGB_FMT_RGB565 (0 << 13)
523#define EXYNOS_CISCCTRL_INRGB_FMT_RGB666 (1 << 13)
524#define EXYNOS_CISCCTRL_INRGB_FMT_RGB888 (2 << 13)
525#define EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK (3 << 13)
526#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
527#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
528#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
529#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK (3 << 11)
530#define EXYNOS_CISCCTRL_EXTRGB_NORMAL (0 << 10)
531#define EXYNOS_CISCCTRL_EXTRGB_EXTENSION (1 << 10)
532#define EXYNOS_CISCCTRL_ONE2ONE (1 << 9)
533#define EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK (0x1ff << 0)
534#define EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK (0x1ff << 16)
535
536/* Status register */
537#define EXYNOS_CISTATUS_OVFIY (1 << 31)
538#define EXYNOS_CISTATUS_OVFICB (1 << 30)
539#define EXYNOS_CISTATUS_OVFICR (1 << 29)
540#define EXYNOS_CISTATUS_VSYNC (1 << 28)
541#define EXYNOS_CISTATUS_SCALERSTART (1 << 26)
542#define EXYNOS_CISTATUS_WINOFSTEN (1 << 25)
543#define EXYNOS_CISTATUS_IMGCPTEN (1 << 22)
544#define EXYNOS_CISTATUS_IMGCPTENSC (1 << 21)
545#define EXYNOS_CISTATUS_VSYNC_A (1 << 20)
546#define EXYNOS_CISTATUS_VSYNC_B (1 << 19)
547#define EXYNOS_CISTATUS_OVRLB (1 << 18)
548#define EXYNOS_CISTATUS_FRAMEEND (1 << 17)
549#define EXYNOS_CISTATUS_LASTCAPTUREEND (1 << 16)
550#define EXYNOS_CISTATUS_VVALID_A (1 << 15)
551#define EXYNOS_CISTATUS_VVALID_B (1 << 14)
552
553/* Image capture enable register */
554#define EXYNOS_CIIMGCPT_IMGCPTEN (1 << 31)
555#define EXYNOS_CIIMGCPT_IMGCPTEN_SC (1 << 30)
556#define EXYNOS_CIIMGCPT_CPT_FREN_ENABLE (1 << 25)
557#define EXYNOS_CIIMGCPT_CPT_FRMOD_EN (0 << 18)
558#define EXYNOS_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
559
560/* Image effects register */
561#define EXYNOS_CIIMGEFF_IE_DISABLE (0 << 30)
562#define EXYNOS_CIIMGEFF_IE_ENABLE (1 << 30)
563#define EXYNOS_CIIMGEFF_IE_SC_BEFORE (0 << 29)
564#define EXYNOS_CIIMGEFF_IE_SC_AFTER (1 << 29)
565#define EXYNOS_CIIMGEFF_FIN_BYPASS (0 << 26)
566#define EXYNOS_CIIMGEFF_FIN_ARBITRARY (1 << 26)
567#define EXYNOS_CIIMGEFF_FIN_NEGATIVE (2 << 26)
568#define EXYNOS_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
569#define EXYNOS_CIIMGEFF_FIN_EMBOSSING (4 << 26)
570#define EXYNOS_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
571#define EXYNOS_CIIMGEFF_FIN_MASK (7 << 26)
572#define EXYNOS_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0))
573
574/* Real input DMA size register */
575#define EXYNOS_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31)
576#define EXYNOS_CIREAL_ISIZE_ADDR_CH_DISABLE (1 << 30)
577#define EXYNOS_CIREAL_ISIZE_HEIGHT_MASK (0x3FFF << 16)
578#define EXYNOS_CIREAL_ISIZE_WIDTH_MASK (0x3FFF << 0)
579
580/* Input DMA control register */
581#define EXYNOS_MSCTRL_FIELD_MASK (1 << 31)
582#define EXYNOS_MSCTRL_FIELD_WEAVE (1 << 31)
583#define EXYNOS_MSCTRL_FIELD_NORMAL (0 << 31)
584#define EXYNOS_MSCTRL_BURST_CNT (24)
585#define EXYNOS_MSCTRL_BURST_CNT_MASK (0xf << 24)
586#define EXYNOS_MSCTRL_ORDER2P_LSB_CBCR (0 << 16)
587#define EXYNOS_MSCTRL_ORDER2P_LSB_CRCB (1 << 16)
588#define EXYNOS_MSCTRL_ORDER2P_MSB_CRCB (2 << 16)
589#define EXYNOS_MSCTRL_ORDER2P_MSB_CBCR (3 << 16)
590#define EXYNOS_MSCTRL_ORDER2P_SHIFT (16)
591#define EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK (0x3 << 16)
592#define EXYNOS_MSCTRL_C_INT_IN_3PLANE (0 << 15)
593#define EXYNOS_MSCTRL_C_INT_IN_2PLANE (1 << 15)
594#define EXYNOS_MSCTRL_FLIP_SHIFT (13)
595#define EXYNOS_MSCTRL_FLIP_NORMAL (0 << 13)
596#define EXYNOS_MSCTRL_FLIP_X_MIRROR (1 << 13)
597#define EXYNOS_MSCTRL_FLIP_Y_MIRROR (2 << 13)
598#define EXYNOS_MSCTRL_FLIP_180 (3 << 13)
599#define EXYNOS_MSCTRL_FLIP_MASK (3 << 13)
600#define EXYNOS_MSCTRL_ORDER422_CRYCBY (0 << 4)
601#define EXYNOS_MSCTRL_ORDER422_YCRYCB (1 << 4)
602#define EXYNOS_MSCTRL_ORDER422_CBYCRY (2 << 4)
603#define EXYNOS_MSCTRL_ORDER422_YCBYCR (3 << 4)
604#define EXYNOS_MSCTRL_INPUT_EXTCAM (0 << 3)
605#define EXYNOS_MSCTRL_INPUT_MEMORY (1 << 3)
606#define EXYNOS_MSCTRL_INPUT_MASK (1 << 3)
607#define EXYNOS_MSCTRL_INFORMAT_YCBCR420 (0 << 1)
608#define EXYNOS_MSCTRL_INFORMAT_YCBCR422 (1 << 1)
609#define EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE (2 << 1)
610#define EXYNOS_MSCTRL_INFORMAT_RGB (3 << 1)
611#define EXYNOS_MSCTRL_ENVID (1 << 0)
612
613/* DMA parameter register */
614#define EXYNOS_CIDMAPARAM_R_MODE_LINEAR (0 << 29)
615#define EXYNOS_CIDMAPARAM_R_MODE_CONFTILE (1 << 29)
616#define EXYNOS_CIDMAPARAM_R_MODE_16X16 (2 << 29)
617#define EXYNOS_CIDMAPARAM_R_MODE_64X32 (3 << 29)
618#define EXYNOS_CIDMAPARAM_R_MODE_MASK (3 << 29)
619#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_64 (0 << 24)
620#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_128 (1 << 24)
621#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_256 (2 << 24)
622#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_512 (3 << 24)
623#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_1024 (4 << 24)
624#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_2048 (5 << 24)
625#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_4096 (6 << 24)
626#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_1 (0 << 20)
627#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_2 (1 << 20)
628#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_4 (2 << 20)
629#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_8 (3 << 20)
630#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_16 (4 << 20)
631#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_32 (5 << 20)
632#define EXYNOS_CIDMAPARAM_W_MODE_LINEAR (0 << 13)
633#define EXYNOS_CIDMAPARAM_W_MODE_CONFTILE (1 << 13)
634#define EXYNOS_CIDMAPARAM_W_MODE_16X16 (2 << 13)
635#define EXYNOS_CIDMAPARAM_W_MODE_64X32 (3 << 13)
636#define EXYNOS_CIDMAPARAM_W_MODE_MASK (3 << 13)
637#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_64 (0 << 8)
638#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_128 (1 << 8)
639#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_256 (2 << 8)
640#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_512 (3 << 8)
641#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_1024 (4 << 8)
642#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_2048 (5 << 8)
643#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_4096 (6 << 8)
644#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_1 (0 << 4)
645#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_2 (1 << 4)
646#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_4 (2 << 4)
647#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_8 (3 << 4)
648#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_16 (4 << 4)
649#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_32 (5 << 4)
650
651/* Gathering Extension register */
652#define EXYNOS_CIEXTEN_TARGETH_EXT_MASK (1 << 26)
653#define EXYNOS_CIEXTEN_TARGETV_EXT_MASK (1 << 24)
654#define EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK (0x3F << 10)
655#define EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK (0x3F)
656#define EXYNOS_CIEXTEN_YUV444_OUT (1 << 22)
657
658/* FIMC Clock Source Select register */
659#define EXYNOS_CLKSRC_HCLK (0 << 1)
660#define EXYNOS_CLKSRC_HCLK_MASK (1 << 1)
661#define EXYNOS_CLKSRC_SCLK (1 << 1)
662
663/* SYSREG for FIMC writeback */
664#define SYSREG_CAMERA_BLK (S3C_VA_SYS + 0x0218)
665#define SYSREG_ISP_BLK (S3C_VA_SYS + 0x020c)
666#define SYSREG_FIMD0WB_DEST_MASK (0x3 << 23)
667#define SYSREG_FIMD0WB_DEST_SHIFT 23
668
669#endif /* EXYNOS_REGS_FIMC_H */
diff --git a/drivers/gpu/drm/exynos/regs-gsc.h b/drivers/gpu/drm/exynos/regs-gsc.h
new file mode 100644
index 000000000000..9ad592707aaf
--- /dev/null
+++ b/drivers/gpu/drm/exynos/regs-gsc.h
@@ -0,0 +1,284 @@
1/* linux/drivers/gpu/drm/exynos/regs-gsc.h
2 *
3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * Register definition file for Samsung G-Scaler driver
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef EXYNOS_REGS_GSC_H_
14#define EXYNOS_REGS_GSC_H_
15
16/* G-Scaler enable */
17#define GSC_ENABLE 0x00
18#define GSC_ENABLE_PP_UPDATE_TIME_MASK (1 << 9)
19#define GSC_ENABLE_PP_UPDATE_TIME_CURR (0 << 9)
20#define GSC_ENABLE_PP_UPDATE_TIME_EOPAS (1 << 9)
21#define GSC_ENABLE_CLK_GATE_MODE_MASK (1 << 8)
22#define GSC_ENABLE_CLK_GATE_MODE_FREE (1 << 8)
23#define GSC_ENABLE_IPC_MODE_MASK (1 << 7)
24#define GSC_ENABLE_NORM_MODE (0 << 7)
25#define GSC_ENABLE_IPC_MODE (1 << 7)
26#define GSC_ENABLE_PP_UPDATE_MODE_MASK (1 << 6)
27#define GSC_ENABLE_PP_UPDATE_FIRE_MODE (1 << 6)
28#define GSC_ENABLE_IN_PP_UPDATE (1 << 5)
29#define GSC_ENABLE_ON_CLEAR_MASK (1 << 4)
30#define GSC_ENABLE_ON_CLEAR_ONESHOT (1 << 4)
31#define GSC_ENABLE_QOS_ENABLE (1 << 3)
32#define GSC_ENABLE_OP_STATUS (1 << 2)
33#define GSC_ENABLE_SFR_UPDATE (1 << 1)
34#define GSC_ENABLE_ON (1 << 0)
35
36/* G-Scaler S/W reset */
37#define GSC_SW_RESET 0x04
38#define GSC_SW_RESET_SRESET (1 << 0)
39
40/* G-Scaler IRQ */
41#define GSC_IRQ 0x08
42#define GSC_IRQ_STATUS_OR_IRQ (1 << 17)
43#define GSC_IRQ_STATUS_OR_FRM_DONE (1 << 16)
44#define GSC_IRQ_OR_MASK (1 << 2)
45#define GSC_IRQ_FRMDONE_MASK (1 << 1)
46#define GSC_IRQ_ENABLE (1 << 0)
47
48/* G-Scaler input control */
49#define GSC_IN_CON 0x10
50#define GSC_IN_CHROM_STRIDE_SEL_MASK (1 << 20)
51#define GSC_IN_CHROM_STRIDE_SEPAR (1 << 20)
52#define GSC_IN_RB_SWAP_MASK (1 << 19)
53#define GSC_IN_RB_SWAP (1 << 19)
54#define GSC_IN_ROT_MASK (7 << 16)
55#define GSC_IN_ROT_270 (7 << 16)
56#define GSC_IN_ROT_90_YFLIP (6 << 16)
57#define GSC_IN_ROT_90_XFLIP (5 << 16)
58#define GSC_IN_ROT_90 (4 << 16)
59#define GSC_IN_ROT_180 (3 << 16)
60#define GSC_IN_ROT_YFLIP (2 << 16)
61#define GSC_IN_ROT_XFLIP (1 << 16)
62#define GSC_IN_RGB_TYPE_MASK (3 << 14)
63#define GSC_IN_RGB_HD_WIDE (3 << 14)
64#define GSC_IN_RGB_HD_NARROW (2 << 14)
65#define GSC_IN_RGB_SD_WIDE (1 << 14)
66#define GSC_IN_RGB_SD_NARROW (0 << 14)
67#define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13)
68#define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13)
69#define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13)
70#define GSC_IN_CHROMA_ORDER_MASK (1 << 12)
71#define GSC_IN_CHROMA_ORDER_CBCR (0 << 12)
72#define GSC_IN_CHROMA_ORDER_CRCB (1 << 12)
73#define GSC_IN_FORMAT_MASK (7 << 8)
74#define GSC_IN_XRGB8888 (0 << 8)
75#define GSC_IN_RGB565 (1 << 8)
76#define GSC_IN_YUV420_2P (2 << 8)
77#define GSC_IN_YUV420_3P (3 << 8)
78#define GSC_IN_YUV422_1P (4 << 8)
79#define GSC_IN_YUV422_2P (5 << 8)
80#define GSC_IN_YUV422_3P (6 << 8)
81#define GSC_IN_TILE_TYPE_MASK (1 << 4)
82#define GSC_IN_TILE_C_16x8 (0 << 4)
83#define GSC_IN_TILE_C_16x16 (1 << 4)
84#define GSC_IN_TILE_MODE (1 << 3)
85#define GSC_IN_LOCAL_SEL_MASK (3 << 1)
86#define GSC_IN_LOCAL_CAM3 (3 << 1)
87#define GSC_IN_LOCAL_FIMD_WB (2 << 1)
88#define GSC_IN_LOCAL_CAM1 (1 << 1)
89#define GSC_IN_LOCAL_CAM0 (0 << 1)
90#define GSC_IN_PATH_MASK (1 << 0)
91#define GSC_IN_PATH_LOCAL (1 << 0)
92#define GSC_IN_PATH_MEMORY (0 << 0)
93
94/* G-Scaler source image size */
95#define GSC_SRCIMG_SIZE 0x14
96#define GSC_SRCIMG_HEIGHT_MASK (0x1fff << 16)
97#define GSC_SRCIMG_HEIGHT(x) ((x) << 16)
98#define GSC_SRCIMG_WIDTH_MASK (0x3fff << 0)
99#define GSC_SRCIMG_WIDTH(x) ((x) << 0)
100
101/* G-Scaler source image offset */
102#define GSC_SRCIMG_OFFSET 0x18
103#define GSC_SRCIMG_OFFSET_Y_MASK (0x1fff << 16)
104#define GSC_SRCIMG_OFFSET_Y(x) ((x) << 16)
105#define GSC_SRCIMG_OFFSET_X_MASK (0x1fff << 0)
106#define GSC_SRCIMG_OFFSET_X(x) ((x) << 0)
107
108/* G-Scaler cropped source image size */
109#define GSC_CROPPED_SIZE 0x1C
110#define GSC_CROPPED_HEIGHT_MASK (0x1fff << 16)
111#define GSC_CROPPED_HEIGHT(x) ((x) << 16)
112#define GSC_CROPPED_WIDTH_MASK (0x1fff << 0)
113#define GSC_CROPPED_WIDTH(x) ((x) << 0)
114
115/* G-Scaler output control */
116#define GSC_OUT_CON 0x20
117#define GSC_OUT_GLOBAL_ALPHA_MASK (0xff << 24)
118#define GSC_OUT_GLOBAL_ALPHA(x) ((x) << 24)
119#define GSC_OUT_CHROM_STRIDE_SEL_MASK (1 << 13)
120#define GSC_OUT_CHROM_STRIDE_SEPAR (1 << 13)
121#define GSC_OUT_RB_SWAP_MASK (1 << 12)
122#define GSC_OUT_RB_SWAP (1 << 12)
123#define GSC_OUT_RGB_TYPE_MASK (3 << 10)
124#define GSC_OUT_RGB_HD_NARROW (3 << 10)
125#define GSC_OUT_RGB_HD_WIDE (2 << 10)
126#define GSC_OUT_RGB_SD_NARROW (1 << 10)
127#define GSC_OUT_RGB_SD_WIDE (0 << 10)
128#define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9)
129#define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9)
130#define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9)
131#define GSC_OUT_CHROMA_ORDER_MASK (1 << 8)
132#define GSC_OUT_CHROMA_ORDER_CBCR (0 << 8)
133#define GSC_OUT_CHROMA_ORDER_CRCB (1 << 8)
134#define GSC_OUT_FORMAT_MASK (7 << 4)
135#define GSC_OUT_XRGB8888 (0 << 4)
136#define GSC_OUT_RGB565 (1 << 4)
137#define GSC_OUT_YUV420_2P (2 << 4)
138#define GSC_OUT_YUV420_3P (3 << 4)
139#define GSC_OUT_YUV422_1P (4 << 4)
140#define GSC_OUT_YUV422_2P (5 << 4)
141#define GSC_OUT_YUV444 (7 << 4)
142#define GSC_OUT_TILE_TYPE_MASK (1 << 2)
143#define GSC_OUT_TILE_C_16x8 (0 << 2)
144#define GSC_OUT_TILE_C_16x16 (1 << 2)
145#define GSC_OUT_TILE_MODE (1 << 1)
146#define GSC_OUT_PATH_MASK (1 << 0)
147#define GSC_OUT_PATH_LOCAL (1 << 0)
148#define GSC_OUT_PATH_MEMORY (0 << 0)
149
150/* G-Scaler scaled destination image size */
151#define GSC_SCALED_SIZE 0x24
152#define GSC_SCALED_HEIGHT_MASK (0x1fff << 16)
153#define GSC_SCALED_HEIGHT(x) ((x) << 16)
154#define GSC_SCALED_WIDTH_MASK (0x1fff << 0)
155#define GSC_SCALED_WIDTH(x) ((x) << 0)
156
157/* G-Scaler pre scale ratio */
158#define GSC_PRE_SCALE_RATIO 0x28
159#define GSC_PRESC_SHFACTOR_MASK (7 << 28)
160#define GSC_PRESC_SHFACTOR(x) ((x) << 28)
161#define GSC_PRESC_V_RATIO_MASK (7 << 16)
162#define GSC_PRESC_V_RATIO(x) ((x) << 16)
163#define GSC_PRESC_H_RATIO_MASK (7 << 0)
164#define GSC_PRESC_H_RATIO(x) ((x) << 0)
165
166/* G-Scaler main scale horizontal ratio */
167#define GSC_MAIN_H_RATIO 0x2C
168#define GSC_MAIN_H_RATIO_MASK (0xfffff << 0)
169#define GSC_MAIN_H_RATIO_VALUE(x) ((x) << 0)
170
171/* G-Scaler main scale vertical ratio */
172#define GSC_MAIN_V_RATIO 0x30
173#define GSC_MAIN_V_RATIO_MASK (0xfffff << 0)
174#define GSC_MAIN_V_RATIO_VALUE(x) ((x) << 0)
175
176/* G-Scaler input chrominance stride */
177#define GSC_IN_CHROM_STRIDE 0x3C
178#define GSC_IN_CHROM_STRIDE_MASK (0x3fff << 0)
179#define GSC_IN_CHROM_STRIDE_VALUE(x) ((x) << 0)
180
181/* G-Scaler destination image size */
182#define GSC_DSTIMG_SIZE 0x40
183#define GSC_DSTIMG_HEIGHT_MASK (0x1fff << 16)
184#define GSC_DSTIMG_HEIGHT(x) ((x) << 16)
185#define GSC_DSTIMG_WIDTH_MASK (0x1fff << 0)
186#define GSC_DSTIMG_WIDTH(x) ((x) << 0)
187
188/* G-Scaler destination image offset */
189#define GSC_DSTIMG_OFFSET 0x44
190#define GSC_DSTIMG_OFFSET_Y_MASK (0x1fff << 16)
191#define GSC_DSTIMG_OFFSET_Y(x) ((x) << 16)
192#define GSC_DSTIMG_OFFSET_X_MASK (0x1fff << 0)
193#define GSC_DSTIMG_OFFSET_X(x) ((x) << 0)
194
195/* G-Scaler output chrominance stride */
196#define GSC_OUT_CHROM_STRIDE 0x48
197#define GSC_OUT_CHROM_STRIDE_MASK (0x3fff << 0)
198#define GSC_OUT_CHROM_STRIDE_VALUE(x) ((x) << 0)
199
200/* G-Scaler input y address mask */
201#define GSC_IN_BASE_ADDR_Y_MASK 0x4C
202/* G-Scaler input y base address */
203#define GSC_IN_BASE_ADDR_Y(n) (0x50 + (n) * 0x4)
204/* G-Scaler input y base current address */
205#define GSC_IN_BASE_ADDR_Y_CUR(n) (0x60 + (n) * 0x4)
206
207/* G-Scaler input cb address mask */
208#define GSC_IN_BASE_ADDR_CB_MASK 0x7C
209/* G-Scaler input cb base address */
210#define GSC_IN_BASE_ADDR_CB(n) (0x80 + (n) * 0x4)
211/* G-Scaler input cb base current address */
212#define GSC_IN_BASE_ADDR_CB_CUR(n) (0x90 + (n) * 0x4)
213
214/* G-Scaler input cr address mask */
215#define GSC_IN_BASE_ADDR_CR_MASK 0xAC
216/* G-Scaler input cr base address */
217#define GSC_IN_BASE_ADDR_CR(n) (0xB0 + (n) * 0x4)
218/* G-Scaler input cr base current address */
219#define GSC_IN_BASE_ADDR_CR_CUR(n) (0xC0 + (n) * 0x4)
220
221/* G-Scaler input address mask */
222#define GSC_IN_CURR_ADDR_INDEX (0xf << 24)
223#define GSC_IN_CURR_GET_INDEX(x) ((x) >> 24)
224#define GSC_IN_BASE_ADDR_PINGPONG(x) ((x) << 16)
225#define GSC_IN_BASE_ADDR_MASK (0xff << 0)
226
227/* G-Scaler output y address mask */
228#define GSC_OUT_BASE_ADDR_Y_MASK 0x10C
229/* G-Scaler output y base address */
230#define GSC_OUT_BASE_ADDR_Y(n) (0x110 + (n) * 0x4)
231
232/* G-Scaler output cb address mask */
233#define GSC_OUT_BASE_ADDR_CB_MASK 0x15C
234/* G-Scaler output cb base address */
235#define GSC_OUT_BASE_ADDR_CB(n) (0x160 + (n) * 0x4)
236
237/* G-Scaler output cr address mask */
238#define GSC_OUT_BASE_ADDR_CR_MASK 0x1AC
239/* G-Scaler output cr base address */
240#define GSC_OUT_BASE_ADDR_CR(n) (0x1B0 + (n) * 0x4)
241
242/* G-Scaler output address mask */
243#define GSC_OUT_CURR_ADDR_INDEX (0xf << 24)
244#define GSC_OUT_CURR_GET_INDEX(x) ((x) >> 24)
245#define GSC_OUT_BASE_ADDR_PINGPONG(x) ((x) << 16)
246#define GSC_OUT_BASE_ADDR_MASK (0xffff << 0)
247
248/* G-Scaler horizontal scaling filter */
249#define GSC_HCOEF(n, s, x) (0x300 + (n) * 0x4 + (s) * 0x30 + (x) * 0x300)
250
251/* G-Scaler vertical scaling filter */
252#define GSC_VCOEF(n, s, x) (0x200 + (n) * 0x4 + (s) * 0x30 + (x) * 0x300)
253
254/* G-Scaler BUS control */
255#define GSC_BUSCON 0xA78
256#define GSC_BUSCON_INT_TIME_MASK (1 << 8)
257#define GSC_BUSCON_INT_DATA_TRANS (0 << 8)
258#define GSC_BUSCON_INT_AXI_RESPONSE (1 << 8)
259#define GSC_BUSCON_AWCACHE(x) ((x) << 4)
260#define GSC_BUSCON_ARCACHE(x) ((x) << 0)
261
262/* G-Scaler V position */
263#define GSC_VPOSITION 0xA7C
264#define GSC_VPOS_F(x) ((x) << 0)
265
266
267/* G-Scaler clock initial count */
268#define GSC_CLK_INIT_COUNT 0xC00
269#define GSC_CLK_GATE_MODE_INIT_CNT(x) ((x) << 0)
270
271/* G-Scaler clock snoop count */
272#define GSC_CLK_SNOOP_COUNT 0xC04
273#define GSC_CLK_GATE_MODE_SNOOP_CNT(x) ((x) << 0)
274
275/* SYSCON. GSCBLK_CFG */
276#define SYSREG_GSCBLK_CFG1 (S3C_VA_SYS + 0x0224)
277#define GSC_BLK_DISP1WB_DEST(x) (x << 10)
278#define GSC_BLK_SW_RESET_WB_DEST(x) (1 << (18 + x))
279#define GSC_BLK_PXLASYNC_LO_MASK_WB(x) (0 << (14 + x))
280#define GSC_BLK_GSCL_WB_IN_SRC_SEL(x) (1 << (2 * x))
281#define SYSREG_GSCBLK_CFG2 (S3C_VA_SYS + 0x2000)
282#define PXLASYNC_LO_MASK_CAMIF_GSCL(x) (1 << (x))
283
284#endif /* EXYNOS_REGS_GSC_H_ */
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h
index 970cdb518eb1..ef1b3eb3ba6e 100644
--- a/drivers/gpu/drm/exynos/regs-hdmi.h
+++ b/drivers/gpu/drm/exynos/regs-hdmi.h
@@ -176,6 +176,11 @@
176#define HDMI_PHY_CMU HDMI_CTRL_BASE(0x007C) 176#define HDMI_PHY_CMU HDMI_CTRL_BASE(0x007C)
177#define HDMI_CORE_RSTOUT HDMI_CTRL_BASE(0x0080) 177#define HDMI_CORE_RSTOUT HDMI_CTRL_BASE(0x0080)
178 178
179/* PHY Control bit definition */
180
181/* HDMI_PHY_CON_0 */
182#define HDMI_PHY_POWER_OFF_EN (1 << 0)
183
179/* Video related registers */ 184/* Video related registers */
180#define HDMI_YMAX HDMI_CORE_BASE(0x0060) 185#define HDMI_YMAX HDMI_CORE_BASE(0x0060)
181#define HDMI_YMIN HDMI_CORE_BASE(0x0064) 186#define HDMI_YMIN HDMI_CORE_BASE(0x0064)
diff --git a/drivers/gpu/drm/exynos/regs-rotator.h b/drivers/gpu/drm/exynos/regs-rotator.h
new file mode 100644
index 000000000000..a09ac6e180da
--- /dev/null
+++ b/drivers/gpu/drm/exynos/regs-rotator.h
@@ -0,0 +1,73 @@
1/* drivers/gpu/drm/exynos/regs-rotator.h
2 *
3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Register definition file for Samsung Rotator Interface (Rotator) driver
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef EXYNOS_REGS_ROTATOR_H
14#define EXYNOS_REGS_ROTATOR_H
15
16/* Configuration */
17#define ROT_CONFIG 0x00
18#define ROT_CONFIG_IRQ (3 << 8)
19
20/* Image Control */
21#define ROT_CONTROL 0x10
22#define ROT_CONTROL_PATTERN_WRITE (1 << 16)
23#define ROT_CONTROL_FMT_YCBCR420_2P (1 << 8)
24#define ROT_CONTROL_FMT_RGB888 (6 << 8)
25#define ROT_CONTROL_FMT_MASK (7 << 8)
26#define ROT_CONTROL_FLIP_VERTICAL (2 << 6)
27#define ROT_CONTROL_FLIP_HORIZONTAL (3 << 6)
28#define ROT_CONTROL_FLIP_MASK (3 << 6)
29#define ROT_CONTROL_ROT_90 (1 << 4)
30#define ROT_CONTROL_ROT_180 (2 << 4)
31#define ROT_CONTROL_ROT_270 (3 << 4)
32#define ROT_CONTROL_ROT_MASK (3 << 4)
33#define ROT_CONTROL_START (1 << 0)
34
35/* Status */
36#define ROT_STATUS 0x20
37#define ROT_STATUS_IRQ_PENDING(x) (1 << (x))
38#define ROT_STATUS_IRQ(x) (((x) >> 8) & 0x3)
39#define ROT_STATUS_IRQ_VAL_COMPLETE 1
40#define ROT_STATUS_IRQ_VAL_ILLEGAL 2
41
42/* Buffer Address */
43#define ROT_SRC_BUF_ADDR(n) (0x30 + ((n) << 2))
44#define ROT_DST_BUF_ADDR(n) (0x50 + ((n) << 2))
45
46/* Buffer Size */
47#define ROT_SRC_BUF_SIZE 0x3c
48#define ROT_DST_BUF_SIZE 0x5c
49#define ROT_SET_BUF_SIZE_H(x) ((x) << 16)
50#define ROT_SET_BUF_SIZE_W(x) ((x) << 0)
51#define ROT_GET_BUF_SIZE_H(x) ((x) >> 16)
52#define ROT_GET_BUF_SIZE_W(x) ((x) & 0xffff)
53
54/* Crop Position */
55#define ROT_SRC_CROP_POS 0x40
56#define ROT_DST_CROP_POS 0x60
57#define ROT_CROP_POS_Y(x) ((x) << 16)
58#define ROT_CROP_POS_X(x) ((x) << 0)
59
60/* Source Crop Size */
61#define ROT_SRC_CROP_SIZE 0x44
62#define ROT_SRC_CROP_SIZE_H(x) ((x) << 16)
63#define ROT_SRC_CROP_SIZE_W(x) ((x) << 0)
64
65/* Round to nearest aligned value */
66#define ROT_ALIGN(x, align, mask) (((x) + (1 << ((align) - 1))) & (mask))
67/* Minimum limit value */
68#define ROT_MIN(min, mask) (((min) + ~(mask)) & (mask))
69/* Maximum limit value */
70#define ROT_MAX(max, mask) ((max) & (mask))
71
72#endif /* EXYNOS_REGS_ROTATOR_H */
73