Commit | Line | Data |
---|---|---|
5fd8f738 SN |
1 | /* |
2 | * Register interface file for Samsung Camera Interface (FIMC) driver | |
3 | * | |
0c9204d3 SN |
4 | * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd. |
5 | * Sylwester Nawrocki, <s.nawrocki@samsung.com> | |
5fd8f738 SN |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | */ | |
11 | ||
12 | #include <linux/io.h> | |
13 | #include <linux/delay.h> | |
df7e09a3 | 14 | #include <media/s5p_fimc.h> |
5fd8f738 | 15 | |
c83a1ff0 | 16 | #include "fimc-reg.h" |
5fd8f738 SN |
17 | #include "fimc-core.h" |
18 | ||
19 | ||
20 | void fimc_hw_reset(struct fimc_dev *dev) | |
21 | { | |
22 | u32 cfg; | |
23 | ||
c83a1ff0 SN |
24 | cfg = readl(dev->regs + FIMC_REG_CISRCFMT); |
25 | cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; | |
26 | writel(cfg, dev->regs + FIMC_REG_CISRCFMT); | |
5fd8f738 SN |
27 | |
28 | /* Software reset. */ | |
c83a1ff0 SN |
29 | cfg = readl(dev->regs + FIMC_REG_CIGCTRL); |
30 | cfg |= (FIMC_REG_CIGCTRL_SWRST | FIMC_REG_CIGCTRL_IRQ_LEVEL); | |
31 | writel(cfg, dev->regs + FIMC_REG_CIGCTRL); | |
e9e21083 | 32 | udelay(10); |
5fd8f738 | 33 | |
c83a1ff0 SN |
34 | cfg = readl(dev->regs + FIMC_REG_CIGCTRL); |
35 | cfg &= ~FIMC_REG_CIGCTRL_SWRST; | |
36 | writel(cfg, dev->regs + FIMC_REG_CIGCTRL); | |
2c1bb62e SN |
37 | |
38 | if (dev->variant->out_buf_count > 4) | |
39 | fimc_hw_set_dma_seq(dev, 0xF); | |
5fd8f738 SN |
40 | } |
41 | ||
ac75934c | 42 | static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx) |
5fd8f738 | 43 | { |
c83a1ff0 | 44 | u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL; |
5fd8f738 | 45 | |
131b6c61 | 46 | if (ctx->hflip) |
c83a1ff0 | 47 | flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR; |
131b6c61 | 48 | if (ctx->vflip) |
c83a1ff0 | 49 | flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR; |
131b6c61 | 50 | |
ac75934c SN |
51 | if (ctx->rotation <= 90) |
52 | return flip; | |
5fd8f738 | 53 | |
c83a1ff0 | 54 | return (flip ^ FIMC_REG_MSCTRL_FLIP_180) & FIMC_REG_MSCTRL_FLIP_180; |
5fd8f738 SN |
55 | } |
56 | ||
ac75934c | 57 | static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx) |
5fd8f738 | 58 | { |
c83a1ff0 | 59 | u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL; |
5fd8f738 | 60 | |
131b6c61 | 61 | if (ctx->hflip) |
c83a1ff0 | 62 | flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR; |
131b6c61 | 63 | if (ctx->vflip) |
c83a1ff0 | 64 | flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR; |
131b6c61 | 65 | |
ac75934c SN |
66 | if (ctx->rotation <= 90) |
67 | return flip; | |
68 | ||
c83a1ff0 | 69 | return (flip ^ FIMC_REG_CITRGFMT_FLIP_180) & FIMC_REG_CITRGFMT_FLIP_180; |
5fd8f738 SN |
70 | } |
71 | ||
47654df8 SN |
72 | void fimc_hw_set_rotation(struct fimc_ctx *ctx) |
73 | { | |
74 | u32 cfg, flip; | |
75 | struct fimc_dev *dev = ctx->fimc_dev; | |
76 | ||
c83a1ff0 SN |
77 | cfg = readl(dev->regs + FIMC_REG_CITRGFMT); |
78 | cfg &= ~(FIMC_REG_CITRGFMT_INROT90 | FIMC_REG_CITRGFMT_OUTROT90 | | |
79 | FIMC_REG_CITRGFMT_FLIP_180); | |
47654df8 SN |
80 | |
81 | /* | |
82 | * The input and output rotator cannot work simultaneously. | |
83 | * Use the output rotator in output DMA mode or the input rotator | |
84 | * in direct fifo output mode. | |
85 | */ | |
86 | if (ctx->rotation == 90 || ctx->rotation == 270) { | |
3d112d9a | 87 | if (ctx->out_path == FIMC_IO_LCDFIFO) |
c83a1ff0 | 88 | cfg |= FIMC_REG_CITRGFMT_INROT90; |
47654df8 | 89 | else |
c83a1ff0 | 90 | cfg |= FIMC_REG_CITRGFMT_OUTROT90; |
47654df8 | 91 | } |
47654df8 | 92 | |
3d112d9a | 93 | if (ctx->out_path == FIMC_IO_DMA) { |
ac75934c | 94 | cfg |= fimc_hw_get_target_flip(ctx); |
c83a1ff0 | 95 | writel(cfg, dev->regs + FIMC_REG_CITRGFMT); |
ac75934c SN |
96 | } else { |
97 | /* LCD FIFO path */ | |
c83a1ff0 SN |
98 | flip = readl(dev->regs + FIMC_REG_MSCTRL); |
99 | flip &= ~FIMC_REG_MSCTRL_FLIP_MASK; | |
ac75934c | 100 | flip |= fimc_hw_get_in_flip(ctx); |
c83a1ff0 | 101 | writel(flip, dev->regs + FIMC_REG_MSCTRL); |
ac75934c | 102 | } |
47654df8 SN |
103 | } |
104 | ||
5fd8f738 SN |
105 | void fimc_hw_set_target_format(struct fimc_ctx *ctx) |
106 | { | |
107 | u32 cfg; | |
108 | struct fimc_dev *dev = ctx->fimc_dev; | |
109 | struct fimc_frame *frame = &ctx->d_frame; | |
110 | ||
111 | dbg("w= %d, h= %d color: %d", frame->width, | |
c83a1ff0 | 112 | frame->height, frame->fmt->color); |
5fd8f738 | 113 | |
c83a1ff0 SN |
114 | cfg = readl(dev->regs + FIMC_REG_CITRGFMT); |
115 | cfg &= ~(FIMC_REG_CITRGFMT_FMT_MASK | FIMC_REG_CITRGFMT_HSIZE_MASK | | |
116 | FIMC_REG_CITRGFMT_VSIZE_MASK); | |
5fd8f738 SN |
117 | |
118 | switch (frame->fmt->color) { | |
3d112d9a | 119 | case FIMC_FMT_RGB444...FIMC_FMT_RGB888: |
c83a1ff0 | 120 | cfg |= FIMC_REG_CITRGFMT_RGB; |
5fd8f738 | 121 | break; |
3d112d9a | 122 | case FIMC_FMT_YCBCR420: |
c83a1ff0 | 123 | cfg |= FIMC_REG_CITRGFMT_YCBCR420; |
5fd8f738 | 124 | break; |
3d112d9a | 125 | case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422: |
ef7af59b | 126 | if (frame->fmt->colplanes == 1) |
c83a1ff0 | 127 | cfg |= FIMC_REG_CITRGFMT_YCBCR422_1P; |
5fd8f738 | 128 | else |
c83a1ff0 | 129 | cfg |= FIMC_REG_CITRGFMT_YCBCR422; |
5fd8f738 SN |
130 | break; |
131 | default: | |
132 | break; | |
133 | } | |
134 | ||
c83a1ff0 SN |
135 | if (ctx->rotation == 90 || ctx->rotation == 270) |
136 | cfg |= (frame->height << 16) | frame->width; | |
137 | else | |
138 | cfg |= (frame->width << 16) | frame->height; | |
47654df8 | 139 | |
c83a1ff0 | 140 | writel(cfg, dev->regs + FIMC_REG_CITRGFMT); |
5fd8f738 | 141 | |
c83a1ff0 SN |
142 | cfg = readl(dev->regs + FIMC_REG_CITAREA); |
143 | cfg &= ~FIMC_REG_CITAREA_MASK; | |
5fd8f738 | 144 | cfg |= (frame->width * frame->height); |
c83a1ff0 | 145 | writel(cfg, dev->regs + FIMC_REG_CITAREA); |
5fd8f738 SN |
146 | } |
147 | ||
148 | static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx) | |
149 | { | |
150 | struct fimc_dev *dev = ctx->fimc_dev; | |
151 | struct fimc_frame *frame = &ctx->d_frame; | |
47654df8 | 152 | u32 cfg; |
5fd8f738 | 153 | |
c83a1ff0 SN |
154 | cfg = (frame->f_height << 16) | frame->f_width; |
155 | writel(cfg, dev->regs + FIMC_REG_ORGOSIZE); | |
5f3cc447 SN |
156 | |
157 | /* Select color space conversion equation (HD/SD size).*/ | |
c83a1ff0 | 158 | cfg = readl(dev->regs + FIMC_REG_CIGCTRL); |
5f3cc447 | 159 | if (frame->f_width >= 1280) /* HD */ |
c83a1ff0 | 160 | cfg |= FIMC_REG_CIGCTRL_CSC_ITU601_709; |
5f3cc447 | 161 | else /* SD */ |
c83a1ff0 SN |
162 | cfg &= ~FIMC_REG_CIGCTRL_CSC_ITU601_709; |
163 | writel(cfg, dev->regs + FIMC_REG_CIGCTRL); | |
5f3cc447 | 164 | |
5fd8f738 SN |
165 | } |
166 | ||
167 | void fimc_hw_set_out_dma(struct fimc_ctx *ctx) | |
168 | { | |
5fd8f738 SN |
169 | struct fimc_dev *dev = ctx->fimc_dev; |
170 | struct fimc_frame *frame = &ctx->d_frame; | |
171 | struct fimc_dma_offset *offset = &frame->dma_offset; | |
dafb9c70 | 172 | struct fimc_fmt *fmt = frame->fmt; |
c83a1ff0 | 173 | u32 cfg; |
5fd8f738 SN |
174 | |
175 | /* Set the input dma offsets. */ | |
c83a1ff0 SN |
176 | cfg = (offset->y_v << 16) | offset->y_h; |
177 | writel(cfg, dev->regs + FIMC_REG_CIOYOFF); | |
5fd8f738 | 178 | |
c83a1ff0 SN |
179 | cfg = (offset->cb_v << 16) | offset->cb_h; |
180 | writel(cfg, dev->regs + FIMC_REG_CIOCBOFF); | |
5fd8f738 | 181 | |
c83a1ff0 SN |
182 | cfg = (offset->cr_v << 16) | offset->cr_h; |
183 | writel(cfg, dev->regs + FIMC_REG_CIOCROFF); | |
5fd8f738 SN |
184 | |
185 | fimc_hw_set_out_dma_size(ctx); | |
186 | ||
187 | /* Configure chroma components order. */ | |
c83a1ff0 | 188 | cfg = readl(dev->regs + FIMC_REG_CIOCTRL); |
5fd8f738 | 189 | |
c83a1ff0 SN |
190 | cfg &= ~(FIMC_REG_CIOCTRL_ORDER2P_MASK | |
191 | FIMC_REG_CIOCTRL_ORDER422_MASK | | |
192 | FIMC_REG_CIOCTRL_YCBCR_PLANE_MASK | | |
193 | FIMC_REG_CIOCTRL_RGB16FMT_MASK); | |
5fd8f738 | 194 | |
dafb9c70 | 195 | if (fmt->colplanes == 1) |
5fd8f738 | 196 | cfg |= ctx->out_order_1p; |
dafb9c70 | 197 | else if (fmt->colplanes == 2) |
c83a1ff0 | 198 | cfg |= ctx->out_order_2p | FIMC_REG_CIOCTRL_YCBCR_2PLANE; |
dafb9c70 | 199 | else if (fmt->colplanes == 3) |
c83a1ff0 | 200 | cfg |= FIMC_REG_CIOCTRL_YCBCR_3PLANE; |
5fd8f738 | 201 | |
3d112d9a | 202 | if (fmt->color == FIMC_FMT_RGB565) |
c83a1ff0 | 203 | cfg |= FIMC_REG_CIOCTRL_RGB565; |
3d112d9a | 204 | else if (fmt->color == FIMC_FMT_RGB555) |
c83a1ff0 | 205 | cfg |= FIMC_REG_CIOCTRL_ARGB1555; |
3d112d9a | 206 | else if (fmt->color == FIMC_FMT_RGB444) |
c83a1ff0 | 207 | cfg |= FIMC_REG_CIOCTRL_ARGB4444; |
dafb9c70 | 208 | |
c83a1ff0 | 209 | writel(cfg, dev->regs + FIMC_REG_CIOCTRL); |
5fd8f738 SN |
210 | } |
211 | ||
212 | static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable) | |
213 | { | |
c83a1ff0 | 214 | u32 cfg = readl(dev->regs + FIMC_REG_ORGISIZE); |
5fd8f738 | 215 | if (enable) |
c83a1ff0 | 216 | cfg |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN; |
5fd8f738 | 217 | else |
c83a1ff0 SN |
218 | cfg &= ~FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN; |
219 | writel(cfg, dev->regs + FIMC_REG_ORGISIZE); | |
5fd8f738 SN |
220 | } |
221 | ||
222 | void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable) | |
223 | { | |
c83a1ff0 | 224 | u32 cfg = readl(dev->regs + FIMC_REG_CIOCTRL); |
5fd8f738 | 225 | if (enable) |
c83a1ff0 | 226 | cfg |= FIMC_REG_CIOCTRL_LASTIRQ_ENABLE; |
5fd8f738 | 227 | else |
c83a1ff0 SN |
228 | cfg &= ~FIMC_REG_CIOCTRL_LASTIRQ_ENABLE; |
229 | writel(cfg, dev->regs + FIMC_REG_CIOCTRL); | |
5fd8f738 SN |
230 | } |
231 | ||
b241c6d6 | 232 | void fimc_hw_set_prescaler(struct fimc_ctx *ctx) |
5fd8f738 SN |
233 | { |
234 | struct fimc_dev *dev = ctx->fimc_dev; | |
235 | struct fimc_scaler *sc = &ctx->scaler; | |
548aafcd | 236 | u32 cfg, shfactor; |
5fd8f738 SN |
237 | |
238 | shfactor = 10 - (sc->hfactor + sc->vfactor); | |
c83a1ff0 | 239 | cfg = shfactor << 28; |
5fd8f738 | 240 | |
c83a1ff0 SN |
241 | cfg |= (sc->pre_hratio << 16) | sc->pre_vratio; |
242 | writel(cfg, dev->regs + FIMC_REG_CISCPRERATIO); | |
5fd8f738 | 243 | |
c83a1ff0 SN |
244 | cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height; |
245 | writel(cfg, dev->regs + FIMC_REG_CISCPREDST); | |
5fd8f738 SN |
246 | } |
247 | ||
b241c6d6 | 248 | static void fimc_hw_set_scaler(struct fimc_ctx *ctx) |
5fd8f738 SN |
249 | { |
250 | struct fimc_dev *dev = ctx->fimc_dev; | |
251 | struct fimc_scaler *sc = &ctx->scaler; | |
252 | struct fimc_frame *src_frame = &ctx->s_frame; | |
253 | struct fimc_frame *dst_frame = &ctx->d_frame; | |
2c1bb62e | 254 | |
c83a1ff0 | 255 | u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL); |
2c1bb62e | 256 | |
c83a1ff0 SN |
257 | cfg &= ~(FIMC_REG_CISCCTRL_CSCR2Y_WIDE | FIMC_REG_CISCCTRL_CSCY2R_WIDE | |
258 | FIMC_REG_CISCCTRL_SCALEUP_H | FIMC_REG_CISCCTRL_SCALEUP_V | | |
259 | FIMC_REG_CISCCTRL_SCALERBYPASS | FIMC_REG_CISCCTRL_ONE2ONE | | |
260 | FIMC_REG_CISCCTRL_INRGB_FMT_MASK | FIMC_REG_CISCCTRL_OUTRGB_FMT_MASK | | |
261 | FIMC_REG_CISCCTRL_INTERLACE | FIMC_REG_CISCCTRL_RGB_EXT); | |
5fd8f738 SN |
262 | |
263 | if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW)) | |
c83a1ff0 SN |
264 | cfg |= (FIMC_REG_CISCCTRL_CSCR2Y_WIDE | |
265 | FIMC_REG_CISCCTRL_CSCY2R_WIDE); | |
5fd8f738 SN |
266 | |
267 | if (!sc->enabled) | |
c83a1ff0 | 268 | cfg |= FIMC_REG_CISCCTRL_SCALERBYPASS; |
5fd8f738 SN |
269 | |
270 | if (sc->scaleup_h) | |
c83a1ff0 | 271 | cfg |= FIMC_REG_CISCCTRL_SCALEUP_H; |
5fd8f738 SN |
272 | |
273 | if (sc->scaleup_v) | |
c83a1ff0 | 274 | cfg |= FIMC_REG_CISCCTRL_SCALEUP_V; |
5fd8f738 SN |
275 | |
276 | if (sc->copy_mode) | |
c83a1ff0 | 277 | cfg |= FIMC_REG_CISCCTRL_ONE2ONE; |
5fd8f738 | 278 | |
3d112d9a | 279 | if (ctx->in_path == FIMC_IO_DMA) { |
dafb9c70 | 280 | switch (src_frame->fmt->color) { |
3d112d9a | 281 | case FIMC_FMT_RGB565: |
c83a1ff0 | 282 | cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB565; |
dafb9c70 | 283 | break; |
3d112d9a | 284 | case FIMC_FMT_RGB666: |
c83a1ff0 | 285 | cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB666; |
dafb9c70 | 286 | break; |
3d112d9a | 287 | case FIMC_FMT_RGB888: |
c83a1ff0 | 288 | cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB888; |
dafb9c70 SN |
289 | break; |
290 | } | |
5fd8f738 SN |
291 | } |
292 | ||
3d112d9a | 293 | if (ctx->out_path == FIMC_IO_DMA) { |
dafb9c70 SN |
294 | u32 color = dst_frame->fmt->color; |
295 | ||
3d112d9a | 296 | if (color >= FIMC_FMT_RGB444 && color <= FIMC_FMT_RGB565) |
c83a1ff0 | 297 | cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565; |
3d112d9a | 298 | else if (color == FIMC_FMT_RGB666) |
c83a1ff0 | 299 | cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666; |
3d112d9a | 300 | else if (color == FIMC_FMT_RGB888) |
c83a1ff0 | 301 | cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888; |
5fd8f738 | 302 | } else { |
c83a1ff0 | 303 | cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888; |
5fd8f738 SN |
304 | |
305 | if (ctx->flags & FIMC_SCAN_MODE_INTERLACED) | |
c83a1ff0 | 306 | cfg |= FIMC_REG_CISCCTRL_INTERLACE; |
5fd8f738 SN |
307 | } |
308 | ||
c83a1ff0 | 309 | writel(cfg, dev->regs + FIMC_REG_CISCCTRL); |
b241c6d6 HK |
310 | } |
311 | ||
312 | void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) | |
313 | { | |
314 | struct fimc_dev *dev = ctx->fimc_dev; | |
bb7c276e | 315 | struct fimc_variant *variant = dev->variant; |
b241c6d6 HK |
316 | struct fimc_scaler *sc = &ctx->scaler; |
317 | u32 cfg; | |
318 | ||
319 | dbg("main_hratio= 0x%X main_vratio= 0x%X", | |
c83a1ff0 | 320 | sc->main_hratio, sc->main_vratio); |
b241c6d6 HK |
321 | |
322 | fimc_hw_set_scaler(ctx); | |
323 | ||
c83a1ff0 SN |
324 | cfg = readl(dev->regs + FIMC_REG_CISCCTRL); |
325 | cfg &= ~(FIMC_REG_CISCCTRL_MHRATIO_MASK | | |
326 | FIMC_REG_CISCCTRL_MVRATIO_MASK); | |
b241c6d6 | 327 | |
70f66ea2 | 328 | if (variant->has_mainscaler_ext) { |
c83a1ff0 SN |
329 | cfg |= FIMC_REG_CISCCTRL_MHRATIO_EXT(sc->main_hratio); |
330 | cfg |= FIMC_REG_CISCCTRL_MVRATIO_EXT(sc->main_vratio); | |
331 | writel(cfg, dev->regs + FIMC_REG_CISCCTRL); | |
b241c6d6 | 332 | |
c83a1ff0 | 333 | cfg = readl(dev->regs + FIMC_REG_CIEXTEN); |
b241c6d6 | 334 | |
c83a1ff0 SN |
335 | cfg &= ~(FIMC_REG_CIEXTEN_MVRATIO_EXT_MASK | |
336 | FIMC_REG_CIEXTEN_MHRATIO_EXT_MASK); | |
337 | cfg |= FIMC_REG_CIEXTEN_MHRATIO_EXT(sc->main_hratio); | |
338 | cfg |= FIMC_REG_CIEXTEN_MVRATIO_EXT(sc->main_vratio); | |
339 | writel(cfg, dev->regs + FIMC_REG_CIEXTEN); | |
70f66ea2 | 340 | } else { |
c83a1ff0 SN |
341 | cfg |= FIMC_REG_CISCCTRL_MHRATIO(sc->main_hratio); |
342 | cfg |= FIMC_REG_CISCCTRL_MVRATIO(sc->main_vratio); | |
343 | writel(cfg, dev->regs + FIMC_REG_CISCCTRL); | |
70f66ea2 | 344 | } |
5fd8f738 SN |
345 | } |
346 | ||
347 | void fimc_hw_en_capture(struct fimc_ctx *ctx) | |
348 | { | |
349 | struct fimc_dev *dev = ctx->fimc_dev; | |
5fd8f738 | 350 | |
c83a1ff0 | 351 | u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT); |
5f3cc447 | 352 | |
3d112d9a | 353 | if (ctx->out_path == FIMC_IO_DMA) { |
5f3cc447 | 354 | /* one shot mode */ |
c83a1ff0 SN |
355 | cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE | |
356 | FIMC_REG_CIIMGCPT_IMGCPTEN; | |
5f3cc447 | 357 | } else { |
25985edc | 358 | /* Continuous frame capture mode (freerun). */ |
c83a1ff0 SN |
359 | cfg &= ~(FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE | |
360 | FIMC_REG_CIIMGCPT_CPT_FRMOD_CNT); | |
361 | cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN; | |
5f3cc447 | 362 | } |
5fd8f738 SN |
363 | |
364 | if (ctx->scaler.enabled) | |
c83a1ff0 | 365 | cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC; |
5fd8f738 | 366 | |
c83a1ff0 SN |
367 | cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN; |
368 | writel(cfg, dev->regs + FIMC_REG_CIIMGCPT); | |
5fd8f738 SN |
369 | } |
370 | ||
9448ab7d | 371 | void fimc_hw_set_effect(struct fimc_ctx *ctx) |
5fd8f738 SN |
372 | { |
373 | struct fimc_dev *dev = ctx->fimc_dev; | |
374 | struct fimc_effect *effect = &ctx->effect; | |
ee7160e5 | 375 | u32 cfg = 0; |
5fd8f738 | 376 | |
9448ab7d | 377 | if (effect->type != FIMC_REG_CIIMGEFF_FIN_BYPASS) { |
c83a1ff0 SN |
378 | cfg |= FIMC_REG_CIIMGEFF_IE_SC_AFTER | |
379 | FIMC_REG_CIIMGEFF_IE_ENABLE; | |
ee7160e5 | 380 | cfg |= effect->type; |
c83a1ff0 SN |
381 | if (effect->type == FIMC_REG_CIIMGEFF_FIN_ARBITRARY) |
382 | cfg |= (effect->pat_cb << 13) | effect->pat_cr; | |
5fd8f738 SN |
383 | } |
384 | ||
c83a1ff0 | 385 | writel(cfg, dev->regs + FIMC_REG_CIIMGEFF); |
5fd8f738 SN |
386 | } |
387 | ||
dafb9c70 SN |
388 | void 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 | ||
c83a1ff0 SN |
397 | cfg = readl(dev->regs + FIMC_REG_CIOCTRL); |
398 | cfg &= ~FIMC_REG_CIOCTRL_ALPHA_OUT_MASK; | |
dafb9c70 | 399 | cfg |= (frame->alpha << 4); |
c83a1ff0 | 400 | writel(cfg, dev->regs + FIMC_REG_CIOCTRL); |
dafb9c70 SN |
401 | } |
402 | ||
5fd8f738 SN |
403 | static 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 | ||
3d112d9a | 410 | if (FIMC_IO_LCDFIFO == ctx->out_path) |
c83a1ff0 | 411 | cfg_r |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN; |
5fd8f738 | 412 | |
c83a1ff0 SN |
413 | cfg_o |= (frame->f_height << 16) | frame->f_width; |
414 | cfg_r |= (frame->height << 16) | frame->width; | |
5fd8f738 | 415 | |
c83a1ff0 SN |
416 | writel(cfg_o, dev->regs + FIMC_REG_ORGISIZE); |
417 | writel(cfg_r, dev->regs + FIMC_REG_CIREAL_ISIZE); | |
5fd8f738 SN |
418 | } |
419 | ||
420 | void 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; | |
548aafcd | 425 | u32 cfg; |
5fd8f738 SN |
426 | |
427 | /* Set the pixel offsets. */ | |
c83a1ff0 SN |
428 | cfg = (offset->y_v << 16) | offset->y_h; |
429 | writel(cfg, dev->regs + FIMC_REG_CIIYOFF); | |
5fd8f738 | 430 | |
c83a1ff0 SN |
431 | cfg = (offset->cb_v << 16) | offset->cb_h; |
432 | writel(cfg, dev->regs + FIMC_REG_CIICBOFF); | |
5fd8f738 | 433 | |
c83a1ff0 SN |
434 | cfg = (offset->cr_v << 16) | offset->cr_h; |
435 | writel(cfg, dev->regs + FIMC_REG_CIICROFF); | |
5fd8f738 SN |
436 | |
437 | /* Input original and real size. */ | |
438 | fimc_hw_set_in_dma_size(ctx); | |
439 | ||
548aafcd | 440 | /* Use DMA autoload only in FIFO mode. */ |
3d112d9a | 441 | fimc_hw_en_autoload(dev, ctx->out_path == FIMC_IO_LCDFIFO); |
5fd8f738 SN |
442 | |
443 | /* Set the input DMA to process single frame only. */ | |
c83a1ff0 SN |
444 | 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 | |
449 | | FIMC_REG_MSCTRL_2P_IN_ORDER_MASK); | |
5fd8f738 | 450 | |
c83a1ff0 SN |
451 | cfg |= (FIMC_REG_MSCTRL_IN_BURST_COUNT(4) |
452 | | FIMC_REG_MSCTRL_INPUT_MEMORY | |
453 | | FIMC_REG_MSCTRL_FIFO_CTRL_FULL); | |
5fd8f738 SN |
454 | |
455 | switch (frame->fmt->color) { | |
3d112d9a | 456 | case FIMC_FMT_RGB565...FIMC_FMT_RGB888: |
c83a1ff0 | 457 | cfg |= FIMC_REG_MSCTRL_INFORMAT_RGB; |
5fd8f738 | 458 | break; |
3d112d9a | 459 | case FIMC_FMT_YCBCR420: |
c83a1ff0 | 460 | cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR420; |
5fd8f738 | 461 | |
ef7af59b | 462 | if (frame->fmt->colplanes == 2) |
c83a1ff0 | 463 | cfg |= ctx->in_order_2p | FIMC_REG_MSCTRL_C_INT_IN_2PLANE; |
5fd8f738 | 464 | else |
c83a1ff0 | 465 | cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE; |
5fd8f738 SN |
466 | |
467 | break; | |
3d112d9a | 468 | case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422: |
ef7af59b | 469 | if (frame->fmt->colplanes == 1) { |
5fd8f738 | 470 | cfg |= ctx->in_order_1p |
c83a1ff0 | 471 | | FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P; |
5fd8f738 | 472 | } else { |
c83a1ff0 | 473 | cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR422; |
5fd8f738 | 474 | |
ef7af59b | 475 | if (frame->fmt->colplanes == 2) |
5fd8f738 | 476 | cfg |= ctx->in_order_2p |
c83a1ff0 | 477 | | FIMC_REG_MSCTRL_C_INT_IN_2PLANE; |
5fd8f738 | 478 | else |
c83a1ff0 | 479 | cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE; |
5fd8f738 SN |
480 | } |
481 | break; | |
482 | default: | |
483 | break; | |
484 | } | |
485 | ||
c83a1ff0 | 486 | writel(cfg, dev->regs + FIMC_REG_MSCTRL); |
5fd8f738 SN |
487 | |
488 | /* Input/output DMA linear/tiled mode. */ | |
c83a1ff0 SN |
489 | cfg = readl(dev->regs + FIMC_REG_CIDMAPARAM); |
490 | cfg &= ~FIMC_REG_CIDMAPARAM_TILE_MASK; | |
5fd8f738 SN |
491 | |
492 | if (tiled_fmt(ctx->s_frame.fmt)) | |
c83a1ff0 | 493 | cfg |= FIMC_REG_CIDMAPARAM_R_64X32; |
5fd8f738 SN |
494 | |
495 | if (tiled_fmt(ctx->d_frame.fmt)) | |
c83a1ff0 | 496 | cfg |= FIMC_REG_CIDMAPARAM_W_64X32; |
5fd8f738 | 497 | |
c83a1ff0 | 498 | writel(cfg, dev->regs + FIMC_REG_CIDMAPARAM); |
5fd8f738 SN |
499 | } |
500 | ||
501 | ||
502 | void fimc_hw_set_input_path(struct fimc_ctx *ctx) | |
503 | { | |
504 | struct fimc_dev *dev = ctx->fimc_dev; | |
505 | ||
c83a1ff0 SN |
506 | u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL); |
507 | cfg &= ~FIMC_REG_MSCTRL_INPUT_MASK; | |
5fd8f738 | 508 | |
3d112d9a | 509 | if (ctx->in_path == FIMC_IO_DMA) |
c83a1ff0 | 510 | cfg |= FIMC_REG_MSCTRL_INPUT_MEMORY; |
5fd8f738 | 511 | else |
c83a1ff0 | 512 | cfg |= FIMC_REG_MSCTRL_INPUT_EXTCAM; |
5fd8f738 | 513 | |
c83a1ff0 | 514 | writel(cfg, dev->regs + FIMC_REG_MSCTRL); |
5fd8f738 SN |
515 | } |
516 | ||
517 | void fimc_hw_set_output_path(struct fimc_ctx *ctx) | |
518 | { | |
519 | struct fimc_dev *dev = ctx->fimc_dev; | |
520 | ||
c83a1ff0 SN |
521 | u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL); |
522 | cfg &= ~FIMC_REG_CISCCTRL_LCDPATHEN_FIFO; | |
3d112d9a | 523 | if (ctx->out_path == FIMC_IO_LCDFIFO) |
c83a1ff0 SN |
524 | cfg |= FIMC_REG_CISCCTRL_LCDPATHEN_FIFO; |
525 | writel(cfg, dev->regs + FIMC_REG_CISCCTRL); | |
5fd8f738 SN |
526 | } |
527 | ||
528 | void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr) | |
529 | { | |
c83a1ff0 SN |
530 | u32 cfg = readl(dev->regs + FIMC_REG_CIREAL_ISIZE); |
531 | cfg |= FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS; | |
532 | writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE); | |
5fd8f738 | 533 | |
c83a1ff0 SN |
534 | writel(paddr->y, dev->regs + FIMC_REG_CIIYSA(0)); |
535 | writel(paddr->cb, dev->regs + FIMC_REG_CIICBSA(0)); | |
536 | writel(paddr->cr, dev->regs + FIMC_REG_CIICRSA(0)); | |
5fd8f738 | 537 | |
c83a1ff0 SN |
538 | cfg &= ~FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS; |
539 | writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE); | |
5fd8f738 SN |
540 | } |
541 | ||
548aafcd SN |
542 | void fimc_hw_set_output_addr(struct fimc_dev *dev, |
543 | struct fimc_addr *paddr, int index) | |
5fd8f738 | 544 | { |
548aafcd SN |
545 | int i = (index == -1) ? 0 : index; |
546 | do { | |
c83a1ff0 SN |
547 | writel(paddr->y, dev->regs + FIMC_REG_CIOYSA(i)); |
548 | writel(paddr->cb, dev->regs + FIMC_REG_CIOCBSA(i)); | |
549 | writel(paddr->cr, dev->regs + FIMC_REG_CIOCRSA(i)); | |
548aafcd SN |
550 | dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X", |
551 | i, paddr->y, paddr->cb, paddr->cr); | |
552 | } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS); | |
5fd8f738 | 553 | } |
5f3cc447 SN |
554 | |
555 | int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, | |
df7e09a3 | 556 | struct s5p_fimc_isp_info *cam) |
5f3cc447 | 557 | { |
c83a1ff0 | 558 | u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL); |
5f3cc447 | 559 | |
c83a1ff0 SN |
560 | cfg &= ~(FIMC_REG_CIGCTRL_INVPOLPCLK | FIMC_REG_CIGCTRL_INVPOLVSYNC | |
561 | FIMC_REG_CIGCTRL_INVPOLHREF | FIMC_REG_CIGCTRL_INVPOLHSYNC | | |
562 | FIMC_REG_CIGCTRL_INVPOLFIELD); | |
5f3cc447 | 563 | |
12ecf56d | 564 | if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) |
c83a1ff0 | 565 | cfg |= FIMC_REG_CIGCTRL_INVPOLPCLK; |
5f3cc447 | 566 | |
12ecf56d | 567 | if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) |
c83a1ff0 | 568 | cfg |= FIMC_REG_CIGCTRL_INVPOLVSYNC; |
5f3cc447 | 569 | |
12ecf56d | 570 | if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) |
c83a1ff0 | 571 | cfg |= FIMC_REG_CIGCTRL_INVPOLHREF; |
5f3cc447 | 572 | |
12ecf56d | 573 | if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) |
c83a1ff0 | 574 | cfg |= FIMC_REG_CIGCTRL_INVPOLHSYNC; |
5f3cc447 | 575 | |
12ecf56d | 576 | if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW) |
c83a1ff0 | 577 | cfg |= FIMC_REG_CIGCTRL_INVPOLFIELD; |
12ecf56d | 578 | |
c83a1ff0 | 579 | writel(cfg, fimc->regs + FIMC_REG_CIGCTRL); |
5f3cc447 SN |
580 | |
581 | return 0; | |
582 | } | |
583 | ||
c83a1ff0 SN |
584 | struct mbus_pixfmt_desc { |
585 | u32 pixelcode; | |
586 | u32 cisrcfmt; | |
587 | u16 bus_width; | |
588 | }; | |
589 | ||
590 | static const struct mbus_pixfmt_desc pix_desc[] = { | |
591 | { V4L2_MBUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 }, | |
592 | { V4L2_MBUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 }, | |
593 | { V4L2_MBUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 }, | |
594 | { V4L2_MBUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 }, | |
595 | }; | |
596 | ||
5f3cc447 | 597 | int fimc_hw_set_camera_source(struct fimc_dev *fimc, |
df7e09a3 | 598 | struct s5p_fimc_isp_info *cam) |
5f3cc447 SN |
599 | { |
600 | struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; | |
601 | u32 cfg = 0; | |
3d0ce7ed SN |
602 | u32 bus_width; |
603 | int i; | |
604 | ||
5f3cc447 | 605 | if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) { |
3d0ce7ed | 606 | for (i = 0; i < ARRAY_SIZE(pix_desc); i++) { |
237e0265 | 607 | if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) { |
3d0ce7ed SN |
608 | cfg = pix_desc[i].cisrcfmt; |
609 | bus_width = pix_desc[i].bus_width; | |
610 | break; | |
611 | } | |
612 | } | |
5f3cc447 | 613 | |
3d0ce7ed | 614 | if (i == ARRAY_SIZE(pix_desc)) { |
30c9939d | 615 | v4l2_err(fimc->vid_cap.vfd, |
3d0ce7ed | 616 | "Camera color format not supported: %d\n", |
237e0265 | 617 | fimc->vid_cap.mf.code); |
5f3cc447 SN |
618 | return -EINVAL; |
619 | } | |
620 | ||
621 | if (cam->bus_type == FIMC_ITU_601) { | |
3d0ce7ed | 622 | if (bus_width == 8) |
c83a1ff0 | 623 | cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; |
3d0ce7ed | 624 | else if (bus_width == 16) |
c83a1ff0 | 625 | cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT; |
5f3cc447 | 626 | } /* else defaults to ITU-R BT.656 8-bit */ |
ee7160e5 SN |
627 | } else if (cam->bus_type == FIMC_MIPI_CSI2) { |
628 | if (fimc_fmt_is_jpeg(f->fmt->color)) | |
c83a1ff0 | 629 | cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; |
5f3cc447 SN |
630 | } |
631 | ||
c83a1ff0 SN |
632 | cfg |= (f->o_width << 16) | f->o_height; |
633 | writel(cfg, fimc->regs + FIMC_REG_CISRCFMT); | |
5f3cc447 SN |
634 | return 0; |
635 | } | |
636 | ||
c83a1ff0 | 637 | void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f) |
5f3cc447 SN |
638 | { |
639 | u32 hoff2, voff2; | |
640 | ||
c83a1ff0 | 641 | u32 cfg = readl(fimc->regs + FIMC_REG_CIWDOFST); |
5f3cc447 | 642 | |
c83a1ff0 SN |
643 | cfg &= ~(FIMC_REG_CIWDOFST_HOROFF_MASK | FIMC_REG_CIWDOFST_VEROFF_MASK); |
644 | cfg |= FIMC_REG_CIWDOFST_OFF_EN | | |
645 | (f->offs_h << 16) | f->offs_v; | |
5f3cc447 | 646 | |
c83a1ff0 | 647 | writel(cfg, fimc->regs + FIMC_REG_CIWDOFST); |
5f3cc447 SN |
648 | |
649 | /* See CIWDOFSTn register description in the datasheet for details. */ | |
650 | hoff2 = f->o_width - f->width - f->offs_h; | |
651 | voff2 = f->o_height - f->height - f->offs_v; | |
c83a1ff0 SN |
652 | cfg = (hoff2 << 16) | voff2; |
653 | writel(cfg, fimc->regs + FIMC_REG_CIWDOFST2); | |
5f3cc447 SN |
654 | } |
655 | ||
656 | int fimc_hw_set_camera_type(struct fimc_dev *fimc, | |
df7e09a3 | 657 | struct s5p_fimc_isp_info *cam) |
5f3cc447 SN |
658 | { |
659 | u32 cfg, tmp; | |
660 | struct fimc_vid_cap *vid_cap = &fimc->vid_cap; | |
20676a4c | 661 | u32 csis_data_alignment = 32; |
5f3cc447 | 662 | |
c83a1ff0 | 663 | cfg = readl(fimc->regs + FIMC_REG_CIGCTRL); |
5f3cc447 SN |
664 | |
665 | /* Select ITU B interface, disable Writeback path and test pattern. */ | |
c83a1ff0 SN |
666 | cfg &= ~(FIMC_REG_CIGCTRL_TESTPAT_MASK | FIMC_REG_CIGCTRL_SELCAM_ITU_A | |
667 | FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB | | |
668 | FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG); | |
5f3cc447 | 669 | |
31ce54f6 SN |
670 | switch (cam->bus_type) { |
671 | case FIMC_MIPI_CSI2: | |
c83a1ff0 | 672 | cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI; |
5f3cc447 SN |
673 | |
674 | if (cam->mux_id == 0) | |
c83a1ff0 | 675 | cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A; |
5f3cc447 SN |
676 | |
677 | /* TODO: add remaining supported formats. */ | |
ee7160e5 SN |
678 | switch (vid_cap->mf.code) { |
679 | case V4L2_MBUS_FMT_VYUY8_2X8: | |
c83a1ff0 | 680 | tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT; |
ee7160e5 SN |
681 | break; |
682 | case V4L2_MBUS_FMT_JPEG_1X8: | |
c83a1ff0 SN |
683 | tmp = FIMC_REG_CSIIMGFMT_USER(1); |
684 | cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; | |
ee7160e5 SN |
685 | break; |
686 | default: | |
a516d08f SK |
687 | v4l2_err(vid_cap->vfd, |
688 | "Not supported camera pixel format: %#x\n", | |
237e0265 | 689 | vid_cap->mf.code); |
5f3cc447 SN |
690 | return -EINVAL; |
691 | } | |
20676a4c | 692 | tmp |= (csis_data_alignment == 32) << 8; |
e0eec9af | 693 | |
c83a1ff0 | 694 | writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT); |
31ce54f6 SN |
695 | break; |
696 | case FIMC_ITU_601...FIMC_ITU_656: | |
5f3cc447 | 697 | if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */ |
c83a1ff0 | 698 | cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A; |
31ce54f6 SN |
699 | break; |
700 | case FIMC_LCD_WB: | |
c83a1ff0 | 701 | cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB; |
31ce54f6 SN |
702 | break; |
703 | default: | |
a516d08f | 704 | v4l2_err(vid_cap->vfd, "Invalid camera bus type selected\n"); |
5f3cc447 SN |
705 | return -EINVAL; |
706 | } | |
c83a1ff0 | 707 | writel(cfg, fimc->regs + FIMC_REG_CIGCTRL); |
5f3cc447 SN |
708 | |
709 | return 0; | |
710 | } | |
c83a1ff0 SN |
711 | |
712 | void fimc_hw_clear_irq(struct fimc_dev *dev) | |
713 | { | |
714 | u32 cfg = readl(dev->regs + FIMC_REG_CIGCTRL); | |
715 | cfg |= FIMC_REG_CIGCTRL_IRQ_CLR; | |
716 | writel(cfg, dev->regs + FIMC_REG_CIGCTRL); | |
717 | } | |
718 | ||
719 | void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on) | |
720 | { | |
721 | u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL); | |
722 | if (on) | |
723 | cfg |= FIMC_REG_CISCCTRL_SCALERSTART; | |
724 | else | |
725 | cfg &= ~FIMC_REG_CISCCTRL_SCALERSTART; | |
726 | writel(cfg, dev->regs + FIMC_REG_CISCCTRL); | |
727 | } | |
728 | ||
729 | void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on) | |
730 | { | |
731 | u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL); | |
732 | if (on) | |
733 | cfg |= FIMC_REG_MSCTRL_ENVID; | |
734 | else | |
735 | cfg &= ~FIMC_REG_MSCTRL_ENVID; | |
736 | writel(cfg, dev->regs + FIMC_REG_MSCTRL); | |
737 | } | |
738 | ||
739 | void fimc_hw_dis_capture(struct fimc_dev *dev) | |
740 | { | |
741 | u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT); | |
742 | cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN | FIMC_REG_CIIMGCPT_IMGCPTEN_SC); | |
743 | writel(cfg, dev->regs + FIMC_REG_CIIMGCPT); | |
744 | } | |
745 | ||
746 | /* Return an index to the buffer actually being written. */ | |
747 | u32 fimc_hw_get_frame_index(struct fimc_dev *dev) | |
748 | { | |
749 | u32 reg; | |
750 | ||
751 | if (dev->variant->has_cistatus2) { | |
752 | reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3F; | |
753 | return reg > 0 ? --reg : reg; | |
754 | } | |
755 | ||
756 | reg = readl(dev->regs + FIMC_REG_CISTATUS); | |
757 | ||
758 | return (reg & FIMC_REG_CISTATUS_FRAMECNT_MASK) >> | |
759 | FIMC_REG_CISTATUS_FRAMECNT_SHIFT; | |
760 | } | |
761 | ||
762 | /* Locking: the caller holds fimc->slock */ | |
763 | void fimc_activate_capture(struct fimc_ctx *ctx) | |
764 | { | |
765 | fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled); | |
766 | fimc_hw_en_capture(ctx); | |
767 | } | |
768 | ||
769 | void fimc_deactivate_capture(struct fimc_dev *fimc) | |
770 | { | |
771 | fimc_hw_en_lastirq(fimc, true); | |
772 | fimc_hw_dis_capture(fimc); | |
773 | fimc_hw_enable_scaler(fimc, false); | |
774 | fimc_hw_en_lastirq(fimc, false); | |
775 | } |