summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/s5p-g2d
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-24 17:35:10 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-24 17:35:10 -0800
commit21fbd5809ad126b949206d78e0a0e07ec872ea11 (patch)
treea824045df99fc1f0690095a925cceb50207e332b /drivers/media/platform/s5p-g2d
parentd9978ec5680059d727b39d6c706777c6973587f2 (diff)
parented72d37a33fdf43dc47787fe220532cdec9da528 (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - Some cleanups at V4L2 documentation - new drivers: ts2020 frontend, ov9650 sensor, s5c73m3 sensor, sh-mobile veu mem2mem driver, radio-ma901, davinci_vpfe staging driver - Lots of missing MAINTAINERS entries added - several em28xx driver improvements, including its conversion to videobuf2 - several fixups on drivers to make them to better comply with the API - DVB core: add support for DVBv5 stats, allowing the implementation of statistics for new standards like ISDB - mb86a20s: add statistics to the driver - lots of new board additions, cleanups, and driver improvements. * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (596 commits) [media] media: Add 0x3009 USB PID to ttusb2 driver (fixed diff) [media] rtl28xxu: Add USB IDs for Compro VideoMate U620F [media] em28xx: add usb id for terratec h5 rev. 3 [media] media: rc: gpio-ir-recv: add support for device tree parsing [media] mceusb: move check earlier to make smatch happy [media] radio-si470x doc: add info about v4l2-ctl and sox+alsa [media] staging: media: Remove unnecessary OOM messages [media] sh_vou: Use vou_dev instead of vou_file wherever possible [media] sh_vou: Use video_drvdata() [media] drivers/media/platform/soc_camera/pxa_camera.c: use devm_ functions [media] mt9t112: mt9t111 format set up differs from mt9t112 [media] sh-mobile-ceu-camera: fix SHARPNESS control default Revert "[media] fc0011: Return early, if the frequency is already tuned" [media] cx18/ivtv: fix regression: remove __init from a non-init function [media] em28xx: fix analog streaming with USB bulk transfers [media] stv0900: remove unnecessary null pointer check [media] fc0011: Return early, if the frequency is already tuned [media] fc0011: Add some sanity checks and cleanups [media] fc0011: Fix xin value clamping Revert "[media] [PATH,1/2] mxl5007 move reset to attach" ...
Diffstat (limited to 'drivers/media/platform/s5p-g2d')
-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.c35
-rw-r--r--drivers/media/platform/s5p-g2d/g2d.h17
4 files changed, 64 insertions, 11 deletions
diff --git a/drivers/media/platform/s5p-g2d/g2d-hw.c b/drivers/media/platform/s5p-g2d/g2d-hw.c
index 5b86cbe408e..e87bd93811d 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)
{
u32 n;
+ w(0, SRC_SELECT_REG);
w(f->stride & 0xFFFF, SRC_STRIDE_REG);
n = f->o_height & 0xFFF;
@@ -52,6 +53,7 @@ void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f)
{
u32 n;
+ w(0, DST_SELECT_REG);
w(f->stride & 0xFFFF, DST_STRIDE_REG);
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);
}
-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;
- return e << 4;
+ w(DEFAULT_SCALE_MODE, SRC_SCALE_CTRL_REG);
+
+ /* 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)
@@ -96,7 +102,9 @@ void g2d_set_cmd(struct g2d_dev *d, u32 c)
void g2d_start(struct g2d_dev *d)
{
/* Clear cache */
- w(0x7, CACHECTL_REG);
+ if (d->variant->hw_rev == TYPE_G2D_3X)
+ w(0x7, CACHECTL_REG);
+
/* Enable interrupt */
w(1, INTEN_REG);
/* Start G2D engine */
diff --git a/drivers/media/platform/s5p-g2d/g2d-regs.h b/drivers/media/platform/s5p-g2d/g2d-regs.h
index 02e1cf50da4..9bf31ad35d4 100644
--- a/drivers/media/platform/s5p-g2d/g2d-regs.h
+++ b/drivers/media/platform/s5p-g2d/g2d-regs.h
@@ -35,6 +35,9 @@
#define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode 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_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) */
#define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */
@@ -113,3 +116,7 @@
#define DEFAULT_WIDTH 100
#define DEFAULT_HEIGHT 100
+#define DEFAULT_SCALE_MODE (2 << 0)
+
+/* Command mode register values */
+#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 6ed259fb104..aaaf276a5a6 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)
g2d_set_flip(dev, ctx->flip);
if (ctx->in.c_width != ctx->out.c_width ||
- ctx->in.c_height != ctx->out.c_height)
- cmd |= g2d_cmd_stretch(1);
+ ctx->in.c_height != ctx->out.c_height) {
+ 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_start(dev);
@@ -713,7 +718,7 @@ static int g2d_probe(struct platform_device *pdev)
return PTR_ERR(dev->regs);
dev->clk = clk_get(&pdev->dev, "sclk_fimg2d");
- if (IS_ERR_OR_NULL(dev->clk)) {
+ if (IS_ERR(dev->clk)) {
dev_err(&pdev->dev, "failed to get g2d clock\n");
return -ENXIO;
}
@@ -725,7 +730,7 @@ static int g2d_probe(struct platform_device *pdev)
}
dev->gate = clk_get(&pdev->dev, "fimg2d");
- if (IS_ERR_OR_NULL(dev->gate)) {
+ if (IS_ERR(dev->gate)) {
dev_err(&pdev->dev, "failed to get g2d clock gate\n");
ret = -ENXIO;
goto unprep_clk;
@@ -789,6 +794,7 @@ static int g2d_probe(struct platform_device *pdev)
}
def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
+ dev->variant = g2d_get_drv_data(pdev);
return 0;
@@ -828,9 +834,30 @@ static int g2d_remove(struct platform_device *pdev)
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 = {
.probe = g2d_probe,
.remove = g2d_remove,
+ .id_table = g2d_driver_ids,
.driver = {
.name = G2D_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/media/platform/s5p-g2d/g2d.h b/drivers/media/platform/s5p-g2d/g2d.h
index 6b765b0216c..300ca05ba40 100644
--- a/drivers/media/platform/s5p-g2d/g2d.h
+++ b/drivers/media/platform/s5p-g2d/g2d.h
@@ -10,10 +10,13 @@
* License, or (at your option) any later version
*/
+#include <linux/platform_device.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
#define G2D_NAME "s5p-g2d"
+#define TYPE_G2D_3X 3
+#define TYPE_G2D_4X 4
struct g2d_dev {
struct v4l2_device v4l2_dev;
@@ -27,6 +30,7 @@ struct g2d_dev {
struct clk *clk;
struct clk *gate;
struct g2d_ctx *curr;
+ struct g2d_variant *variant;
int irq;
wait_queue_head_t irq_queue;
};
@@ -53,7 +57,7 @@ struct g2d_frame {
struct g2d_ctx {
struct v4l2_fh fh;
struct g2d_dev *dev;
- struct v4l2_m2m_ctx *m2m_ctx;
+ struct v4l2_m2m_ctx *m2m_ctx;
struct g2d_frame in;
struct g2d_frame out;
struct v4l2_ctrl *ctrl_hflip;
@@ -70,6 +74,9 @@ struct g2d_fmt {
u32 hw;
};
+struct g2d_variant {
+ unsigned short hw_rev;
+};
void g2d_reset(struct g2d_dev *d);
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_set_rop4(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);
-
+static inline struct g2d_variant *g2d_get_drv_data(struct platform_device *pdev)
+{
+ return (struct g2d_variant *)platform_get_device_id(pdev)->driver_data;
+}