Merge tag 'arc-5.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
[linux-2.6-microblaze.git] / drivers / media / platform / exynos4-is / fimc-reg.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Register interface file for Samsung Camera Interface (FIMC) driver
4  *
5  * Copyright (C) 2010 - 2013 Samsung Electronics Co., Ltd.
6  * Sylwester Nawrocki <s.nawrocki@samsung.com>
7 */
8
9 #include <linux/delay.h>
10 #include <linux/io.h>
11 #include <linux/regmap.h>
12
13 #include <media/drv-intf/exynos-fimc.h>
14 #include "media-dev.h"
15
16 #include "fimc-reg.h"
17 #include "fimc-core.h"
18
19 void fimc_hw_reset(struct fimc_dev *dev)
20 {
21         u32 cfg;
22
23         cfg = readl(dev->regs + FIMC_REG_CISRCFMT);
24         cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
25         writel(cfg, dev->regs + FIMC_REG_CISRCFMT);
26
27         /* Software reset. */
28         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);
31         udelay(10);
32
33         cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
34         cfg &= ~FIMC_REG_CIGCTRL_SWRST;
35         writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
36
37         if (dev->drv_data->out_buf_count > 4)
38                 fimc_hw_set_dma_seq(dev, 0xF);
39 }
40
41 static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
42 {
43         u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL;
44
45         if (ctx->hflip)
46                 flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR;
47         if (ctx->vflip)
48                 flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR;
49
50         if (ctx->rotation <= 90)
51                 return flip;
52
53         return (flip ^ FIMC_REG_MSCTRL_FLIP_180) & FIMC_REG_MSCTRL_FLIP_180;
54 }
55
56 static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
57 {
58         u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL;
59
60         if (ctx->hflip)
61                 flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR;
62         if (ctx->vflip)
63                 flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR;
64
65         if (ctx->rotation <= 90)
66                 return flip;
67
68         return (flip ^ FIMC_REG_CITRGFMT_FLIP_180) & FIMC_REG_CITRGFMT_FLIP_180;
69 }
70
71 void fimc_hw_set_rotation(struct fimc_ctx *ctx)
72 {
73         u32 cfg, flip;
74         struct fimc_dev *dev = ctx->fimc_dev;
75
76         cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
77         cfg &= ~(FIMC_REG_CITRGFMT_INROT90 | FIMC_REG_CITRGFMT_OUTROT90 |
78                  FIMC_REG_CITRGFMT_FLIP_180);
79
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) {
86                 if (ctx->out_path == FIMC_IO_LCDFIFO)
87                         cfg |= FIMC_REG_CITRGFMT_INROT90;
88                 else
89                         cfg |= FIMC_REG_CITRGFMT_OUTROT90;
90         }
91
92         if (ctx->out_path == FIMC_IO_DMA) {
93                 cfg |= fimc_hw_get_target_flip(ctx);
94                 writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
95         } else {
96                 /* LCD FIFO path */
97                 flip = readl(dev->regs + FIMC_REG_MSCTRL);
98                 flip &= ~FIMC_REG_MSCTRL_FLIP_MASK;
99                 flip |= fimc_hw_get_in_flip(ctx);
100                 writel(flip, dev->regs + FIMC_REG_MSCTRL);
101         }
102 }
103
104 void 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,
111             frame->height, frame->fmt->color);
112
113         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);
116
117         switch (frame->fmt->color) {
118         case FIMC_FMT_RGB444...FIMC_FMT_RGB888:
119                 cfg |= FIMC_REG_CITRGFMT_RGB;
120                 break;
121         case FIMC_FMT_YCBCR420:
122                 cfg |= FIMC_REG_CITRGFMT_YCBCR420;
123                 break;
124         case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
125                 if (frame->fmt->colplanes == 1)
126                         cfg |= FIMC_REG_CITRGFMT_YCBCR422_1P;
127                 else
128                         cfg |= FIMC_REG_CITRGFMT_YCBCR422;
129                 break;
130         default:
131                 break;
132         }
133
134         if (ctx->rotation == 90 || ctx->rotation == 270)
135                 cfg |= (frame->height << 16) | frame->width;
136         else
137                 cfg |= (frame->width << 16) | frame->height;
138
139         writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
140
141         cfg = readl(dev->regs + FIMC_REG_CITAREA);
142         cfg &= ~FIMC_REG_CITAREA_MASK;
143         cfg |= (frame->width * frame->height);
144         writel(cfg, dev->regs + FIMC_REG_CITAREA);
145 }
146
147 static 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;
151         u32 cfg;
152
153         cfg = (frame->f_height << 16) | frame->f_width;
154         writel(cfg, dev->regs + FIMC_REG_ORGOSIZE);
155
156         /* Select color space conversion equation (HD/SD size).*/
157         cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
158         if (frame->f_width >= 1280) /* HD */
159                 cfg |= FIMC_REG_CIGCTRL_CSC_ITU601_709;
160         else    /* SD */
161                 cfg &= ~FIMC_REG_CIGCTRL_CSC_ITU601_709;
162         writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
163
164 }
165
166 void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
167 {
168         struct fimc_dev *dev = ctx->fimc_dev;
169         struct fimc_frame *frame = &ctx->d_frame;
170         struct fimc_dma_offset *offset = &frame->dma_offset;
171         struct fimc_fmt *fmt = frame->fmt;
172         u32 cfg;
173
174         /* Set the input dma offsets. */
175         cfg = (offset->y_v << 16) | offset->y_h;
176         writel(cfg, dev->regs + FIMC_REG_CIOYOFF);
177
178         cfg = (offset->cb_v << 16) | offset->cb_h;
179         writel(cfg, dev->regs + FIMC_REG_CIOCBOFF);
180
181         cfg = (offset->cr_v << 16) | offset->cr_h;
182         writel(cfg, dev->regs + FIMC_REG_CIOCROFF);
183
184         fimc_hw_set_out_dma_size(ctx);
185
186         /* Configure chroma components order. */
187         cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
188
189         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);
193
194         if (fmt->colplanes == 1)
195                 cfg |= ctx->out_order_1p;
196         else if (fmt->colplanes == 2)
197                 cfg |= ctx->out_order_2p | FIMC_REG_CIOCTRL_YCBCR_2PLANE;
198         else if (fmt->colplanes == 3)
199                 cfg |= FIMC_REG_CIOCTRL_YCBCR_3PLANE;
200
201         if (fmt->color == FIMC_FMT_RGB565)
202                 cfg |= FIMC_REG_CIOCTRL_RGB565;
203         else if (fmt->color == FIMC_FMT_RGB555)
204                 cfg |= FIMC_REG_CIOCTRL_ARGB1555;
205         else if (fmt->color == FIMC_FMT_RGB444)
206                 cfg |= FIMC_REG_CIOCTRL_ARGB4444;
207
208         writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
209 }
210
211 static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
212 {
213         u32 cfg = readl(dev->regs + FIMC_REG_ORGISIZE);
214         if (enable)
215                 cfg |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
216         else
217                 cfg &= ~FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
218         writel(cfg, dev->regs + FIMC_REG_ORGISIZE);
219 }
220
221 void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
222 {
223         u32 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
224         if (enable)
225                 cfg |= FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
226         else
227                 cfg &= ~FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
228         writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
229 }
230
231 void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
232 {
233         struct fimc_dev *dev =  ctx->fimc_dev;
234         struct fimc_scaler *sc = &ctx->scaler;
235         u32 cfg, shfactor;
236
237         shfactor = 10 - (sc->hfactor + sc->vfactor);
238         cfg = shfactor << 28;
239
240         cfg |= (sc->pre_hratio << 16) | sc->pre_vratio;
241         writel(cfg, dev->regs + FIMC_REG_CISCPRERATIO);
242
243         cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
244         writel(cfg, dev->regs + FIMC_REG_CISCPREDST);
245 }
246
247 static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
248 {
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;
253
254         u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
255
256         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);
261
262         if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
263                 cfg |= (FIMC_REG_CISCCTRL_CSCR2Y_WIDE |
264                         FIMC_REG_CISCCTRL_CSCY2R_WIDE);
265
266         if (!sc->enabled)
267                 cfg |= FIMC_REG_CISCCTRL_SCALERBYPASS;
268
269         if (sc->scaleup_h)
270                 cfg |= FIMC_REG_CISCCTRL_SCALEUP_H;
271
272         if (sc->scaleup_v)
273                 cfg |= FIMC_REG_CISCCTRL_SCALEUP_V;
274
275         if (sc->copy_mode)
276                 cfg |= FIMC_REG_CISCCTRL_ONE2ONE;
277
278         if (ctx->in_path == FIMC_IO_DMA) {
279                 switch (src_frame->fmt->color) {
280                 case FIMC_FMT_RGB565:
281                         cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB565;
282                         break;
283                 case FIMC_FMT_RGB666:
284                         cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB666;
285                         break;
286                 case FIMC_FMT_RGB888:
287                         cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB888;
288                         break;
289                 }
290         }
291
292         if (ctx->out_path == FIMC_IO_DMA) {
293                 u32 color = dst_frame->fmt->color;
294
295                 if (color >= FIMC_FMT_RGB444 && color <= FIMC_FMT_RGB565)
296                         cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565;
297                 else if (color == FIMC_FMT_RGB666)
298                         cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666;
299                 else if (color == FIMC_FMT_RGB888)
300                         cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
301         } else {
302                 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
303
304                 if (ctx->flags & FIMC_SCAN_MODE_INTERLACED)
305                         cfg |= FIMC_REG_CISCCTRL_INTERLACE;
306         }
307
308         writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
309 }
310
311 void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
312 {
313         struct fimc_dev *dev = ctx->fimc_dev;
314         const struct fimc_variant *variant = dev->variant;
315         struct fimc_scaler *sc = &ctx->scaler;
316         u32 cfg;
317
318         dbg("main_hratio= 0x%X  main_vratio= 0x%X",
319             sc->main_hratio, sc->main_vratio);
320
321         fimc_hw_set_scaler(ctx);
322
323         cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
324         cfg &= ~(FIMC_REG_CISCCTRL_MHRATIO_MASK |
325                  FIMC_REG_CISCCTRL_MVRATIO_MASK);
326
327         if (variant->has_mainscaler_ext) {
328                 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);
331
332                 cfg = readl(dev->regs + FIMC_REG_CIEXTEN);
333
334                 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);
339         } else {
340                 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);
343         }
344 }
345
346 void fimc_hw_enable_capture(struct fimc_ctx *ctx)
347 {
348         struct fimc_dev *dev = ctx->fimc_dev;
349         u32 cfg;
350
351         cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
352         cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE;
353
354         if (ctx->scaler.enabled)
355                 cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
356         else
357                 cfg &= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
358
359         cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
360         writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
361 }
362
363 void 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
371 void fimc_hw_set_effect(struct fimc_ctx *ctx)
372 {
373         struct fimc_dev *dev = ctx->fimc_dev;
374         struct fimc_effect *effect = &ctx->effect;
375         u32 cfg = 0;
376
377         if (effect->type != FIMC_REG_CIIMGEFF_FIN_BYPASS) {
378                 cfg |= FIMC_REG_CIIMGEFF_IE_SC_AFTER |
379                         FIMC_REG_CIIMGEFF_IE_ENABLE;
380                 cfg |= effect->type;
381                 if (effect->type == FIMC_REG_CIIMGEFF_FIN_ARBITRARY)
382                         cfg |= (effect->pat_cb << 13) | effect->pat_cr;
383         }
384
385         writel(cfg, dev->regs + FIMC_REG_CIIMGEFF);
386 }
387
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
397         cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
398         cfg &= ~FIMC_REG_CIOCTRL_ALPHA_OUT_MASK;
399         cfg |= (frame->alpha << 4);
400         writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
401 }
402
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
410         if (FIMC_IO_LCDFIFO == ctx->out_path)
411                 cfg_r |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
412
413         cfg_o |= (frame->f_height << 16) | frame->f_width;
414         cfg_r |= (frame->height << 16) | frame->width;
415
416         writel(cfg_o, dev->regs + FIMC_REG_ORGISIZE);
417         writel(cfg_r, dev->regs + FIMC_REG_CIREAL_ISIZE);
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;
425         u32 cfg;
426
427         /* Set the pixel offsets. */
428         cfg = (offset->y_v << 16) | offset->y_h;
429         writel(cfg, dev->regs + FIMC_REG_CIIYOFF);
430
431         cfg = (offset->cb_v << 16) | offset->cb_h;
432         writel(cfg, dev->regs + FIMC_REG_CIICBOFF);
433
434         cfg = (offset->cr_v << 16) | offset->cr_h;
435         writel(cfg, dev->regs + FIMC_REG_CIICROFF);
436
437         /* Input original and real size. */
438         fimc_hw_set_in_dma_size(ctx);
439
440         /* Use DMA autoload only in FIFO mode. */
441         fimc_hw_en_autoload(dev, ctx->out_path == FIMC_IO_LCDFIFO);
442
443         /* Set the input DMA to process single frame only. */
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
450                  | FIMC_REG_MSCTRL_ORDER422_MASK);
451
452         cfg |= (FIMC_REG_MSCTRL_IN_BURST_COUNT(4)
453                 | FIMC_REG_MSCTRL_INPUT_MEMORY
454                 | FIMC_REG_MSCTRL_FIFO_CTRL_FULL);
455
456         switch (frame->fmt->color) {
457         case FIMC_FMT_RGB565...FIMC_FMT_RGB888:
458                 cfg |= FIMC_REG_MSCTRL_INFORMAT_RGB;
459                 break;
460         case FIMC_FMT_YCBCR420:
461                 cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR420;
462
463                 if (frame->fmt->colplanes == 2)
464                         cfg |= ctx->in_order_2p | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
465                 else
466                         cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
467
468                 break;
469         case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
470                 if (frame->fmt->colplanes == 1) {
471                         cfg |= ctx->in_order_1p
472                                 | FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P;
473                 } else {
474                         cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR422;
475
476                         if (frame->fmt->colplanes == 2)
477                                 cfg |= ctx->in_order_2p
478                                         | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
479                         else
480                                 cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
481                 }
482                 break;
483         default:
484                 break;
485         }
486
487         writel(cfg, dev->regs + FIMC_REG_MSCTRL);
488
489         /* Input/output DMA linear/tiled mode. */
490         cfg = readl(dev->regs + FIMC_REG_CIDMAPARAM);
491         cfg &= ~FIMC_REG_CIDMAPARAM_TILE_MASK;
492
493         if (tiled_fmt(ctx->s_frame.fmt))
494                 cfg |= FIMC_REG_CIDMAPARAM_R_64X32;
495
496         if (tiled_fmt(ctx->d_frame.fmt))
497                 cfg |= FIMC_REG_CIDMAPARAM_W_64X32;
498
499         writel(cfg, dev->regs + FIMC_REG_CIDMAPARAM);
500 }
501
502
503 void fimc_hw_set_input_path(struct fimc_ctx *ctx)
504 {
505         struct fimc_dev *dev = ctx->fimc_dev;
506
507         u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
508         cfg &= ~FIMC_REG_MSCTRL_INPUT_MASK;
509
510         if (ctx->in_path == FIMC_IO_DMA)
511                 cfg |= FIMC_REG_MSCTRL_INPUT_MEMORY;
512         else
513                 cfg |= FIMC_REG_MSCTRL_INPUT_EXTCAM;
514
515         writel(cfg, dev->regs + FIMC_REG_MSCTRL);
516 }
517
518 void fimc_hw_set_output_path(struct fimc_ctx *ctx)
519 {
520         struct fimc_dev *dev = ctx->fimc_dev;
521
522         u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
523         cfg &= ~FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
524         if (ctx->out_path == FIMC_IO_LCDFIFO)
525                 cfg |= FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
526         writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
527 }
528
529 void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
530 {
531         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);
534
535         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));
538
539         cfg &= ~FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
540         writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
541 }
542
543 void fimc_hw_set_output_addr(struct fimc_dev *dev,
544                              struct fimc_addr *paddr, int index)
545 {
546         int i = (index == -1) ? 0 : index;
547         do {
548                 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));
551                 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);
554 }
555
556 int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
557                                 struct fimc_source_info *cam)
558 {
559         u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
560
561         cfg &= ~(FIMC_REG_CIGCTRL_INVPOLPCLK | FIMC_REG_CIGCTRL_INVPOLVSYNC |
562                  FIMC_REG_CIGCTRL_INVPOLHREF | FIMC_REG_CIGCTRL_INVPOLHSYNC |
563                  FIMC_REG_CIGCTRL_INVPOLFIELD);
564
565         if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
566                 cfg |= FIMC_REG_CIGCTRL_INVPOLPCLK;
567
568         if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
569                 cfg |= FIMC_REG_CIGCTRL_INVPOLVSYNC;
570
571         if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
572                 cfg |= FIMC_REG_CIGCTRL_INVPOLHREF;
573
574         if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
575                 cfg |= FIMC_REG_CIGCTRL_INVPOLHSYNC;
576
577         if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW)
578                 cfg |= FIMC_REG_CIGCTRL_INVPOLFIELD;
579
580         writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
581
582         return 0;
583 }
584
585 struct mbus_pixfmt_desc {
586         u32 pixelcode;
587         u32 cisrcfmt;
588         u16 bus_width;
589 };
590
591 static const struct mbus_pixfmt_desc pix_desc[] = {
592         { 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 },
596 };
597
598 int fimc_hw_set_camera_source(struct fimc_dev *fimc,
599                               struct fimc_source_info *source)
600 {
601         struct fimc_vid_cap *vc = &fimc->vid_cap;
602         struct fimc_frame *f = &vc->ctx->s_frame;
603         u32 bus_width, cfg = 0;
604         int i;
605
606         switch (source->fimc_bus_type) {
607         case FIMC_BUS_TYPE_ITU_601:
608         case FIMC_BUS_TYPE_ITU_656:
609                 for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
610                         if (vc->ci_fmt.code == pix_desc[i].pixelcode) {
611                                 cfg = pix_desc[i].cisrcfmt;
612                                 bus_width = pix_desc[i].bus_width;
613                                 break;
614                         }
615                 }
616
617                 if (i == ARRAY_SIZE(pix_desc)) {
618                         v4l2_err(&vc->ve.vdev,
619                                  "Camera color format not supported: %d\n",
620                                  vc->ci_fmt.code);
621                         return -EINVAL;
622                 }
623
624                 if (source->fimc_bus_type == FIMC_BUS_TYPE_ITU_601) {
625                         if (bus_width == 8)
626                                 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
627                         else if (bus_width == 16)
628                                 cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
629                 } /* else defaults to ITU-R BT.656 8-bit */
630                 break;
631         case FIMC_BUS_TYPE_MIPI_CSI2:
632                 if (fimc_fmt_is_user_defined(f->fmt->color))
633                         cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
634                 break;
635         default:
636         case FIMC_BUS_TYPE_ISP_WRITEBACK:
637                 /* Anything to do here ? */
638                 break;
639         }
640
641         cfg |= (f->o_width << 16) | f->o_height;
642         writel(cfg, fimc->regs + FIMC_REG_CISRCFMT);
643         return 0;
644 }
645
646 void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
647 {
648         u32 hoff2, voff2;
649
650         u32 cfg = readl(fimc->regs + FIMC_REG_CIWDOFST);
651
652         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;
655
656         writel(cfg, fimc->regs + FIMC_REG_CIWDOFST);
657
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;
661         cfg = (hoff2 << 16) | voff2;
662         writel(cfg, fimc->regs + FIMC_REG_CIWDOFST2);
663 }
664
665 int fimc_hw_set_camera_type(struct fimc_dev *fimc,
666                             struct fimc_source_info *source)
667 {
668         struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
669         u32 csis_data_alignment = 32;
670         u32 cfg, tmp;
671
672         cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
673
674         /* Select ITU B interface, disable Writeback path and test pattern. */
675         cfg &= ~(FIMC_REG_CIGCTRL_TESTPAT_MASK | FIMC_REG_CIGCTRL_SELCAM_ITU_A |
676                 FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB |
677                 FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG |
678                 FIMC_REG_CIGCTRL_SELWB_A);
679
680         switch (source->fimc_bus_type) {
681         case FIMC_BUS_TYPE_MIPI_CSI2:
682                 cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI;
683
684                 if (source->mux_id == 0)
685                         cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A;
686
687                 /* TODO: add remaining supported formats. */
688                 switch (vid_cap->ci_fmt.code) {
689                 case MEDIA_BUS_FMT_VYUY8_2X8:
690                         tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
691                         break;
692                 case MEDIA_BUS_FMT_JPEG_1X8:
693                 case MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8:
694                         tmp = FIMC_REG_CSIIMGFMT_USER(1);
695                         cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
696                         break;
697                 default:
698                         v4l2_err(&vid_cap->ve.vdev,
699                                  "Not supported camera pixel format: %#x\n",
700                                  vid_cap->ci_fmt.code);
701                         return -EINVAL;
702                 }
703                 tmp |= (csis_data_alignment == 32) << 8;
704
705                 writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT);
706                 break;
707         case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656:
708                 if (source->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
709                         cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A;
710                 break;
711         case FIMC_BUS_TYPE_LCD_WRITEBACK_A:
712                 cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
713                 /* 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");
719                 break;
720         default:
721                 v4l2_err(&vid_cap->ve.vdev,
722                          "Invalid FIMC bus type selected: %d\n",
723                          source->fimc_bus_type);
724                 return -EINVAL;
725         }
726         writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
727
728         return 0;
729 }
730
731 void 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
738 void 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
748 void 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
758 /* Return an index to the buffer actually being written. */
759 s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
760 {
761         s32 reg;
762
763         if (dev->drv_data->cistatus2) {
764                 reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
765                 return reg - 1;
766         }
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
774 /* Return an index to the buffer being written previously. */
775 s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
776 {
777         s32 reg;
778
779         if (!dev->drv_data->cistatus2)
780                 return -1;
781
782         reg = readl(dev->regs + FIMC_REG_CISTATUS2);
783         return ((reg >> 7) & 0x3f) - 1;
784 }
785
786 /* Locking: the caller holds fimc->slock */
787 void fimc_activate_capture(struct fimc_ctx *ctx)
788 {
789         fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled);
790         fimc_hw_enable_capture(ctx);
791 }
792
793 void fimc_deactivate_capture(struct fimc_dev *fimc)
794 {
795         fimc_hw_en_lastirq(fimc, true);
796         fimc_hw_disable_capture(fimc);
797         fimc_hw_enable_scaler(fimc, false);
798         fimc_hw_en_lastirq(fimc, false);
799 }
800
801 int 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
807         if (map == NULL)
808                 return 0;
809
810         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 }