aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/exynos/rotator/rotator-regs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/exynos/rotator/rotator-regs.c')
-rw-r--r--drivers/media/video/exynos/rotator/rotator-regs.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/drivers/media/video/exynos/rotator/rotator-regs.c b/drivers/media/video/exynos/rotator/rotator-regs.c
new file mode 100644
index 0000000..9f983bf
--- /dev/null
+++ b/drivers/media/video/exynos/rotator/rotator-regs.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Register interface file for Exynos Rotator driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include "rotator.h"
+
+void rot_hwset_irq_frame_done(struct rot_dev *rot, u32 enable)
+{
+ unsigned long cfg = readl(rot->regs + ROTATOR_CONFIG);
+
+ if (enable)
+ cfg |= ROTATOR_CONFIG_IRQ_DONE;
+ else
+ cfg &= ~ROTATOR_CONFIG_IRQ_DONE;
+
+ writel(cfg, rot->regs + ROTATOR_CONFIG);
+}
+
+void rot_hwset_irq_illegal_config(struct rot_dev *rot, u32 enable)
+{
+ unsigned long cfg = readl(rot->regs + ROTATOR_CONFIG);
+
+ if (enable)
+ cfg |= ROTATOR_CONFIG_IRQ_ILLEGAL;
+ else
+ cfg &= ~ROTATOR_CONFIG_IRQ_ILLEGAL;
+
+ writel(cfg, rot->regs + ROTATOR_CONFIG);
+}
+
+int rot_hwset_image_format(struct rot_dev *rot, u32 pixelformat)
+{
+ unsigned long cfg = readl(rot->regs + ROTATOR_CONTROL);
+ cfg &= ~ROTATOR_CONTROL_FMT_MASK;
+
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUV420M:
+ cfg |= ROTATOR_CONTROL_FMT_YCBCR420_3P;
+ break;
+ case V4L2_PIX_FMT_NV12M:
+ cfg |= ROTATOR_CONTROL_FMT_YCBCR420_2P;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ cfg |= ROTATOR_CONTROL_FMT_YCBCR422;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ cfg |= ROTATOR_CONTROL_FMT_RGB565;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ cfg |= ROTATOR_CONTROL_FMT_RGB888;
+ break;
+ default:
+ dev_err(rot->dev, "invalid pixelformat type\n");
+ return -EINVAL;
+ }
+ writel(cfg, rot->regs + ROTATOR_CONTROL);
+ return 0;
+}
+
+void rot_hwset_flip(struct rot_dev *rot, u32 direction)
+{
+ unsigned long cfg = readl(rot->regs + ROTATOR_CONTROL);
+ cfg &= ~ROTATOR_CONTROL_FLIP_MASK;
+
+ if (direction == ROT_VFLIP)
+ cfg |= ROTATOR_CONTROL_FLIP_V;
+ else if (direction == ROT_HFLIP)
+ cfg |= ROTATOR_CONTROL_FLIP_H;
+
+ writel(cfg, rot->regs + ROTATOR_CONTROL);
+}
+
+void rot_hwset_rotation(struct rot_dev *rot, int degree)
+{
+ unsigned long cfg = readl(rot->regs + ROTATOR_CONTROL);
+ cfg &= ~ROTATOR_CONTROL_ROT_MASK;
+
+ if (degree == 90)
+ cfg |= ROTATOR_CONTROL_ROT_90;
+ else if (degree == 180)
+ cfg |= ROTATOR_CONTROL_ROT_180;
+ else if (degree == 270)
+ cfg |= ROTATOR_CONTROL_ROT_270;
+
+ writel(cfg, rot->regs + ROTATOR_CONTROL);
+}
+
+void rot_hwset_start(struct rot_dev *rot)
+{
+ unsigned long cfg = readl(rot->regs + ROTATOR_CONTROL);
+
+ cfg |= ROTATOR_CONTROL_START;
+
+ writel(cfg, rot->regs + ROTATOR_CONTROL);
+}
+
+void rot_hwset_src_addr(struct rot_dev *rot, dma_addr_t addr, u32 comp)
+{
+ writel(addr, rot->regs + ROTATOR_SRC_IMG_ADDR(comp));
+}
+
+void rot_hwset_dst_addr(struct rot_dev *rot, dma_addr_t addr, u32 comp)
+{
+ writel(addr, rot->regs + ROTATOR_DST_IMG_ADDR(comp));
+}
+
+void rot_hwset_src_imgsize(struct rot_dev *rot, struct rot_frame *frame)
+{
+ unsigned long cfg;
+
+ cfg = ROTATOR_SRCIMG_YSIZE(frame->pix_mp.height) |
+ ROTATOR_SRCIMG_XSIZE(frame->pix_mp.width);
+
+ writel(cfg, rot->regs + ROTATOR_SRCIMG);
+
+ cfg = ROTATOR_SRCROT_YSIZE(frame->pix_mp.height) |
+ ROTATOR_SRCROT_XSIZE(frame->pix_mp.width);
+
+ writel(cfg, rot->regs + ROTATOR_SRCROT);
+}
+
+void rot_hwset_src_crop(struct rot_dev *rot, struct v4l2_rect *rect)
+{
+ unsigned long cfg;
+
+ cfg = ROTATOR_SRC_Y(rect->top) |
+ ROTATOR_SRC_X(rect->left);
+
+ writel(cfg, rot->regs + ROTATOR_SRC);
+
+ cfg = ROTATOR_SRCROT_YSIZE(rect->height) |
+ ROTATOR_SRCROT_XSIZE(rect->width);
+
+ writel(cfg, rot->regs + ROTATOR_SRCROT);
+}
+
+void rot_hwset_dst_imgsize(struct rot_dev *rot, struct rot_frame *frame)
+{
+ unsigned long cfg;
+
+ cfg = ROTATOR_DSTIMG_YSIZE(frame->pix_mp.height) |
+ ROTATOR_DSTIMG_XSIZE(frame->pix_mp.width);
+
+ writel(cfg, rot->regs + ROTATOR_DSTIMG);
+}
+
+void rot_hwset_dst_crop(struct rot_dev *rot, struct v4l2_rect *rect)
+{
+ unsigned long cfg;
+
+ cfg = ROTATOR_DST_Y(rect->top) |
+ ROTATOR_DST_X(rect->left);
+
+ writel(cfg, rot->regs + ROTATOR_DST);
+}
+
+void rot_hwget_irq_src(struct rot_dev *rot, enum rot_irq_src *irq)
+{
+ unsigned long cfg = readl(rot->regs + ROTATOR_STATUS);
+ cfg = ROTATOR_STATUS_IRQ(cfg);
+
+ if (cfg == 1)
+ *irq = ISR_PEND_DONE;
+ else if (cfg == 2)
+ *irq = ISR_PEND_ILLEGAL;
+}
+
+void rot_hwset_irq_clear(struct rot_dev *rot, enum rot_irq_src *irq)
+{
+ unsigned long cfg = readl(rot->regs + ROTATOR_STATUS);
+ cfg |= ROTATOR_STATUS_IRQ_PENDING((u32)irq);
+
+ writel(cfg, rot->regs + ROTATOR_STATUS);
+}
+
+void rot_hwget_status(struct rot_dev *rot, enum rot_status *state)
+{
+ unsigned long cfg;
+
+ cfg = readl(rot->regs + ROTATOR_STATUS);
+ cfg &= ROTATOR_STATUS_MASK;
+
+ switch (cfg) {
+ case 0:
+ *state = ROT_IDLE;
+ break;
+ case 1:
+ *state = ROT_RESERVED;
+ break;
+ case 2:
+ *state = ROT_RUNNING;
+ break;
+ case 3:
+ *state = ROT_RUNNING_REMAIN;
+ break;
+ };
+}
+
+void rot_dump_registers(struct rot_dev *rot)
+{
+ unsigned int tmp, i;
+
+ rot_dbg("dump rotator registers\n");
+ for (i = 0; i <= ROTATOR_DST; i += 0x4) {
+ tmp = readl(rot->regs + i);
+ rot_dbg("0x%08x: 0x%08x", i, tmp);
+ }
+}