Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+12 −4
Original line number Original line Diff line number Diff line
@@ -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)
{
{
	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)
	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)
void g2d_start(struct g2d_dev *d)
void g2d_start(struct g2d_dev *d)
{
{
	/* Clear cache */
	/* Clear cache */
	if (d->variant->hw_rev == TYPE_G2D_3X)
		w(0x7, CACHECTL_REG);
		w(0x7, CACHECTL_REG);

	/* Enable interrupt */
	/* Enable interrupt */
	w(1, INTEN_REG);
	w(1, INTEN_REG);
	/* Start G2D engine */
	/* Start G2D engine */
+7 −0
Original line number Original line Diff line number Diff line
@@ -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 @@
#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)
+29 −2
Original line number Original line Diff line number Diff line
@@ -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)
	}
	}


	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)
	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,
+14 −3
Original line number Original line Diff line number Diff line
@@ -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 {
	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;
};
};
@@ -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);
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;
}