blob: 5ce2bdebd424aaaa3c2ce5ba7438a3e0d3a29c36 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -03002/*
3 * Register interface file for Samsung Camera Interface (FIMC) driver
4 *
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -03005 * Copyright (C) 2010 - 2013 Samsung Electronics Co., Ltd.
6 * Sylwester Nawrocki <s.nawrocki@samsung.com>
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -03007*/
8
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -03009#include <linux/delay.h>
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -030010#include <linux/io.h>
11#include <linux/regmap.h>
12
Mauro Carvalho Chehabd647f0b2015-11-13 19:40:07 -020013#include <media/drv-intf/exynos-fimc.h>
Sylwester Nawrocki56fa1a62013-03-24 16:54:25 +010014#include "media-dev.h"
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030015
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030016#include "fimc-reg.h"
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030017#include "fimc-core.h"
18
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030019void fimc_hw_reset(struct fimc_dev *dev)
20{
21 u32 cfg;
22
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030023 cfg = readl(dev->regs + FIMC_REG_CISRCFMT);
24 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
25 writel(cfg, dev->regs + FIMC_REG_CISRCFMT);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030026
27 /* Software reset. */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030028 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
29 cfg |= (FIMC_REG_CIGCTRL_SWRST | FIMC_REG_CIGCTRL_IRQ_LEVEL);
30 writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
Sylwester Nawrockie9e21082011-09-02 06:25:32 -030031 udelay(10);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030032
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030033 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
34 cfg &= ~FIMC_REG_CIGCTRL_SWRST;
35 writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
Sylwester Nawrocki2c1bb622011-10-05 14:20:45 -030036
Sylwester Nawrockie80cb1f2013-03-26 08:22:21 -030037 if (dev->drv_data->out_buf_count > 4)
Sylwester Nawrocki2c1bb622011-10-05 14:20:45 -030038 fimc_hw_set_dma_seq(dev, 0xF);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030039}
40
Sylwester Nawrockiac759342010-12-27 14:47:32 -030041static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030042{
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030043 u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030044
Sylwester Nawrocki131b6c62011-08-24 19:25:10 -030045 if (ctx->hflip)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030046 flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR;
Sylwester Nawrocki1bc05e72012-11-26 11:08:26 -030047 if (ctx->vflip)
48 flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR;
Sylwester Nawrocki131b6c62011-08-24 19:25:10 -030049
Sylwester Nawrockiac759342010-12-27 14:47:32 -030050 if (ctx->rotation <= 90)
51 return flip;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030052
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030053 return (flip ^ FIMC_REG_MSCTRL_FLIP_180) & FIMC_REG_MSCTRL_FLIP_180;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030054}
55
Sylwester Nawrockiac759342010-12-27 14:47:32 -030056static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030057{
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030058 u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030059
Sylwester Nawrocki131b6c62011-08-24 19:25:10 -030060 if (ctx->hflip)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030061 flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR;
Sylwester Nawrocki1bc05e72012-11-26 11:08:26 -030062 if (ctx->vflip)
63 flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR;
Sylwester Nawrocki131b6c62011-08-24 19:25:10 -030064
Sylwester Nawrockiac759342010-12-27 14:47:32 -030065 if (ctx->rotation <= 90)
66 return flip;
67
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030068 return (flip ^ FIMC_REG_CITRGFMT_FLIP_180) & FIMC_REG_CITRGFMT_FLIP_180;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -030069}
70
Sylwester Nawrocki47654df2010-10-08 05:01:22 -030071void fimc_hw_set_rotation(struct fimc_ctx *ctx)
72{
73 u32 cfg, flip;
74 struct fimc_dev *dev = ctx->fimc_dev;
75
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030076 cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
77 cfg &= ~(FIMC_REG_CITRGFMT_INROT90 | FIMC_REG_CITRGFMT_OUTROT90 |
78 FIMC_REG_CITRGFMT_FLIP_180);
Sylwester Nawrocki47654df2010-10-08 05:01:22 -030079
80 /*
81 * The input and output rotator cannot work simultaneously.
82 * Use the output rotator in output DMA mode or the input rotator
83 * in direct fifo output mode.
84 */
85 if (ctx->rotation == 90 || ctx->rotation == 270) {
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -030086 if (ctx->out_path == FIMC_IO_LCDFIFO)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030087 cfg |= FIMC_REG_CITRGFMT_INROT90;
Sylwester Nawrocki47654df2010-10-08 05:01:22 -030088 else
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030089 cfg |= FIMC_REG_CITRGFMT_OUTROT90;
Sylwester Nawrocki47654df2010-10-08 05:01:22 -030090 }
Sylwester Nawrocki47654df2010-10-08 05:01:22 -030091
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -030092 if (ctx->out_path == FIMC_IO_DMA) {
Sylwester Nawrockiac759342010-12-27 14:47:32 -030093 cfg |= fimc_hw_get_target_flip(ctx);
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030094 writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
Sylwester Nawrockiac759342010-12-27 14:47:32 -030095 } else {
96 /* LCD FIFO path */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -030097 flip = readl(dev->regs + FIMC_REG_MSCTRL);
98 flip &= ~FIMC_REG_MSCTRL_FLIP_MASK;
Sylwester Nawrockiac759342010-12-27 14:47:32 -030099 flip |= fimc_hw_get_in_flip(ctx);
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300100 writel(flip, dev->regs + FIMC_REG_MSCTRL);
Sylwester Nawrockiac759342010-12-27 14:47:32 -0300101 }
Sylwester Nawrocki47654df2010-10-08 05:01:22 -0300102}
103
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300104void fimc_hw_set_target_format(struct fimc_ctx *ctx)
105{
106 u32 cfg;
107 struct fimc_dev *dev = ctx->fimc_dev;
108 struct fimc_frame *frame = &ctx->d_frame;
109
110 dbg("w= %d, h= %d color: %d", frame->width,
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300111 frame->height, frame->fmt->color);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300112
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300113 cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
114 cfg &= ~(FIMC_REG_CITRGFMT_FMT_MASK | FIMC_REG_CITRGFMT_HSIZE_MASK |
115 FIMC_REG_CITRGFMT_VSIZE_MASK);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300116
117 switch (frame->fmt->color) {
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300118 case FIMC_FMT_RGB444...FIMC_FMT_RGB888:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300119 cfg |= FIMC_REG_CITRGFMT_RGB;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300120 break;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300121 case FIMC_FMT_YCBCR420:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300122 cfg |= FIMC_REG_CITRGFMT_YCBCR420;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300123 break;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300124 case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
Sylwester Nawrockief7af592010-12-08 14:05:08 -0300125 if (frame->fmt->colplanes == 1)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300126 cfg |= FIMC_REG_CITRGFMT_YCBCR422_1P;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300127 else
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300128 cfg |= FIMC_REG_CITRGFMT_YCBCR422;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300129 break;
130 default:
131 break;
132 }
133
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300134 if (ctx->rotation == 90 || ctx->rotation == 270)
135 cfg |= (frame->height << 16) | frame->width;
136 else
137 cfg |= (frame->width << 16) | frame->height;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300138
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300139 writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
Sylwester Nawrocki47654df2010-10-08 05:01:22 -0300140
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300141 cfg = readl(dev->regs + FIMC_REG_CITAREA);
142 cfg &= ~FIMC_REG_CITAREA_MASK;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300143 cfg |= (frame->width * frame->height);
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300144 writel(cfg, dev->regs + FIMC_REG_CITAREA);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300145}
146
147static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
148{
149 struct fimc_dev *dev = ctx->fimc_dev;
150 struct fimc_frame *frame = &ctx->d_frame;
Sylwester Nawrocki47654df2010-10-08 05:01:22 -0300151 u32 cfg;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300152
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300153 cfg = (frame->f_height << 16) | frame->f_width;
154 writel(cfg, dev->regs + FIMC_REG_ORGOSIZE);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300155
156 /* Select color space conversion equation (HD/SD size).*/
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300157 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300158 if (frame->f_width >= 1280) /* HD */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300159 cfg |= FIMC_REG_CIGCTRL_CSC_ITU601_709;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300160 else /* SD */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300161 cfg &= ~FIMC_REG_CIGCTRL_CSC_ITU601_709;
162 writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300163
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300164}
165
166void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
167{
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300168 struct fimc_dev *dev = ctx->fimc_dev;
169 struct fimc_frame *frame = &ctx->d_frame;
170 struct fimc_dma_offset *offset = &frame->dma_offset;
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300171 struct fimc_fmt *fmt = frame->fmt;
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300172 u32 cfg;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300173
174 /* Set the input dma offsets. */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300175 cfg = (offset->y_v << 16) | offset->y_h;
176 writel(cfg, dev->regs + FIMC_REG_CIOYOFF);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300177
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300178 cfg = (offset->cb_v << 16) | offset->cb_h;
179 writel(cfg, dev->regs + FIMC_REG_CIOCBOFF);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300180
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300181 cfg = (offset->cr_v << 16) | offset->cr_h;
182 writel(cfg, dev->regs + FIMC_REG_CIOCROFF);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300183
184 fimc_hw_set_out_dma_size(ctx);
185
186 /* Configure chroma components order. */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300187 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300188
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300189 cfg &= ~(FIMC_REG_CIOCTRL_ORDER2P_MASK |
190 FIMC_REG_CIOCTRL_ORDER422_MASK |
191 FIMC_REG_CIOCTRL_YCBCR_PLANE_MASK |
192 FIMC_REG_CIOCTRL_RGB16FMT_MASK);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300193
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300194 if (fmt->colplanes == 1)
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300195 cfg |= ctx->out_order_1p;
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300196 else if (fmt->colplanes == 2)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300197 cfg |= ctx->out_order_2p | FIMC_REG_CIOCTRL_YCBCR_2PLANE;
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300198 else if (fmt->colplanes == 3)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300199 cfg |= FIMC_REG_CIOCTRL_YCBCR_3PLANE;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300200
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300201 if (fmt->color == FIMC_FMT_RGB565)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300202 cfg |= FIMC_REG_CIOCTRL_RGB565;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300203 else if (fmt->color == FIMC_FMT_RGB555)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300204 cfg |= FIMC_REG_CIOCTRL_ARGB1555;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300205 else if (fmt->color == FIMC_FMT_RGB444)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300206 cfg |= FIMC_REG_CIOCTRL_ARGB4444;
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300207
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300208 writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300209}
210
211static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
212{
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300213 u32 cfg = readl(dev->regs + FIMC_REG_ORGISIZE);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300214 if (enable)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300215 cfg |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300216 else
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300217 cfg &= ~FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
218 writel(cfg, dev->regs + FIMC_REG_ORGISIZE);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300219}
220
221void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
222{
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300223 u32 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300224 if (enable)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300225 cfg |= FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300226 else
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300227 cfg &= ~FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
228 writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300229}
230
Hyunwoong Kimb241c6d2010-12-28 11:27:13 -0300231void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300232{
233 struct fimc_dev *dev = ctx->fimc_dev;
234 struct fimc_scaler *sc = &ctx->scaler;
Sylwester Nawrocki548aafc2010-10-08 05:01:14 -0300235 u32 cfg, shfactor;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300236
237 shfactor = 10 - (sc->hfactor + sc->vfactor);
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300238 cfg = shfactor << 28;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300239
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300240 cfg |= (sc->pre_hratio << 16) | sc->pre_vratio;
241 writel(cfg, dev->regs + FIMC_REG_CISCPRERATIO);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300242
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300243 cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
244 writel(cfg, dev->regs + FIMC_REG_CISCPREDST);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300245}
246
Hyunwoong Kimb241c6d2010-12-28 11:27:13 -0300247static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300248{
249 struct fimc_dev *dev = ctx->fimc_dev;
250 struct fimc_scaler *sc = &ctx->scaler;
251 struct fimc_frame *src_frame = &ctx->s_frame;
252 struct fimc_frame *dst_frame = &ctx->d_frame;
Sylwester Nawrocki2c1bb622011-10-05 14:20:45 -0300253
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300254 u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
Sylwester Nawrocki2c1bb622011-10-05 14:20:45 -0300255
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300256 cfg &= ~(FIMC_REG_CISCCTRL_CSCR2Y_WIDE | FIMC_REG_CISCCTRL_CSCY2R_WIDE |
257 FIMC_REG_CISCCTRL_SCALEUP_H | FIMC_REG_CISCCTRL_SCALEUP_V |
258 FIMC_REG_CISCCTRL_SCALERBYPASS | FIMC_REG_CISCCTRL_ONE2ONE |
259 FIMC_REG_CISCCTRL_INRGB_FMT_MASK | FIMC_REG_CISCCTRL_OUTRGB_FMT_MASK |
260 FIMC_REG_CISCCTRL_INTERLACE | FIMC_REG_CISCCTRL_RGB_EXT);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300261
262 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300263 cfg |= (FIMC_REG_CISCCTRL_CSCR2Y_WIDE |
264 FIMC_REG_CISCCTRL_CSCY2R_WIDE);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300265
266 if (!sc->enabled)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300267 cfg |= FIMC_REG_CISCCTRL_SCALERBYPASS;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300268
269 if (sc->scaleup_h)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300270 cfg |= FIMC_REG_CISCCTRL_SCALEUP_H;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300271
272 if (sc->scaleup_v)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300273 cfg |= FIMC_REG_CISCCTRL_SCALEUP_V;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300274
275 if (sc->copy_mode)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300276 cfg |= FIMC_REG_CISCCTRL_ONE2ONE;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300277
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300278 if (ctx->in_path == FIMC_IO_DMA) {
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300279 switch (src_frame->fmt->color) {
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300280 case FIMC_FMT_RGB565:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300281 cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB565;
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300282 break;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300283 case FIMC_FMT_RGB666:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300284 cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB666;
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300285 break;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300286 case FIMC_FMT_RGB888:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300287 cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB888;
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300288 break;
289 }
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300290 }
291
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300292 if (ctx->out_path == FIMC_IO_DMA) {
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300293 u32 color = dst_frame->fmt->color;
294
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300295 if (color >= FIMC_FMT_RGB444 && color <= FIMC_FMT_RGB565)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300296 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300297 else if (color == FIMC_FMT_RGB666)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300298 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300299 else if (color == FIMC_FMT_RGB888)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300300 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300301 } else {
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300302 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300303
304 if (ctx->flags & FIMC_SCAN_MODE_INTERLACED)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300305 cfg |= FIMC_REG_CISCCTRL_INTERLACE;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300306 }
307
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300308 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
Hyunwoong Kimb241c6d2010-12-28 11:27:13 -0300309}
310
311void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
312{
313 struct fimc_dev *dev = ctx->fimc_dev;
Sylwester Nawrocki405f2302012-08-02 10:27:46 -0300314 const struct fimc_variant *variant = dev->variant;
Hyunwoong Kimb241c6d2010-12-28 11:27:13 -0300315 struct fimc_scaler *sc = &ctx->scaler;
316 u32 cfg;
317
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300318 dbg("main_hratio= 0x%X main_vratio= 0x%X",
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300319 sc->main_hratio, sc->main_vratio);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300320
Hyunwoong Kimb241c6d2010-12-28 11:27:13 -0300321 fimc_hw_set_scaler(ctx);
322
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300323 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
324 cfg &= ~(FIMC_REG_CISCCTRL_MHRATIO_MASK |
325 FIMC_REG_CISCCTRL_MVRATIO_MASK);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300326
Sylwester Nawrocki70f66ea2010-12-28 11:37:55 -0300327 if (variant->has_mainscaler_ext) {
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300328 cfg |= FIMC_REG_CISCCTRL_MHRATIO_EXT(sc->main_hratio);
329 cfg |= FIMC_REG_CISCCTRL_MVRATIO_EXT(sc->main_vratio);
330 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300331
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300332 cfg = readl(dev->regs + FIMC_REG_CIEXTEN);
Hyunwoong Kimb241c6d2010-12-28 11:27:13 -0300333
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300334 cfg &= ~(FIMC_REG_CIEXTEN_MVRATIO_EXT_MASK |
335 FIMC_REG_CIEXTEN_MHRATIO_EXT_MASK);
336 cfg |= FIMC_REG_CIEXTEN_MHRATIO_EXT(sc->main_hratio);
337 cfg |= FIMC_REG_CIEXTEN_MVRATIO_EXT(sc->main_vratio);
338 writel(cfg, dev->regs + FIMC_REG_CIEXTEN);
Sylwester Nawrocki70f66ea2010-12-28 11:37:55 -0300339 } else {
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300340 cfg |= FIMC_REG_CISCCTRL_MHRATIO(sc->main_hratio);
341 cfg |= FIMC_REG_CISCCTRL_MVRATIO(sc->main_vratio);
342 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
Sylwester Nawrocki70f66ea2010-12-28 11:37:55 -0300343 }
Hyunwoong Kimb241c6d2010-12-28 11:27:13 -0300344}
345
Sylwester Nawrocki35f29242012-11-22 14:01:39 -0300346void fimc_hw_enable_capture(struct fimc_ctx *ctx)
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300347{
348 struct fimc_dev *dev = ctx->fimc_dev;
Sylwester Nawrocki35f29242012-11-22 14:01:39 -0300349 u32 cfg;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300350
Sylwester Nawrocki35f29242012-11-22 14:01:39 -0300351 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
352 cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300353
354 if (ctx->scaler.enabled)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300355 cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
Sylwester Nawrocki35f29242012-11-22 14:01:39 -0300356 else
357 cfg &= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300358
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300359 cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
360 writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300361}
362
Sylwester Nawrocki35f29242012-11-22 14:01:39 -0300363void fimc_hw_disable_capture(struct fimc_dev *dev)
364{
365 u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
366 cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN |
367 FIMC_REG_CIIMGCPT_IMGCPTEN_SC);
368 writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
369}
370
Sylwester Nawrocki9448ab72012-04-02 06:41:22 -0300371void fimc_hw_set_effect(struct fimc_ctx *ctx)
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300372{
373 struct fimc_dev *dev = ctx->fimc_dev;
374 struct fimc_effect *effect = &ctx->effect;
Sylwester Nawrockiee7160e2011-08-26 14:57:06 -0300375 u32 cfg = 0;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300376
Sylwester Nawrocki9448ab72012-04-02 06:41:22 -0300377 if (effect->type != FIMC_REG_CIIMGEFF_FIN_BYPASS) {
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300378 cfg |= FIMC_REG_CIIMGEFF_IE_SC_AFTER |
379 FIMC_REG_CIIMGEFF_IE_ENABLE;
Sylwester Nawrockiee7160e2011-08-26 14:57:06 -0300380 cfg |= effect->type;
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300381 if (effect->type == FIMC_REG_CIIMGEFF_FIN_ARBITRARY)
382 cfg |= (effect->pat_cb << 13) | effect->pat_cr;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300383 }
384
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300385 writel(cfg, dev->regs + FIMC_REG_CIIMGEFF);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300386}
387
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300388void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx)
389{
390 struct fimc_dev *dev = ctx->fimc_dev;
391 struct fimc_frame *frame = &ctx->d_frame;
392 u32 cfg;
393
394 if (!(frame->fmt->flags & FMT_HAS_ALPHA))
395 return;
396
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300397 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
398 cfg &= ~FIMC_REG_CIOCTRL_ALPHA_OUT_MASK;
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300399 cfg |= (frame->alpha << 4);
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300400 writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
Sylwester Nawrockidafb9c72011-12-01 14:02:24 -0300401}
402
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300403static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
404{
405 struct fimc_dev *dev = ctx->fimc_dev;
406 struct fimc_frame *frame = &ctx->s_frame;
407 u32 cfg_o = 0;
408 u32 cfg_r = 0;
409
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300410 if (FIMC_IO_LCDFIFO == ctx->out_path)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300411 cfg_r |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300412
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300413 cfg_o |= (frame->f_height << 16) | frame->f_width;
414 cfg_r |= (frame->height << 16) | frame->width;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300415
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300416 writel(cfg_o, dev->regs + FIMC_REG_ORGISIZE);
417 writel(cfg_r, dev->regs + FIMC_REG_CIREAL_ISIZE);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300418}
419
420void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
421{
422 struct fimc_dev *dev = ctx->fimc_dev;
423 struct fimc_frame *frame = &ctx->s_frame;
424 struct fimc_dma_offset *offset = &frame->dma_offset;
Sylwester Nawrocki548aafc2010-10-08 05:01:14 -0300425 u32 cfg;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300426
427 /* Set the pixel offsets. */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300428 cfg = (offset->y_v << 16) | offset->y_h;
429 writel(cfg, dev->regs + FIMC_REG_CIIYOFF);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300430
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300431 cfg = (offset->cb_v << 16) | offset->cb_h;
432 writel(cfg, dev->regs + FIMC_REG_CIICBOFF);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300433
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300434 cfg = (offset->cr_v << 16) | offset->cr_h;
435 writel(cfg, dev->regs + FIMC_REG_CIICROFF);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300436
437 /* Input original and real size. */
438 fimc_hw_set_in_dma_size(ctx);
439
Sylwester Nawrocki548aafc2010-10-08 05:01:14 -0300440 /* Use DMA autoload only in FIFO mode. */
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300441 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_IO_LCDFIFO);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300442
443 /* Set the input DMA to process single frame only. */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300444 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
445 cfg &= ~(FIMC_REG_MSCTRL_INFORMAT_MASK
446 | FIMC_REG_MSCTRL_IN_BURST_COUNT_MASK
447 | FIMC_REG_MSCTRL_INPUT_MASK
448 | FIMC_REG_MSCTRL_C_INT_IN_MASK
Sylwester Nawrocki43979792013-03-21 14:22:34 -0300449 | FIMC_REG_MSCTRL_2P_IN_ORDER_MASK
450 | FIMC_REG_MSCTRL_ORDER422_MASK);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300451
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300452 cfg |= (FIMC_REG_MSCTRL_IN_BURST_COUNT(4)
453 | FIMC_REG_MSCTRL_INPUT_MEMORY
454 | FIMC_REG_MSCTRL_FIFO_CTRL_FULL);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300455
456 switch (frame->fmt->color) {
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300457 case FIMC_FMT_RGB565...FIMC_FMT_RGB888:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300458 cfg |= FIMC_REG_MSCTRL_INFORMAT_RGB;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300459 break;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300460 case FIMC_FMT_YCBCR420:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300461 cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR420;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300462
Sylwester Nawrockief7af592010-12-08 14:05:08 -0300463 if (frame->fmt->colplanes == 2)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300464 cfg |= ctx->in_order_2p | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300465 else
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300466 cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300467
468 break;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300469 case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
Sylwester Nawrockief7af592010-12-08 14:05:08 -0300470 if (frame->fmt->colplanes == 1) {
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300471 cfg |= ctx->in_order_1p
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300472 | FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300473 } else {
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300474 cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR422;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300475
Sylwester Nawrockief7af592010-12-08 14:05:08 -0300476 if (frame->fmt->colplanes == 2)
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300477 cfg |= ctx->in_order_2p
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300478 | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300479 else
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300480 cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300481 }
482 break;
483 default:
484 break;
485 }
486
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300487 writel(cfg, dev->regs + FIMC_REG_MSCTRL);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300488
489 /* Input/output DMA linear/tiled mode. */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300490 cfg = readl(dev->regs + FIMC_REG_CIDMAPARAM);
491 cfg &= ~FIMC_REG_CIDMAPARAM_TILE_MASK;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300492
493 if (tiled_fmt(ctx->s_frame.fmt))
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300494 cfg |= FIMC_REG_CIDMAPARAM_R_64X32;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300495
496 if (tiled_fmt(ctx->d_frame.fmt))
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300497 cfg |= FIMC_REG_CIDMAPARAM_W_64X32;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300498
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300499 writel(cfg, dev->regs + FIMC_REG_CIDMAPARAM);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300500}
501
502
503void fimc_hw_set_input_path(struct fimc_ctx *ctx)
504{
505 struct fimc_dev *dev = ctx->fimc_dev;
506
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300507 u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
508 cfg &= ~FIMC_REG_MSCTRL_INPUT_MASK;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300509
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300510 if (ctx->in_path == FIMC_IO_DMA)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300511 cfg |= FIMC_REG_MSCTRL_INPUT_MEMORY;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300512 else
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300513 cfg |= FIMC_REG_MSCTRL_INPUT_EXTCAM;
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300514
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300515 writel(cfg, dev->regs + FIMC_REG_MSCTRL);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300516}
517
518void fimc_hw_set_output_path(struct fimc_ctx *ctx)
519{
520 struct fimc_dev *dev = ctx->fimc_dev;
521
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300522 u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
523 cfg &= ~FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
Sylwester Nawrocki3d112d92012-04-26 06:26:29 -0300524 if (ctx->out_path == FIMC_IO_LCDFIFO)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300525 cfg |= FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
526 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300527}
528
529void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
530{
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300531 u32 cfg = readl(dev->regs + FIMC_REG_CIREAL_ISIZE);
532 cfg |= FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
533 writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300534
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300535 writel(paddr->y, dev->regs + FIMC_REG_CIIYSA(0));
536 writel(paddr->cb, dev->regs + FIMC_REG_CIICBSA(0));
537 writel(paddr->cr, dev->regs + FIMC_REG_CIICRSA(0));
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300538
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300539 cfg &= ~FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
540 writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300541}
542
Sylwester Nawrocki548aafc2010-10-08 05:01:14 -0300543void fimc_hw_set_output_addr(struct fimc_dev *dev,
544 struct fimc_addr *paddr, int index)
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300545{
Sylwester Nawrocki548aafc2010-10-08 05:01:14 -0300546 int i = (index == -1) ? 0 : index;
547 do {
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300548 writel(paddr->y, dev->regs + FIMC_REG_CIOYSA(i));
549 writel(paddr->cb, dev->regs + FIMC_REG_CIOCBSA(i));
550 writel(paddr->cr, dev->regs + FIMC_REG_CIOCRSA(i));
Sylwester Nawrocki548aafc2010-10-08 05:01:14 -0300551 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
552 i, paddr->y, paddr->cb, paddr->cr);
553 } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
Sylwester Nawrocki5fd8f732010-08-03 09:50:29 -0300554}
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300555
556int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300557 struct fimc_source_info *cam)
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300558{
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300559 u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300560
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300561 cfg &= ~(FIMC_REG_CIGCTRL_INVPOLPCLK | FIMC_REG_CIGCTRL_INVPOLVSYNC |
562 FIMC_REG_CIGCTRL_INVPOLHREF | FIMC_REG_CIGCTRL_INVPOLHSYNC |
563 FIMC_REG_CIGCTRL_INVPOLFIELD);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300564
Sylwester Nawrocki12ecf562011-09-19 12:38:35 -0300565 if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300566 cfg |= FIMC_REG_CIGCTRL_INVPOLPCLK;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300567
Sylwester Nawrocki12ecf562011-09-19 12:38:35 -0300568 if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300569 cfg |= FIMC_REG_CIGCTRL_INVPOLVSYNC;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300570
Sylwester Nawrocki12ecf562011-09-19 12:38:35 -0300571 if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300572 cfg |= FIMC_REG_CIGCTRL_INVPOLHREF;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300573
Sylwester Nawrocki12ecf562011-09-19 12:38:35 -0300574 if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300575 cfg |= FIMC_REG_CIGCTRL_INVPOLHSYNC;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300576
Sylwester Nawrocki12ecf562011-09-19 12:38:35 -0300577 if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300578 cfg |= FIMC_REG_CIGCTRL_INVPOLFIELD;
Sylwester Nawrocki12ecf562011-09-19 12:38:35 -0300579
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300580 writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300581
582 return 0;
583}
584
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300585struct mbus_pixfmt_desc {
586 u32 pixelcode;
587 u32 cisrcfmt;
588 u16 bus_width;
589};
590
591static const struct mbus_pixfmt_desc pix_desc[] = {
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -0300592 { MEDIA_BUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 },
593 { MEDIA_BUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 },
594 { MEDIA_BUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 },
595 { MEDIA_BUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 },
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300596};
597
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300598int fimc_hw_set_camera_source(struct fimc_dev *fimc,
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300599 struct fimc_source_info *source)
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300600{
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300601 struct fimc_vid_cap *vc = &fimc->vid_cap;
602 struct fimc_frame *f = &vc->ctx->s_frame;
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300603 u32 bus_width, cfg = 0;
Sylwester Nawrocki3d0ce7e2010-12-27 15:02:16 -0300604 int i;
605
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300606 switch (source->fimc_bus_type) {
607 case FIMC_BUS_TYPE_ITU_601:
608 case FIMC_BUS_TYPE_ITU_656:
Sylwester Nawrocki3d0ce7e2010-12-27 15:02:16 -0300609 for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300610 if (vc->ci_fmt.code == pix_desc[i].pixelcode) {
Sylwester Nawrocki3d0ce7e2010-12-27 15:02:16 -0300611 cfg = pix_desc[i].cisrcfmt;
612 bus_width = pix_desc[i].bus_width;
613 break;
614 }
615 }
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300616
Sylwester Nawrocki3d0ce7e2010-12-27 15:02:16 -0300617 if (i == ARRAY_SIZE(pix_desc)) {
Sylwester Nawrockibc7584b2013-05-31 11:37:18 -0300618 v4l2_err(&vc->ve.vdev,
Sylwester Nawrocki3d0ce7e2010-12-27 15:02:16 -0300619 "Camera color format not supported: %d\n",
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300620 vc->ci_fmt.code);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300621 return -EINVAL;
622 }
623
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300624 if (source->fimc_bus_type == FIMC_BUS_TYPE_ITU_601) {
Sylwester Nawrocki3d0ce7e2010-12-27 15:02:16 -0300625 if (bus_width == 8)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300626 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
Sylwester Nawrocki3d0ce7e2010-12-27 15:02:16 -0300627 else if (bus_width == 16)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300628 cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300629 } /* else defaults to ITU-R BT.656 8-bit */
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300630 break;
631 case FIMC_BUS_TYPE_MIPI_CSI2:
Sylwester Nawrocki14783d22012-09-24 11:08:45 -0300632 if (fimc_fmt_is_user_defined(f->fmt->color))
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300633 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300634 break;
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300635 default:
636 case FIMC_BUS_TYPE_ISP_WRITEBACK:
637 /* Anything to do here ? */
638 break;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300639 }
640
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300641 cfg |= (f->o_width << 16) | f->o_height;
642 writel(cfg, fimc->regs + FIMC_REG_CISRCFMT);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300643 return 0;
644}
645
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300646void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300647{
648 u32 hoff2, voff2;
649
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300650 u32 cfg = readl(fimc->regs + FIMC_REG_CIWDOFST);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300651
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300652 cfg &= ~(FIMC_REG_CIWDOFST_HOROFF_MASK | FIMC_REG_CIWDOFST_VEROFF_MASK);
653 cfg |= FIMC_REG_CIWDOFST_OFF_EN |
654 (f->offs_h << 16) | f->offs_v;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300655
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300656 writel(cfg, fimc->regs + FIMC_REG_CIWDOFST);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300657
658 /* See CIWDOFSTn register description in the datasheet for details. */
659 hoff2 = f->o_width - f->width - f->offs_h;
660 voff2 = f->o_height - f->height - f->offs_v;
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300661 cfg = (hoff2 << 16) | voff2;
662 writel(cfg, fimc->regs + FIMC_REG_CIWDOFST2);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300663}
664
665int fimc_hw_set_camera_type(struct fimc_dev *fimc,
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300666 struct fimc_source_info *source)
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300667{
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300668 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
Sylwester Nawrocki20676a42012-03-21 06:21:30 -0300669 u32 csis_data_alignment = 32;
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300670 u32 cfg, tmp;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300671
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300672 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300673
674 /* Select ITU B interface, disable Writeback path and test pattern. */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300675 cfg &= ~(FIMC_REG_CIGCTRL_TESTPAT_MASK | FIMC_REG_CIGCTRL_SELCAM_ITU_A |
676 FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB |
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300677 FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG |
678 FIMC_REG_CIGCTRL_SELWB_A);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300679
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300680 switch (source->fimc_bus_type) {
681 case FIMC_BUS_TYPE_MIPI_CSI2:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300682 cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300683
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300684 if (source->mux_id == 0)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300685 cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A;
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300686
687 /* TODO: add remaining supported formats. */
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300688 switch (vid_cap->ci_fmt.code) {
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -0300689 case MEDIA_BUS_FMT_VYUY8_2X8:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300690 tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
Sylwester Nawrockiee7160e2011-08-26 14:57:06 -0300691 break;
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -0300692 case MEDIA_BUS_FMT_JPEG_1X8:
693 case MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300694 tmp = FIMC_REG_CSIIMGFMT_USER(1);
695 cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
Sylwester Nawrockiee7160e2011-08-26 14:57:06 -0300696 break;
697 default:
Sylwester Nawrockibc7584b2013-05-31 11:37:18 -0300698 v4l2_err(&vid_cap->ve.vdev,
Sachin Kamata516d082012-06-12 03:12:26 -0300699 "Not supported camera pixel format: %#x\n",
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300700 vid_cap->ci_fmt.code);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300701 return -EINVAL;
702 }
Sylwester Nawrocki20676a42012-03-21 06:21:30 -0300703 tmp |= (csis_data_alignment == 32) << 8;
Sylwester Nawrockie0eec9a2011-02-21 12:09:01 -0300704
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300705 writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT);
Sylwester Nawrocki31ce54f2012-07-24 12:06:26 -0300706 break;
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300707 case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656:
708 if (source->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300709 cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A;
Sylwester Nawrocki31ce54f2012-07-24 12:06:26 -0300710 break;
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300711 case FIMC_BUS_TYPE_LCD_WRITEBACK_A:
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300712 cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300713 /* fall through */
714 case FIMC_BUS_TYPE_ISP_WRITEBACK:
715 if (fimc->variant->has_isp_wb)
716 cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
717 else
718 WARN_ONCE(1, "ISP Writeback input is not supported\n");
Sylwester Nawrocki31ce54f2012-07-24 12:06:26 -0300719 break;
720 default:
Sylwester Nawrockibc7584b2013-05-31 11:37:18 -0300721 v4l2_err(&vid_cap->ve.vdev,
722 "Invalid FIMC bus type selected: %d\n",
Sylwester Nawrocki56bc9112013-02-01 15:00:40 -0300723 source->fimc_bus_type);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300724 return -EINVAL;
725 }
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300726 writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
Sylwester Nawrocki5f3cc442010-10-07 10:06:16 -0300727
728 return 0;
729}
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300730
731void fimc_hw_clear_irq(struct fimc_dev *dev)
732{
733 u32 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
734 cfg |= FIMC_REG_CIGCTRL_IRQ_CLR;
735 writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
736}
737
738void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on)
739{
740 u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
741 if (on)
742 cfg |= FIMC_REG_CISCCTRL_SCALERSTART;
743 else
744 cfg &= ~FIMC_REG_CISCCTRL_SCALERSTART;
745 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
746}
747
748void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on)
749{
750 u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
751 if (on)
752 cfg |= FIMC_REG_MSCTRL_ENVID;
753 else
754 cfg &= ~FIMC_REG_MSCTRL_ENVID;
755 writel(cfg, dev->regs + FIMC_REG_MSCTRL);
756}
757
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300758/* Return an index to the buffer actually being written. */
Sylwester Nawrocki14783d22012-09-24 11:08:45 -0300759s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300760{
Sylwester Nawrocki14783d22012-09-24 11:08:45 -0300761 s32 reg;
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300762
Sylwester Nawrockie80cb1f2013-03-26 08:22:21 -0300763 if (dev->drv_data->cistatus2) {
Sylwester Nawrocki14783d22012-09-24 11:08:45 -0300764 reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
765 return reg - 1;
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300766 }
767
768 reg = readl(dev->regs + FIMC_REG_CISTATUS);
769
770 return (reg & FIMC_REG_CISTATUS_FRAMECNT_MASK) >>
771 FIMC_REG_CISTATUS_FRAMECNT_SHIFT;
772}
773
Sylwester Nawrocki14783d22012-09-24 11:08:45 -0300774/* Return an index to the buffer being written previously. */
775s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
776{
777 s32 reg;
778
Sylwester Nawrockie80cb1f2013-03-26 08:22:21 -0300779 if (!dev->drv_data->cistatus2)
Sylwester Nawrocki14783d22012-09-24 11:08:45 -0300780 return -1;
781
782 reg = readl(dev->regs + FIMC_REG_CISTATUS2);
783 return ((reg >> 7) & 0x3f) - 1;
784}
785
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300786/* Locking: the caller holds fimc->slock */
787void fimc_activate_capture(struct fimc_ctx *ctx)
788{
789 fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled);
Sylwester Nawrocki35f29242012-11-22 14:01:39 -0300790 fimc_hw_enable_capture(ctx);
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300791}
792
793void fimc_deactivate_capture(struct fimc_dev *fimc)
794{
795 fimc_hw_en_lastirq(fimc, true);
Sylwester Nawrocki35f29242012-11-22 14:01:39 -0300796 fimc_hw_disable_capture(fimc);
Sylwester Nawrockic83a1ff2012-05-02 06:14:49 -0300797 fimc_hw_enable_scaler(fimc, false);
798 fimc_hw_en_lastirq(fimc, false);
799}
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300800
801int fimc_hw_camblk_cfg_writeback(struct fimc_dev *fimc)
802{
803 struct regmap *map = fimc->sysreg;
804 unsigned int mask, val, camblk_cfg;
805 int ret;
806
Sylwester Nawrockib3d8b552013-03-31 20:31:02 -0300807 if (map == NULL)
808 return 0;
809
Sylwester Nawrocki88fa8312013-03-20 10:44:39 -0300810 ret = regmap_read(map, SYSREG_CAMBLK, &camblk_cfg);
811 if (ret < 0 || ((camblk_cfg & 0x00700000) >> 20 != 0x3))
812 return ret;
813
814 if (!WARN(fimc->id >= 3, "not supported id: %d\n", fimc->id))
815 val = 0x1 << (fimc->id + 20);
816 else
817 val = 0;
818
819 mask = SYSREG_CAMBLK_FIFORST_ISP | SYSREG_CAMBLK_ISPWB_FULL_EN;
820 ret = regmap_update_bits(map, SYSREG_CAMBLK, mask, val);
821 if (ret < 0)
822 return ret;
823
824 usleep_range(1000, 2000);
825
826 val |= SYSREG_CAMBLK_FIFORST_ISP;
827 ret = regmap_update_bits(map, SYSREG_CAMBLK, mask, val);
828 if (ret < 0)
829 return ret;
830
831 mask = SYSREG_ISPBLK_FIFORST_CAM_BLK;
832 ret = regmap_update_bits(map, SYSREG_ISPBLK, mask, ~mask);
833 if (ret < 0)
834 return ret;
835
836 usleep_range(1000, 2000);
837
838 return regmap_update_bits(map, SYSREG_ISPBLK, mask, mask);
839}