aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform
diff options
context:
space:
mode:
authorSachin Kamat <sachin.kamat@linaro.org>2013-01-16 22:07:18 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-02-05 14:30:14 -0500
commit62ce272d87f09f34f70a9b3f783783af6c1a09d8 (patch)
tree7948ec1c0b9daaaae985b92aefaf362a74007d83 /drivers/media/platform
parent0e5d61d87b3a1ad5591e0dfbe4c548f862e9f5a6 (diff)
[media] s5p-g2d: Add support for G2D H/W Rev.4.1
Modified the G2D driver (which initially supported only H/W Rev.3) to support H/W Rev.4.1 present on Exynos4x12 and Exynos52x0 SOCs. - Set the SRC and DST type to 'memory' instead of using reset values. - FIMG2D v4.1 H/W uses different logic for stretching(scaling). - Use CACHECTL_REG only with FIMG2D v3. [s.nawrocki: removed empty line at end of file]] Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com> Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org> Acked-by: Kamil Debski <k.debski@samsung.com> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/platform')
-rw-r--r--drivers/media/platform/s5p-g2d/g2d-hw.c16
-rw-r--r--drivers/media/platform/s5p-g2d/g2d-regs.h7
-rw-r--r--drivers/media/platform/s5p-g2d/g2d.c31
-rw-r--r--drivers/media/platform/s5p-g2d/g2d.h17
4 files changed, 62 insertions, 9 deletions
diff --git a/drivers/media/platform/s5p-g2d/g2d-hw.c b/drivers/media/platform/s5p-g2d/g2d-hw.c
index 5b86cbe408e2..e87bd93811d4 100644
--- a/drivers/media/platform/s5p-g2d/g2d-hw.c
+++ b/drivers/media/platform/s5p-g2d/g2d-hw.c
@@ -28,6 +28,7 @@ void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f)
28{ 28{
29 u32 n; 29 u32 n;
30 30
31 w(0, SRC_SELECT_REG);
31 w(f->stride & 0xFFFF, SRC_STRIDE_REG); 32 w(f->stride & 0xFFFF, SRC_STRIDE_REG);
32 33
33 n = f->o_height & 0xFFF; 34 n = f->o_height & 0xFFF;
@@ -52,6 +53,7 @@ void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f)
52{ 53{
53 u32 n; 54 u32 n;
54 55
56 w(0, DST_SELECT_REG);
55 w(f->stride & 0xFFFF, DST_STRIDE_REG); 57 w(f->stride & 0xFFFF, DST_STRIDE_REG);
56 58
57 n = f->o_height & 0xFFF; 59 n = f->o_height & 0xFFF;
@@ -82,10 +84,14 @@ void g2d_set_flip(struct g2d_dev *d, u32 r)
82 w(r, SRC_MSK_DIRECT_REG); 84 w(r, SRC_MSK_DIRECT_REG);
83} 85}
84 86
85u32 g2d_cmd_stretch(u32 e) 87void g2d_set_v41_stretch(struct g2d_dev *d, struct g2d_frame *src,
88 struct g2d_frame *dst)
86{ 89{
87 e &= 1; 90 w(DEFAULT_SCALE_MODE, SRC_SCALE_CTRL_REG);
88 return e << 4; 91
92 /* inversed scaling factor: src is numerator */
93 w((src->c_width << 16) / dst->c_width, SRC_XSCALE_REG);
94 w((src->c_height << 16) / dst->c_height, SRC_YSCALE_REG);
89} 95}
90 96
91void g2d_set_cmd(struct g2d_dev *d, u32 c) 97void g2d_set_cmd(struct g2d_dev *d, u32 c)
@@ -96,7 +102,9 @@ void g2d_set_cmd(struct g2d_dev *d, u32 c)
96void g2d_start(struct g2d_dev *d) 102void g2d_start(struct g2d_dev *d)
97{ 103{
98 /* Clear cache */ 104 /* Clear cache */
99 w(0x7, CACHECTL_REG); 105 if (d->variant->hw_rev == TYPE_G2D_3X)
106 w(0x7, CACHECTL_REG);
107
100 /* Enable interrupt */ 108 /* Enable interrupt */
101 w(1, INTEN_REG); 109 w(1, INTEN_REG);
102 /* Start G2D engine */ 110 /* Start G2D engine */
diff --git a/drivers/media/platform/s5p-g2d/g2d-regs.h b/drivers/media/platform/s5p-g2d/g2d-regs.h
index 02e1cf50da4e..9bf31ad35d47 100644
--- a/drivers/media/platform/s5p-g2d/g2d-regs.h
+++ b/drivers/media/platform/s5p-g2d/g2d-regs.h
@@ -35,6 +35,9 @@
35#define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode reg */ 35#define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode reg */
36#define SRC_LEFT_TOP_REG 0x0310 /* Src Left Top Coordinate reg */ 36#define SRC_LEFT_TOP_REG 0x0310 /* Src Left Top Coordinate reg */
37#define SRC_RIGHT_BOTTOM_REG 0x0314 /* Src Right Bottom Coordinate reg */ 37#define SRC_RIGHT_BOTTOM_REG 0x0314 /* Src Right Bottom Coordinate reg */
38#define SRC_SCALE_CTRL_REG 0x0328 /* Src Scaling type select */
39#define SRC_XSCALE_REG 0x032c /* Src X Scaling ratio */
40#define SRC_YSCALE_REG 0x0330 /* Src Y Scaling ratio */
38 41
39/* Parameter Setting Registers (Dest) */ 42/* Parameter Setting Registers (Dest) */
40#define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */ 43#define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */
@@ -113,3 +116,7 @@
113#define DEFAULT_WIDTH 100 116#define DEFAULT_WIDTH 100
114#define DEFAULT_HEIGHT 100 117#define DEFAULT_HEIGHT 100
115 118
119#define DEFAULT_SCALE_MODE (2 << 0)
120
121/* Command mode register values */
122#define CMD_V3_ENABLE_STRETCH (1 << 4)
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index dcd53357704d..7e415297e174 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -604,8 +604,13 @@ static void device_run(void *prv)
604 g2d_set_flip(dev, ctx->flip); 604 g2d_set_flip(dev, ctx->flip);
605 605
606 if (ctx->in.c_width != ctx->out.c_width || 606 if (ctx->in.c_width != ctx->out.c_width ||
607 ctx->in.c_height != ctx->out.c_height) 607 ctx->in.c_height != ctx->out.c_height) {
608 cmd |= g2d_cmd_stretch(1); 608 if (dev->variant->hw_rev == TYPE_G2D_3X)
609 cmd |= CMD_V3_ENABLE_STRETCH;
610 else
611 g2d_set_v41_stretch(dev, &ctx->in, &ctx->out);
612 }
613
609 g2d_set_cmd(dev, cmd); 614 g2d_set_cmd(dev, cmd);
610 g2d_start(dev); 615 g2d_start(dev);
611 616
@@ -791,6 +796,7 @@ static int g2d_probe(struct platform_device *pdev)
791 } 796 }
792 797
793 def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; 798 def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
799 dev->variant = g2d_get_drv_data(pdev);
794 800
795 return 0; 801 return 0;
796 802
@@ -830,9 +836,30 @@ static int g2d_remove(struct platform_device *pdev)
830 return 0; 836 return 0;
831} 837}
832 838
839static struct g2d_variant g2d_drvdata_v3x = {
840 .hw_rev = TYPE_G2D_3X,
841};
842
843static struct g2d_variant g2d_drvdata_v4x = {
844 .hw_rev = TYPE_G2D_4X, /* Revision 4.1 for Exynos4X12 and Exynos5 */
845};
846
847static struct platform_device_id g2d_driver_ids[] = {
848 {
849 .name = "s5p-g2d",
850 .driver_data = (unsigned long)&g2d_drvdata_v3x,
851 }, {
852 .name = "s5p-g2d-v4x",
853 .driver_data = (unsigned long)&g2d_drvdata_v4x,
854 },
855 {},
856};
857MODULE_DEVICE_TABLE(platform, g2d_driver_ids);
858
833static struct platform_driver g2d_pdrv = { 859static struct platform_driver g2d_pdrv = {
834 .probe = g2d_probe, 860 .probe = g2d_probe,
835 .remove = g2d_remove, 861 .remove = g2d_remove,
862 .id_table = g2d_driver_ids,
836 .driver = { 863 .driver = {
837 .name = G2D_NAME, 864 .name = G2D_NAME,
838 .owner = THIS_MODULE, 865 .owner = THIS_MODULE,
diff --git a/drivers/media/platform/s5p-g2d/g2d.h b/drivers/media/platform/s5p-g2d/g2d.h
index 6b765b0216c5..300ca05ba404 100644
--- a/drivers/media/platform/s5p-g2d/g2d.h
+++ b/drivers/media/platform/s5p-g2d/g2d.h
@@ -10,10 +10,13 @@
10 * License, or (at your option) any later version 10 * License, or (at your option) any later version
11 */ 11 */
12 12
13#include <linux/platform_device.h>
13#include <media/v4l2-device.h> 14#include <media/v4l2-device.h>
14#include <media/v4l2-ctrls.h> 15#include <media/v4l2-ctrls.h>
15 16
16#define G2D_NAME "s5p-g2d" 17#define G2D_NAME "s5p-g2d"
18#define TYPE_G2D_3X 3
19#define TYPE_G2D_4X 4
17 20
18struct g2d_dev { 21struct g2d_dev {
19 struct v4l2_device v4l2_dev; 22 struct v4l2_device v4l2_dev;
@@ -27,6 +30,7 @@ struct g2d_dev {
27 struct clk *clk; 30 struct clk *clk;
28 struct clk *gate; 31 struct clk *gate;
29 struct g2d_ctx *curr; 32 struct g2d_ctx *curr;
33 struct g2d_variant *variant;
30 int irq; 34 int irq;
31 wait_queue_head_t irq_queue; 35 wait_queue_head_t irq_queue;
32}; 36};
@@ -53,7 +57,7 @@ struct g2d_frame {
53struct g2d_ctx { 57struct g2d_ctx {
54 struct v4l2_fh fh; 58 struct v4l2_fh fh;
55 struct g2d_dev *dev; 59 struct g2d_dev *dev;
56 struct v4l2_m2m_ctx *m2m_ctx; 60 struct v4l2_m2m_ctx *m2m_ctx;
57 struct g2d_frame in; 61 struct g2d_frame in;
58 struct g2d_frame out; 62 struct g2d_frame out;
59 struct v4l2_ctrl *ctrl_hflip; 63 struct v4l2_ctrl *ctrl_hflip;
@@ -70,6 +74,9 @@ struct g2d_fmt {
70 u32 hw; 74 u32 hw;
71}; 75};
72 76
77struct g2d_variant {
78 unsigned short hw_rev;
79};
73 80
74void g2d_reset(struct g2d_dev *d); 81void g2d_reset(struct g2d_dev *d);
75void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f); 82void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f);
@@ -80,7 +87,11 @@ void g2d_start(struct g2d_dev *d);
80void g2d_clear_int(struct g2d_dev *d); 87void g2d_clear_int(struct g2d_dev *d);
81void g2d_set_rop4(struct g2d_dev *d, u32 r); 88void g2d_set_rop4(struct g2d_dev *d, u32 r);
82void g2d_set_flip(struct g2d_dev *d, u32 r); 89void g2d_set_flip(struct g2d_dev *d, u32 r);
83u32 g2d_cmd_stretch(u32 e); 90void g2d_set_v41_stretch(struct g2d_dev *d,
91 struct g2d_frame *src, struct g2d_frame *dst);
84void g2d_set_cmd(struct g2d_dev *d, u32 c); 92void g2d_set_cmd(struct g2d_dev *d, u32 c);
85 93
86 94static inline struct g2d_variant *g2d_get_drv_data(struct platform_device *pdev)
95{
96 return (struct g2d_variant *)platform_get_device_id(pdev)->driver_data;
97}