diff options
author | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
---|---|---|
committer | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
commit | c6da2cfeb05178a11c6d062a06f8078150ee492f (patch) | |
tree | f3b4021d252c52d6463a9b3c1bb7245e399b009c /drivers/media/video/s5p-fimc/fimc-reg.c | |
parent | c6d7c4dbff353eac7919342ae6b3299a378160a6 (diff) | |
download | kernel_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.c | 255 |
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; +} |