Commit 62ce272d authored by Sachin Kamat's avatar Sachin Kamat Committed by Mauro Carvalho Chehab

[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: default avatarAjay Kumar <ajaykumar.rs@samsung.com>
Signed-off-by: default avatarSachin Kamat <sachin.kamat@linaro.org>
Acked-by: default avatarKamil Debski <k.debski@samsung.com>
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0e5d61d8
...@@ -28,6 +28,7 @@ void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f) ...@@ -28,6 +28,7 @@ void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f)
{ {
u32 n; u32 n;
w(0, SRC_SELECT_REG);
w(f->stride & 0xFFFF, SRC_STRIDE_REG); w(f->stride & 0xFFFF, SRC_STRIDE_REG);
n = f->o_height & 0xFFF; n = f->o_height & 0xFFF;
...@@ -52,6 +53,7 @@ void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f) ...@@ -52,6 +53,7 @@ void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f)
{ {
u32 n; u32 n;
w(0, DST_SELECT_REG);
w(f->stride & 0xFFFF, DST_STRIDE_REG); w(f->stride & 0xFFFF, DST_STRIDE_REG);
n = f->o_height & 0xFFF; n = f->o_height & 0xFFF;
...@@ -82,10 +84,14 @@ void g2d_set_flip(struct g2d_dev *d, u32 r) ...@@ -82,10 +84,14 @@ void g2d_set_flip(struct g2d_dev *d, u32 r)
w(r, SRC_MSK_DIRECT_REG); w(r, SRC_MSK_DIRECT_REG);
} }
u32 g2d_cmd_stretch(u32 e) void g2d_set_v41_stretch(struct g2d_dev *d, struct g2d_frame *src,
struct g2d_frame *dst)
{ {
e &= 1; w(DEFAULT_SCALE_MODE, SRC_SCALE_CTRL_REG);
return e << 4;
/* inversed scaling factor: src is numerator */
w((src->c_width << 16) / dst->c_width, SRC_XSCALE_REG);
w((src->c_height << 16) / dst->c_height, SRC_YSCALE_REG);
} }
void g2d_set_cmd(struct g2d_dev *d, u32 c) 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,7 +102,9 @@ void g2d_set_cmd(struct g2d_dev *d, u32 c)
void g2d_start(struct g2d_dev *d) void g2d_start(struct g2d_dev *d)
{ {
/* Clear cache */ /* Clear cache */
w(0x7, CACHECTL_REG); if (d->variant->hw_rev == TYPE_G2D_3X)
w(0x7, CACHECTL_REG);
/* Enable interrupt */ /* Enable interrupt */
w(1, INTEN_REG); w(1, INTEN_REG);
/* Start G2D engine */ /* Start G2D engine */
......
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
#define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode reg */ #define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode reg */
#define SRC_LEFT_TOP_REG 0x0310 /* Src Left Top Coordinate reg */ #define SRC_LEFT_TOP_REG 0x0310 /* Src Left Top Coordinate reg */
#define SRC_RIGHT_BOTTOM_REG 0x0314 /* Src Right Bottom Coordinate reg */ #define SRC_RIGHT_BOTTOM_REG 0x0314 /* Src Right Bottom Coordinate reg */
#define SRC_SCALE_CTRL_REG 0x0328 /* Src Scaling type select */
#define SRC_XSCALE_REG 0x032c /* Src X Scaling ratio */
#define SRC_YSCALE_REG 0x0330 /* Src Y Scaling ratio */
/* Parameter Setting Registers (Dest) */ /* Parameter Setting Registers (Dest) */
#define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */ #define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */
...@@ -113,3 +116,7 @@ ...@@ -113,3 +116,7 @@
#define DEFAULT_WIDTH 100 #define DEFAULT_WIDTH 100
#define DEFAULT_HEIGHT 100 #define DEFAULT_HEIGHT 100
#define DEFAULT_SCALE_MODE (2 << 0)
/* Command mode register values */
#define CMD_V3_ENABLE_STRETCH (1 << 4)
...@@ -604,8 +604,13 @@ static void device_run(void *prv) ...@@ -604,8 +604,13 @@ static void device_run(void *prv)
g2d_set_flip(dev, ctx->flip); g2d_set_flip(dev, ctx->flip);
if (ctx->in.c_width != ctx->out.c_width || if (ctx->in.c_width != ctx->out.c_width ||
ctx->in.c_height != ctx->out.c_height) ctx->in.c_height != ctx->out.c_height) {
cmd |= g2d_cmd_stretch(1); if (dev->variant->hw_rev == TYPE_G2D_3X)
cmd |= CMD_V3_ENABLE_STRETCH;
else
g2d_set_v41_stretch(dev, &ctx->in, &ctx->out);
}
g2d_set_cmd(dev, cmd); g2d_set_cmd(dev, cmd);
g2d_start(dev); g2d_start(dev);
...@@ -791,6 +796,7 @@ static int g2d_probe(struct platform_device *pdev) ...@@ -791,6 +796,7 @@ static int g2d_probe(struct platform_device *pdev)
} }
def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
dev->variant = g2d_get_drv_data(pdev);
return 0; return 0;
...@@ -830,9 +836,30 @@ static int g2d_remove(struct platform_device *pdev) ...@@ -830,9 +836,30 @@ static int g2d_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct g2d_variant g2d_drvdata_v3x = {
.hw_rev = TYPE_G2D_3X,
};
static struct g2d_variant g2d_drvdata_v4x = {
.hw_rev = TYPE_G2D_4X, /* Revision 4.1 for Exynos4X12 and Exynos5 */
};
static struct platform_device_id g2d_driver_ids[] = {
{
.name = "s5p-g2d",
.driver_data = (unsigned long)&g2d_drvdata_v3x,
}, {
.name = "s5p-g2d-v4x",
.driver_data = (unsigned long)&g2d_drvdata_v4x,
},
{},
};
MODULE_DEVICE_TABLE(platform, g2d_driver_ids);
static struct platform_driver g2d_pdrv = { static struct platform_driver g2d_pdrv = {
.probe = g2d_probe, .probe = g2d_probe,
.remove = g2d_remove, .remove = g2d_remove,
.id_table = g2d_driver_ids,
.driver = { .driver = {
.name = G2D_NAME, .name = G2D_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -10,10 +10,13 @@ ...@@ -10,10 +10,13 @@
* License, or (at your option) any later version * License, or (at your option) any later version
*/ */
#include <linux/platform_device.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#define G2D_NAME "s5p-g2d" #define G2D_NAME "s5p-g2d"
#define TYPE_G2D_3X 3
#define TYPE_G2D_4X 4
struct g2d_dev { struct g2d_dev {
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
...@@ -27,6 +30,7 @@ struct g2d_dev { ...@@ -27,6 +30,7 @@ struct g2d_dev {
struct clk *clk; struct clk *clk;
struct clk *gate; struct clk *gate;
struct g2d_ctx *curr; struct g2d_ctx *curr;
struct g2d_variant *variant;
int irq; int irq;
wait_queue_head_t irq_queue; wait_queue_head_t irq_queue;
}; };
...@@ -53,7 +57,7 @@ struct g2d_frame { ...@@ -53,7 +57,7 @@ struct g2d_frame {
struct g2d_ctx { struct g2d_ctx {
struct v4l2_fh fh; struct v4l2_fh fh;
struct g2d_dev *dev; struct g2d_dev *dev;
struct v4l2_m2m_ctx *m2m_ctx; struct v4l2_m2m_ctx *m2m_ctx;
struct g2d_frame in; struct g2d_frame in;
struct g2d_frame out; struct g2d_frame out;
struct v4l2_ctrl *ctrl_hflip; struct v4l2_ctrl *ctrl_hflip;
...@@ -70,6 +74,9 @@ struct g2d_fmt { ...@@ -70,6 +74,9 @@ struct g2d_fmt {
u32 hw; u32 hw;
}; };
struct g2d_variant {
unsigned short hw_rev;
};
void g2d_reset(struct g2d_dev *d); void g2d_reset(struct g2d_dev *d);
void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f); 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,7 +87,11 @@ void g2d_start(struct g2d_dev *d);
void g2d_clear_int(struct g2d_dev *d); void g2d_clear_int(struct g2d_dev *d);
void g2d_set_rop4(struct g2d_dev *d, u32 r); void g2d_set_rop4(struct g2d_dev *d, u32 r);
void g2d_set_flip(struct g2d_dev *d, u32 r); void g2d_set_flip(struct g2d_dev *d, u32 r);
u32 g2d_cmd_stretch(u32 e); void g2d_set_v41_stretch(struct g2d_dev *d,
struct g2d_frame *src, struct g2d_frame *dst);
void g2d_set_cmd(struct g2d_dev *d, u32 c); void g2d_set_cmd(struct g2d_dev *d, u32 c);
static inline struct g2d_variant *g2d_get_drv_data(struct platform_device *pdev)
{
return (struct g2d_variant *)platform_get_device_id(pdev)->driver_data;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment