aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc/fimc-reg.c
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
commitc6da2cfeb05178a11c6d062a06f8078150ee492f (patch)
treef3b4021d252c52d6463a9b3c1bb7245e399b009c /drivers/media/video/s5p-fimc/fimc-reg.c
parentc6d7c4dbff353eac7919342ae6b3299a378160a6 (diff)
downloadkernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2
samsung update 1
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-reg.c')
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c255
1 files changed, 225 insertions, 30 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
index 4893b2d..5c8354d 100644
--- a/drivers/media/video/s5p-fimc/fimc-reg.c
+++ b/drivers/media/video/s5p-fimc/fimc-reg.c
@@ -14,10 +14,8 @@
#include <linux/delay.h>
#include <mach/map.h>
#include <media/s5p_fimc.h>
-
#include "fimc-core.h"
-
void fimc_hw_reset(struct fimc_dev *dev)
{
u32 cfg;
@@ -35,6 +33,19 @@ void fimc_hw_reset(struct fimc_dev *dev)
cfg = readl(dev->regs + S5P_CIGCTRL);
cfg &= ~S5P_CIGCTRL_SWRST;
writel(cfg, dev->regs + S5P_CIGCTRL);
+ /* Clear LASTCAPT_END bit : This is for Exynos4210 EVT1 */
+ cfg = readl(dev->regs + S5P_CISTATUS);
+ cfg &= ~S5P_CISTATUS_LASTCAPT_END;
+ writel(cfg, dev->regs + S5P_CISTATUS);
+}
+
+void fimc_hw_set_irq_level(struct fimc_dev *dev)
+{
+ u32 cfg;
+ cfg = readl(dev->regs + S5P_CIGCTRL);
+ cfg |= S5P_CIGCTRL_IRQ_LEVEL;
+
+ writel(cfg, dev->regs + S5P_CIGCTRL);
}
static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
@@ -118,22 +129,26 @@ void fimc_hw_set_rotation(struct fimc_ctx *ctx)
void fimc_hw_set_target_format(struct fimc_ctx *ctx)
{
- u32 cfg;
+ u32 cfg, cfg_ext;
struct fimc_dev *dev = ctx->fimc_dev;
struct fimc_frame *frame = &ctx->d_frame;
dbg("w= %d, h= %d color: %d", frame->width,
frame->height, frame->fmt->color);
+ cfg_ext = readl(dev->regs + S5P_CIEXTEN);
+ cfg_ext &= ~(S5P_CIEXTEN_TRGHSIZE_EXT_MASK |
+ S5P_CIEXTEN_TRGVSIZE_EXT_MASK);
cfg = readl(dev->regs + S5P_CITRGFMT);
cfg &= ~(S5P_CITRGFMT_FMT_MASK | S5P_CITRGFMT_HSIZE_MASK |
S5P_CITRGFMT_VSIZE_MASK);
switch (frame->fmt->color) {
- case S5P_FIMC_RGB565...S5P_FIMC_RGB888:
+ case S5P_FIMC_RGB565...S5P_FIMC_RGB444:
cfg |= S5P_CITRGFMT_RGB;
break;
- case S5P_FIMC_YCBCR420:
+ case S5P_FIMC_YCBCR420: /* fall through */
+ case S5P_FIMC_YCRCB420:
cfg |= S5P_CITRGFMT_YCBCR420;
break;
case S5P_FIMC_YCBYCR422...S5P_FIMC_CRYCBY422:
@@ -149,16 +164,26 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx)
if (ctx->rotation == 90 || ctx->rotation == 270) {
cfg |= S5P_CITRGFMT_HSIZE(frame->height);
cfg |= S5P_CITRGFMT_VSIZE(frame->width);
+ cfg_ext |= S5P_CIEXTEN_TRGHSIZE_EXT(frame->height);
+ cfg_ext |= S5P_CIEXTEN_TRGVSIZE_EXT(frame->width);
} else {
cfg |= S5P_CITRGFMT_HSIZE(frame->width);
cfg |= S5P_CITRGFMT_VSIZE(frame->height);
+ cfg_ext |= S5P_CIEXTEN_TRGHSIZE_EXT(frame->width);
+ cfg_ext |= S5P_CIEXTEN_TRGVSIZE_EXT(frame->height);
}
writel(cfg, dev->regs + S5P_CITRGFMT);
+ writel(cfg_ext, dev->regs + S5P_CIEXTEN);
cfg = readl(dev->regs + S5P_CITAREA) & ~S5P_CITAREA_MASK;
+
+ if (frame->fmt->fourcc == V4L2_PIX_FMT_JPEG)
+ cfg |= frame->payload[0];
+ else
cfg |= (frame->width * frame->height);
+
writel(cfg, dev->regs + S5P_CITAREA);
}
@@ -211,7 +236,7 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
cfg = readl(dev->regs + S5P_CIOCTRL);
cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
- S5P_CIOCTRL_YCBCR_PLANE_MASK);
+ S5P_CIOCTRL_YCBCR_PLANE_MASK | S5P_CIOCTRL_RGB16FMT_MASK);
if (frame->fmt->colplanes == 1)
cfg |= ctx->out_order_1p;
@@ -220,6 +245,15 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
else if (frame->fmt->colplanes == 3)
cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
+ if (frame->fmt->color == S5P_FIMC_RGB565)
+ cfg |= S5P_CIOCTRL_RGB565;
+ else if (frame->fmt->color == S5P_FIMC_RGB555)
+ cfg |= S5P_CIOCTRL_ARGB1555;
+ else if (frame->fmt->color == S5P_FIMC_RGB444)
+ cfg |= S5P_CIOCTRL_ARGB4444;
+ else if (frame->fmt->color == S5P_FIMC_YCRCB420)
+ cfg |= S5P_CIOCTRL_ORDER422_2P_LSB_CBCR;
+
writel(cfg, dev->regs + S5P_CIOCTRL);
}
@@ -295,14 +329,18 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
}
if (ctx->out_path == FIMC_DMA) {
- if (dst_frame->fmt->color == S5P_FIMC_RGB565)
+ if ((dst_frame->fmt->color == S5P_FIMC_RGB565)
+ | (dst_frame->fmt->color == S5P_FIMC_RGB555)
+ | (dst_frame->fmt->color == S5P_FIMC_RGB444))
cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565;
else if (dst_frame->fmt->color == S5P_FIMC_RGB666)
cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666;
else if (dst_frame->fmt->color == S5P_FIMC_RGB888)
cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
+ cfg &= ~S5P_CISCCTRL_LCDPATHEN_FIFO;
} else {
- cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
+ cfg |= (S5P_CISCCTRL_OUTRGB_FMT_RGB888
+ | S5P_CISCCTRL_LCDPATHEN_FIFO);
if (ctx->flags & FIMC_SCAN_MODE_INTERLACED)
cfg |= S5P_CISCCTRL_INTERLACE;
@@ -356,7 +394,7 @@ void fimc_hw_en_capture(struct fimc_ctx *ctx)
/* one shot mode */
cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN;
} else {
- /* Continuous frame capture mode (freerun). */
+ /* Continous frame capture mode (freerun). */
cfg &= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE |
S5P_CIIMGCPT_CPT_FRMOD_CNT);
cfg |= S5P_CIIMGCPT_IMGCPTEN;
@@ -372,7 +410,7 @@ void fimc_hw_set_effect(struct fimc_ctx *ctx)
{
struct fimc_dev *dev = ctx->fimc_dev;
struct fimc_effect *effect = &ctx->effect;
- u32 cfg = (S5P_CIIMGEFF_IE_ENABLE | S5P_CIIMGEFF_IE_SC_AFTER);
+ u32 cfg = S5P_CIIMGEFF_IE_SC_AFTER;
cfg |= effect->type;
@@ -384,6 +422,23 @@ void fimc_hw_set_effect(struct fimc_ctx *ctx)
writel(cfg, dev->regs + S5P_CIIMGEFF);
}
+void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_frame *frame = &ctx->d_frame;
+ u32 cfg;
+
+ if (!((frame->fmt->color == S5P_FIMC_RGB555)
+ | (frame->fmt->color == S5P_FIMC_RGB444)
+ | (frame->fmt->color == S5P_FIMC_RGB888)))
+ return;
+
+ cfg = readl(dev->regs + S5P_CIOCTRL);
+ cfg &= ~S5P_CIOCTRL_ALPHA_OUT_MASK;
+ cfg |= (frame->alpha << 4);
+ writel(cfg, dev->regs + S5P_CIOCTRL);
+}
+
static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
{
struct fimc_dev *dev = ctx->fimc_dev;
@@ -445,7 +500,8 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
case S5P_FIMC_RGB565...S5P_FIMC_RGB888:
cfg |= S5P_MSCTRL_INFORMAT_RGB;
break;
- case S5P_FIMC_YCBCR420:
+ case S5P_FIMC_YCBCR420: /* fall through */
+ case S5P_FIMC_YCRCB420:
cfg |= S5P_MSCTRL_INFORMAT_YCBCR420;
if (frame->fmt->colplanes == 2)
@@ -453,6 +509,8 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
else
cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
+ if (frame->fmt->color == S5P_FIMC_YCRCB420)
+ cfg |= S5P_MSCTRL_2P_IN_YCRCB;
break;
case S5P_FIMC_YCBYCR422...S5P_FIMC_CRYCBY422:
if (frame->fmt->colplanes == 1) {
@@ -541,6 +599,18 @@ void fimc_hw_set_output_addr(struct fimc_dev *dev,
} while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
}
+int fimc_hw_save_output_addr(struct fimc_dev *fimc)
+{
+ int i;
+ for (i = 0; i < FIMC_MAX_OUT_BUFS; i++) {
+ fimc->paddr[i].y = readl(fimc->regs + S5P_CIOYSA(i));
+ fimc->paddr[i].cb = readl(fimc->regs + S5P_CIOCBSA(i));
+ fimc->paddr[i].cr = readl(fimc->regs + S5P_CIOCRSA(i));
+ }
+
+ return 0;
+}
+
int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
struct s5p_fimc_isp_info *cam)
{
@@ -573,7 +643,6 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
u32 cfg = 0;
u32 bus_width;
int i;
-
static const struct {
u32 pixelcode;
u32 cisrcfmt;
@@ -585,6 +654,8 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
{ V4L2_MBUS_FMT_UYVY8_2X8, S5P_CISRCFMT_ORDER422_CBYCRY, 8 },
/* TODO: Add pixel codes for 16-bit bus width */
};
+ dbg("f->o_width : %d, f->o_height : %d\n", f->o_width, f->o_height);
+ dbg("code : %d\n", fimc->vid_cap.fmt.code);
if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) {
for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
@@ -608,9 +679,18 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
else if (bus_width == 16)
cfg |= S5P_CISRCFMT_ITU601_16BIT;
} /* else defaults to ITU-R BT.656 8-bit */
+ } else if (cam->bus_type == FIMC_MIPI_CSI2) {
+ if (fimc_fmt_is_jpeg(f->fmt->color) || fimc->vid_cap.is.sd
+ || fimc->vid_cap.is.camcording)
+ cfg |= S5P_CISRCFMT_ITU601_8BIT;
}
- cfg |= S5P_CISRCFMT_HSIZE(f->o_width) | S5P_CISRCFMT_VSIZE(f->o_height);
+ if (fimc->vid_cap.is.sd || fimc->vid_cap.is.camcording)
+ cfg |= S5P_CISRCFMT_HSIZE(fimc->vid_cap.is.fmt.width) |
+ S5P_CISRCFMT_VSIZE(fimc->vid_cap.is.fmt.height);
+ else
+ cfg |= S5P_CISRCFMT_HSIZE(f->o_width) |
+ S5P_CISRCFMT_VSIZE(f->o_height);
writel(cfg, fimc->regs + S5P_CISRCFMT);
return 0;
}
@@ -641,7 +721,8 @@ int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
int fimc_hw_set_camera_type(struct fimc_dev *fimc,
struct s5p_fimc_isp_info *cam)
{
- u32 cfg, tmp;
+ u32 cfg = 0;
+ u32 tmp = 0;
struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
cfg = readl(fimc->regs + S5P_CIGCTRL);
@@ -649,32 +730,47 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
/* Select ITU B interface, disable Writeback path and test pattern. */
cfg &= ~(S5P_CIGCTRL_TESTPAT_MASK | S5P_CIGCTRL_SELCAM_ITU_A |
S5P_CIGCTRL_SELCAM_MIPI | S5P_CIGCTRL_CAMIF_SELWB |
- S5P_CIGCTRL_SELCAM_MIPI_A);
+ S5P_CIGCTRL_SELCAM_MIPI_A | S5P_CIGCTRL_SELWRITEBACK_A |
+ S5P_CIGCTRL_CAM_JPEG);
if (cam->bus_type == FIMC_MIPI_CSI2) {
- cfg |= S5P_CIGCTRL_SELCAM_MIPI;
-
- if (cam->mux_id == 0)
- cfg |= S5P_CIGCTRL_SELCAM_MIPI_A;
+ if (!vid_cap->is.sd && !vid_cap->is.camcording) {
+ cfg |= S5P_CIGCTRL_SELCAM_MIPI;
+
+ if (cam->mux_id == 0)
+ cfg |= S5P_CIGCTRL_SELCAM_MIPI_A;
+
+ /* TODO: add remaining supported formats. */
+ switch (vid_cap->fmt.code) {
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ tmp = S5P_CSIIMGFMT_YCBCR422_8BIT;
+ break;
+ case V4L2_MBUS_FMT_JPEG_1X8:
+ tmp = S5P_CSIIMGFMT_USER(1);
+ cfg |= S5P_CIGCTRL_CAM_JPEG;
+ break;
+ default:
+ v4l2_err(&fimc->vid_cap.v4l2_dev,
+ "Not supported camera pixel format: %d",
+ vid_cap->fmt.code);
+ }
+ tmp |= (cam->csi_data_align == 32) << 8;
- /* TODO: add remaining supported formats. */
- if (vid_cap->fmt.code == V4L2_MBUS_FMT_VYUY8_2X8) {
- tmp = S5P_CSIIMGFMT_YCBCR422_8BIT;
+ writel(tmp, fimc->regs + S5P_CSIIMGFMT);
} else {
- err("camera image format not supported: %d",
- vid_cap->fmt.code);
- return -EINVAL;
+ cfg |= S5P_CIGCTRL_CAMIF_SELWB;
+ cfg |= S5P_CIGCTRL_SELWRITEBACK_B;
}
- tmp |= (cam->csi_data_align == 32) << 8;
-
- writel(tmp, fimc->regs + S5P_CSIIMGFMT);
-
} else if (cam->bus_type == FIMC_ITU_601 ||
- cam->bus_type == FIMC_ITU_656) {
+ cam->bus_type == FIMC_ITU_656) {
if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
cfg |= S5P_CIGCTRL_SELCAM_ITU_A;
} else if (cam->bus_type == FIMC_LCD_WB) {
cfg |= S5P_CIGCTRL_CAMIF_SELWB;
+ if (cam->mux_id == 0)
+ cfg |= S5P_CIGCTRL_SELWRITEBACK_A;
} else {
err("invalid camera bus type selected\n");
return -EINVAL;
@@ -683,3 +779,102 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
return 0;
}
+
+int fimc_hwset_sysreg_camblk_fimd0_wb(struct fimc_dev *fimc)
+{
+ u32 cfg = readl(SYSREG_CAMERA_BLK);
+ cfg = cfg & (~(0x3 << 14));
+ if (fimc->id == 0)
+ cfg = cfg | FIMD0_WB_DEST_FIMC0;
+ else if (fimc->id == 1)
+ cfg = cfg | FIMD0_WB_DEST_FIMC1;
+ else if (fimc->id == 2)
+ cfg = cfg | FIMD0_WB_DEST_FIMC2;
+ else if (fimc->id == 3)
+ cfg = cfg | FIMD0_WB_DEST_FIMC3;
+ else
+ err("%s: not supported id : %d\n", __func__, fimc->id);
+
+ writel(cfg, SYSREG_CAMERA_BLK);
+
+ return 0;
+}
+int fimc_hwset_sysreg_camblk_fimd1_wb(struct fimc_dev *fimc)
+{
+ u32 cfg = readl(SYSREG_CAMERA_BLK);
+ cfg = cfg & (~(0x3 << 10));
+ if (fimc->id == 0)
+ cfg = cfg | FIMD1_WB_DEST_FIMC0;
+ else if (fimc->id == 1)
+ cfg = cfg | FIMD1_WB_DEST_FIMC1;
+ else if (fimc->id == 2)
+ cfg = cfg | FIMD1_WB_DEST_FIMC2;
+ else if (fimc->id == 3)
+ cfg = cfg | FIMD1_WB_DEST_FIMC3;
+ else
+ err("%s: not supported id : %d\n", __func__, fimc->id);
+
+ writel(cfg, SYSREG_CAMERA_BLK);
+
+ return 0;
+}
+
+int fimc_hwset_sysreg_camblk_isp_wb(struct fimc_dev *fimc)
+{
+ u32 camblk_cfg = readl(SYSREG_CAMERA_BLK);
+ u32 ispblk_cfg = readl(SYSREG_ISP_BLK);
+ camblk_cfg = camblk_cfg & (~(0x7 << 20));
+ if (fimc->id == 0)
+ camblk_cfg = camblk_cfg | (0x1 << 20);
+ else if (fimc->id == 1)
+ camblk_cfg = camblk_cfg | (0x2 << 20);
+ else if (fimc->id == 2)
+ camblk_cfg = camblk_cfg | (0x4 << 20);
+ else if (fimc->id == 3)
+ camblk_cfg = camblk_cfg | (0x7 << 20); /* FIXME*/
+ else
+ err("%s: not supported id : %d\n", __func__, fimc->id);
+
+ camblk_cfg = camblk_cfg & (~(0x1 << 15));
+ writel(camblk_cfg, SYSREG_CAMERA_BLK);
+ udelay(1000);
+ camblk_cfg = camblk_cfg | (0x1 << 15);
+ writel(camblk_cfg, SYSREG_CAMERA_BLK);
+
+ ispblk_cfg = ispblk_cfg & (~(0x1 << 7));
+ writel(ispblk_cfg, SYSREG_ISP_BLK);
+ udelay(1000);
+ ispblk_cfg = ispblk_cfg | (0x1 << 7);
+ writel(ispblk_cfg, SYSREG_ISP_BLK);
+
+ return 0;
+}
+
+int fimc_wait_disable_capture(struct fimc_dev *fimc)
+{
+ unsigned long timeo = jiffies + 20; /* timeout of 100ms */
+ u32 cfg;
+
+ while (time_before(jiffies, timeo)) {
+ cfg = readl(fimc->regs + S5P_CISTATUS);
+
+ if (!(cfg & S5P_CISTATUS_IMGCPT_EN) &&
+ !(cfg & S5P_CISTATUS_IMGCPT_SCEN) &&
+ !(cfg & S5P_CISTATUS_SCALER_START))
+ return 0;
+ msleep(5);
+ }
+ dbg("wait time : %d ms\n", jiffies_to_msecs(jiffies - timeo + 20));
+
+ return -EBUSY;
+}
+
+int fimc_hwset_enable_lastend(struct fimc_dev *fimc)
+{
+ u32 cfg = readl(fimc->regs + S5P_CIOCTRL);
+
+ cfg |= S5P_CIOCTRL_LASTENDEN;
+ writel(cfg, fimc->regs + S5P_CIOCTRL);
+
+ return 0;
+}