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