diff options
author | Sachin Kamat <sachin.kamat@linaro.org> | 2013-01-16 22:07:18 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-02-05 14:30:14 -0500 |
commit | 62ce272d87f09f34f70a9b3f783783af6c1a09d8 (patch) | |
tree | 7948ec1c0b9daaaae985b92aefaf362a74007d83 /drivers/media/platform | |
parent | 0e5d61d87b3a1ad5591e0dfbe4c548f862e9f5a6 (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.c | 16 | ||||
-rw-r--r-- | drivers/media/platform/s5p-g2d/g2d-regs.h | 7 | ||||
-rw-r--r-- | drivers/media/platform/s5p-g2d/g2d.c | 31 | ||||
-rw-r--r-- | drivers/media/platform/s5p-g2d/g2d.h | 17 |
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 | ||
85 | u32 g2d_cmd_stretch(u32 e) | 87 | void 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 | ||
91 | void g2d_set_cmd(struct g2d_dev *d, u32 c) | 97 | void g2d_set_cmd(struct g2d_dev *d, u32 c) |
@@ -96,7 +102,9 @@ void g2d_set_cmd(struct g2d_dev *d, u32 c) | |||
96 | void g2d_start(struct g2d_dev *d) | 102 | void 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 | ||
839 | static struct g2d_variant g2d_drvdata_v3x = { | ||
840 | .hw_rev = TYPE_G2D_3X, | ||
841 | }; | ||
842 | |||
843 | static struct g2d_variant g2d_drvdata_v4x = { | ||
844 | .hw_rev = TYPE_G2D_4X, /* Revision 4.1 for Exynos4X12 and Exynos5 */ | ||
845 | }; | ||
846 | |||
847 | static 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 | }; | ||
857 | MODULE_DEVICE_TABLE(platform, g2d_driver_ids); | ||
858 | |||
833 | static struct platform_driver g2d_pdrv = { | 859 | static 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 | ||
18 | struct g2d_dev { | 21 | struct 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 { | |||
53 | struct g2d_ctx { | 57 | struct 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 | ||
77 | struct g2d_variant { | ||
78 | unsigned short hw_rev; | ||
79 | }; | ||
73 | 80 | ||
74 | void g2d_reset(struct g2d_dev *d); | 81 | void g2d_reset(struct g2d_dev *d); |
75 | void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f); | 82 | void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f); |
@@ -80,7 +87,11 @@ void g2d_start(struct g2d_dev *d); | |||
80 | void g2d_clear_int(struct g2d_dev *d); | 87 | void g2d_clear_int(struct g2d_dev *d); |
81 | void g2d_set_rop4(struct g2d_dev *d, u32 r); | 88 | void g2d_set_rop4(struct g2d_dev *d, u32 r); |
82 | void g2d_set_flip(struct g2d_dev *d, u32 r); | 89 | void g2d_set_flip(struct g2d_dev *d, u32 r); |
83 | u32 g2d_cmd_stretch(u32 e); | 90 | void g2d_set_v41_stretch(struct g2d_dev *d, |
91 | struct g2d_frame *src, struct g2d_frame *dst); | ||
84 | void g2d_set_cmd(struct g2d_dev *d, u32 c); | 92 | void g2d_set_cmd(struct g2d_dev *d, u32 c); |
85 | 93 | ||
86 | 94 | static 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 | } | ||