[media] move soc_camera i2c drivers into its own dir
[sfrench/cifs-2.6.git] / drivers / media / platform / s5p-fimc / fimc-reg.c
1 /*
2  * Register interface file for Samsung Camera Interface (FIMC) driver
3  *
4  * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
5  * Sylwester Nawrocki, <s.nawrocki@samsung.com>
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>
14 #include <media/s5p_fimc.h>
15
16 #include "fimc-reg.h"
17 #include "fimc-core.h"
18
19
20 void fimc_hw_reset(struct fimc_dev *dev)
21 {
22         u32 cfg;
23
24         cfg = readl(dev->regs + FIMC_REG_CISRCFMT);
25         cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
26         writel(cfg, dev->regs + FIMC_REG_CISRCFMT);
27
28         /* Software reset. */
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);
32         udelay(10);
33
34         cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
35         cfg &= ~FIMC_REG_CIGCTRL_SWRST;
36         writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
37
38         if (dev->variant->out_buf_count > 4)
39                 fimc_hw_set_dma_seq(dev, 0xF);
40 }
41
42 static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
43 {
44         u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL;
45
46         if (ctx->hflip)
47                 flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR;
48         if (ctx->vflip)
49                 flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR;
50
51         if (ctx->rotation <= 90)
52                 return flip;
53
54         return (flip ^ FIMC_REG_MSCTRL_FLIP_180) & FIMC_REG_MSCTRL_FLIP_180;
55 }
56
57 static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
58 {
59         u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL;
60
61         if (ctx->hflip)
62                 flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR;
63         if (ctx->vflip)
64                 flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR;
65
66         if (ctx->rotation <= 90)
67                 return flip;
68
69         return (flip ^ FIMC_REG_CITRGFMT_FLIP_180) & FIMC_REG_CITRGFMT_FLIP_180;
70 }
71
72 void fimc_hw_set_rotation(struct fimc_ctx *ctx)
73 {
74         u32 cfg, flip;
75         struct fimc_dev *dev = ctx->fimc_dev;
76
77         cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
78         cfg &= ~(FIMC_REG_CITRGFMT_INROT90 | FIMC_REG_CITRGFMT_OUTROT90 |
79                  FIMC_REG_CITRGFMT_FLIP_180);
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) {
87                 if (ctx->out_path == FIMC_IO_LCDFIFO)
88                         cfg |= FIMC_REG_CITRGFMT_INROT90;
89                 else
90                         cfg |= FIMC_REG_CITRGFMT_OUTROT90;
91         }
92
93         if (ctx->out_path == FIMC_IO_DMA) {
94                 cfg |= fimc_hw_get_target_flip(ctx);
95                 writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
96         } else {
97                 /* LCD FIFO path */
98                 flip = readl(dev->regs + FIMC_REG_MSCTRL);
99                 flip &= ~FIMC_REG_MSCTRL_FLIP_MASK;
100                 flip |= fimc_hw_get_in_flip(ctx);
101                 writel(flip, dev->regs + FIMC_REG_MSCTRL);
102         }
103 }
104
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,
112             frame->height, frame->fmt->color);
113
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);
117
118         switch (frame->fmt->color) {
119         case FIMC_FMT_RGB444...FIMC_FMT_RGB888:
120                 cfg |= FIMC_REG_CITRGFMT_RGB;
121                 break;
122         case FIMC_FMT_YCBCR420:
123                 cfg |= FIMC_REG_CITRGFMT_YCBCR420;
124                 break;
125         case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
126                 if (frame->fmt->colplanes == 1)
127                         cfg |= FIMC_REG_CITRGFMT_YCBCR422_1P;
128                 else
129                         cfg |= FIMC_REG_CITRGFMT_YCBCR422;
130                 break;
131         default:
132                 break;
133         }
134
135         if (ctx->rotation == 90 || ctx->rotation == 270)
136                 cfg |= (frame->height << 16) | frame->width;
137         else
138                 cfg |= (frame->width << 16) | frame->height;
139
140         writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
141
142         cfg = readl(dev->regs + FIMC_REG_CITAREA);
143         cfg &= ~FIMC_REG_CITAREA_MASK;
144         cfg |= (frame->width * frame->height);
145         writel(cfg, dev->regs + FIMC_REG_CITAREA);
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;
152         u32 cfg;
153
154         cfg = (frame->f_height << 16) | frame->f_width;
155         writel(cfg, dev->regs + FIMC_REG_ORGOSIZE);
156
157         /* Select color space conversion equation (HD/SD size).*/
158         cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
159         if (frame->f_width >= 1280) /* HD */
160                 cfg |= FIMC_REG_CIGCTRL_CSC_ITU601_709;
161         else    /* SD */
162                 cfg &= ~FIMC_REG_CIGCTRL_CSC_ITU601_709;
163         writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
164
165 }
166
167 void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
168 {
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;
172         struct fimc_fmt *fmt = frame->fmt;
173         u32 cfg;
174
175         /* Set the input dma offsets. */
176         cfg = (offset->y_v << 16) | offset->y_h;
177         writel(cfg, dev->regs + FIMC_REG_CIOYOFF);
178
179         cfg = (offset->cb_v << 16) | offset->cb_h;
180         writel(cfg, dev->regs + FIMC_REG_CIOCBOFF);
181
182         cfg = (offset->cr_v << 16) | offset->cr_h;
183         writel(cfg, dev->regs + FIMC_REG_CIOCROFF);
184
185         fimc_hw_set_out_dma_size(ctx);
186
187         /* Configure chroma components order. */
188         cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
189
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);
194
195         if (fmt->colplanes == 1)
196                 cfg |= ctx->out_order_1p;
197         else if (fmt->colplanes == 2)
198                 cfg |= ctx->out_order_2p | FIMC_REG_CIOCTRL_YCBCR_2PLANE;
199         else if (fmt->colplanes == 3)
200                 cfg |= FIMC_REG_CIOCTRL_YCBCR_3PLANE;
201
202         if (fmt->color == FIMC_FMT_RGB565)
203                 cfg |= FIMC_REG_CIOCTRL_RGB565;
204         else if (fmt->color == FIMC_FMT_RGB555)
205                 cfg |= FIMC_REG_CIOCTRL_ARGB1555;
206         else if (fmt->color == FIMC_FMT_RGB444)
207                 cfg |= FIMC_REG_CIOCTRL_ARGB4444;
208
209         writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
210 }
211
212 static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
213 {
214         u32 cfg = readl(dev->regs + FIMC_REG_ORGISIZE);
215         if (enable)
216                 cfg |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
217         else
218                 cfg &= ~FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
219         writel(cfg, dev->regs + FIMC_REG_ORGISIZE);
220 }
221
222 void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
223 {
224         u32 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
225         if (enable)
226                 cfg |= FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
227         else
228                 cfg &= ~FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
229         writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
230 }
231
232 void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
233 {
234         struct fimc_dev *dev =  ctx->fimc_dev;
235         struct fimc_scaler *sc = &ctx->scaler;
236         u32 cfg, shfactor;
237
238         shfactor = 10 - (sc->hfactor + sc->vfactor);
239         cfg = shfactor << 28;
240
241         cfg |= (sc->pre_hratio << 16) | sc->pre_vratio;
242         writel(cfg, dev->regs + FIMC_REG_CISCPRERATIO);
243
244         cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
245         writel(cfg, dev->regs + FIMC_REG_CISCPREDST);
246 }
247
248 static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
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;
254
255         u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
256
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);
262
263         if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
264                 cfg |= (FIMC_REG_CISCCTRL_CSCR2Y_WIDE |
265                         FIMC_REG_CISCCTRL_CSCY2R_WIDE);
266
267         if (!sc->enabled)
268                 cfg |= FIMC_REG_CISCCTRL_SCALERBYPASS;
269
270         if (sc->scaleup_h)
271                 cfg |= FIMC_REG_CISCCTRL_SCALEUP_H;
272
273         if (sc->scaleup_v)
274                 cfg |= FIMC_REG_CISCCTRL_SCALEUP_V;
275
276         if (sc->copy_mode)
277                 cfg |= FIMC_REG_CISCCTRL_ONE2ONE;
278
279         if (ctx->in_path == FIMC_IO_DMA) {
280                 switch (src_frame->fmt->color) {
281                 case FIMC_FMT_RGB565:
282                         cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB565;
283                         break;
284                 case FIMC_FMT_RGB666:
285                         cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB666;
286                         break;
287                 case FIMC_FMT_RGB888:
288                         cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB888;
289                         break;
290                 }
291         }
292
293         if (ctx->out_path == FIMC_IO_DMA) {
294                 u32 color = dst_frame->fmt->color;
295
296                 if (color >= FIMC_FMT_RGB444 && color <= FIMC_FMT_RGB565)
297                         cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565;
298                 else if (color == FIMC_FMT_RGB666)
299                         cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666;
300                 else if (color == FIMC_FMT_RGB888)
301                         cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
302         } else {
303                 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
304
305                 if (ctx->flags & FIMC_SCAN_MODE_INTERLACED)
306                         cfg |= FIMC_REG_CISCCTRL_INTERLACE;
307         }
308
309         writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
310 }
311
312 void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
313 {
314         struct fimc_dev *dev = ctx->fimc_dev;
315         struct fimc_variant *variant = dev->variant;
316         struct fimc_scaler *sc = &ctx->scaler;
317         u32 cfg;
318
319         dbg("main_hratio= 0x%X  main_vratio= 0x%X",
320             sc->main_hratio, sc->main_vratio);
321
322         fimc_hw_set_scaler(ctx);
323
324         cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
325         cfg &= ~(FIMC_REG_CISCCTRL_MHRATIO_MASK |
326                  FIMC_REG_CISCCTRL_MVRATIO_MASK);
327
328         if (variant->has_mainscaler_ext) {
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);
332
333                 cfg = readl(dev->regs + FIMC_REG_CIEXTEN);
334
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);
340         } else {
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);
344         }
345 }
346
347 void fimc_hw_en_capture(struct fimc_ctx *ctx)
348 {
349         struct fimc_dev *dev = ctx->fimc_dev;
350
351         u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
352
353         if (ctx->out_path == FIMC_IO_DMA) {
354                 /* one shot mode */
355                 cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE |
356                         FIMC_REG_CIIMGCPT_IMGCPTEN;
357         } else {
358                 /* Continuous frame capture mode (freerun). */
359                 cfg &= ~(FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE |
360                          FIMC_REG_CIIMGCPT_CPT_FRMOD_CNT);
361                 cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
362         }
363
364         if (ctx->scaler.enabled)
365                 cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
366
367         cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
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
451         cfg |= (FIMC_REG_MSCTRL_IN_BURST_COUNT(4)
452                 | FIMC_REG_MSCTRL_INPUT_MEMORY
453                 | FIMC_REG_MSCTRL_FIFO_CTRL_FULL);
454
455         switch (frame->fmt->color) {
456         case FIMC_FMT_RGB565...FIMC_FMT_RGB888:
457                 cfg |= FIMC_REG_MSCTRL_INFORMAT_RGB;
458                 break;
459         case FIMC_FMT_YCBCR420:
460                 cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR420;
461
462                 if (frame->fmt->colplanes == 2)
463                         cfg |= ctx->in_order_2p | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
464                 else
465                         cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
466
467                 break;
468         case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
469                 if (frame->fmt->colplanes == 1) {
470                         cfg |= ctx->in_order_1p
471                                 | FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P;
472                 } else {
473                         cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR422;
474
475                         if (frame->fmt->colplanes == 2)
476                                 cfg |= ctx->in_order_2p
477                                         | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
478                         else
479                                 cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
480                 }
481                 break;
482         default:
483                 break;
484         }
485
486         writel(cfg, dev->regs + FIMC_REG_MSCTRL);
487
488         /* Input/output DMA linear/tiled mode. */
489         cfg = readl(dev->regs + FIMC_REG_CIDMAPARAM);
490         cfg &= ~FIMC_REG_CIDMAPARAM_TILE_MASK;
491
492         if (tiled_fmt(ctx->s_frame.fmt))
493                 cfg |= FIMC_REG_CIDMAPARAM_R_64X32;
494
495         if (tiled_fmt(ctx->d_frame.fmt))
496                 cfg |= FIMC_REG_CIDMAPARAM_W_64X32;
497
498         writel(cfg, dev->regs + FIMC_REG_CIDMAPARAM);
499 }
500
501
502 void fimc_hw_set_input_path(struct fimc_ctx *ctx)
503 {
504         struct fimc_dev *dev = ctx->fimc_dev;
505
506         u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
507         cfg &= ~FIMC_REG_MSCTRL_INPUT_MASK;
508
509         if (ctx->in_path == FIMC_IO_DMA)
510                 cfg |= FIMC_REG_MSCTRL_INPUT_MEMORY;
511         else
512                 cfg |= FIMC_REG_MSCTRL_INPUT_EXTCAM;
513
514         writel(cfg, dev->regs + FIMC_REG_MSCTRL);
515 }
516
517 void fimc_hw_set_output_path(struct fimc_ctx *ctx)
518 {
519         struct fimc_dev *dev = ctx->fimc_dev;
520
521         u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
522         cfg &= ~FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
523         if (ctx->out_path == FIMC_IO_LCDFIFO)
524                 cfg |= FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
525         writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
526 }
527
528 void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
529 {
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);
533
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));
537
538         cfg &= ~FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
539         writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
540 }
541
542 void fimc_hw_set_output_addr(struct fimc_dev *dev,
543                              struct fimc_addr *paddr, int index)
544 {
545         int i = (index == -1) ? 0 : index;
546         do {
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));
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);
553 }
554
555 int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
556                                 struct s5p_fimc_isp_info *cam)
557 {
558         u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
559
560         cfg &= ~(FIMC_REG_CIGCTRL_INVPOLPCLK | FIMC_REG_CIGCTRL_INVPOLVSYNC |
561                  FIMC_REG_CIGCTRL_INVPOLHREF | FIMC_REG_CIGCTRL_INVPOLHSYNC |
562                  FIMC_REG_CIGCTRL_INVPOLFIELD);
563
564         if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
565                 cfg |= FIMC_REG_CIGCTRL_INVPOLPCLK;
566
567         if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
568                 cfg |= FIMC_REG_CIGCTRL_INVPOLVSYNC;
569
570         if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
571                 cfg |= FIMC_REG_CIGCTRL_INVPOLHREF;
572
573         if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
574                 cfg |= FIMC_REG_CIGCTRL_INVPOLHSYNC;
575
576         if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW)
577                 cfg |= FIMC_REG_CIGCTRL_INVPOLFIELD;
578
579         writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
580
581         return 0;
582 }
583
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
597 int fimc_hw_set_camera_source(struct fimc_dev *fimc,
598                               struct s5p_fimc_isp_info *cam)
599 {
600         struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
601         u32 cfg = 0;
602         u32 bus_width;
603         int i;
604
605         if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) {
606                 for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
607                         if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) {
608                                 cfg = pix_desc[i].cisrcfmt;
609                                 bus_width = pix_desc[i].bus_width;
610                                 break;
611                         }
612                 }
613
614                 if (i == ARRAY_SIZE(pix_desc)) {
615                         v4l2_err(fimc->vid_cap.vfd,
616                                  "Camera color format not supported: %d\n",
617                                  fimc->vid_cap.mf.code);
618                         return -EINVAL;
619                 }
620
621                 if (cam->bus_type == FIMC_ITU_601) {
622                         if (bus_width == 8)
623                                 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
624                         else if (bus_width == 16)
625                                 cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
626                 } /* else defaults to ITU-R BT.656 8-bit */
627         } else if (cam->bus_type == FIMC_MIPI_CSI2) {
628                 if (fimc_fmt_is_jpeg(f->fmt->color))
629                         cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
630         }
631
632         cfg |= (f->o_width << 16) | f->o_height;
633         writel(cfg, fimc->regs + FIMC_REG_CISRCFMT);
634         return 0;
635 }
636
637 void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
638 {
639         u32 hoff2, voff2;
640
641         u32 cfg = readl(fimc->regs + FIMC_REG_CIWDOFST);
642
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;
646
647         writel(cfg, fimc->regs + FIMC_REG_CIWDOFST);
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;
652         cfg = (hoff2 << 16) | voff2;
653         writel(cfg, fimc->regs + FIMC_REG_CIWDOFST2);
654 }
655
656 int fimc_hw_set_camera_type(struct fimc_dev *fimc,
657                             struct s5p_fimc_isp_info *cam)
658 {
659         u32 cfg, tmp;
660         struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
661         u32 csis_data_alignment = 32;
662
663         cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
664
665         /* Select ITU B interface, disable Writeback path and test pattern. */
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);
669
670         switch (cam->bus_type) {
671         case FIMC_MIPI_CSI2:
672                 cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI;
673
674                 if (cam->mux_id == 0)
675                         cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A;
676
677                 /* TODO: add remaining supported formats. */
678                 switch (vid_cap->mf.code) {
679                 case V4L2_MBUS_FMT_VYUY8_2X8:
680                         tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
681                         break;
682                 case V4L2_MBUS_FMT_JPEG_1X8:
683                         tmp = FIMC_REG_CSIIMGFMT_USER(1);
684                         cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
685                         break;
686                 default:
687                         v4l2_err(vid_cap->vfd,
688                                  "Not supported camera pixel format: %#x\n",
689                                  vid_cap->mf.code);
690                         return -EINVAL;
691                 }
692                 tmp |= (csis_data_alignment == 32) << 8;
693
694                 writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT);
695                 break;
696         case FIMC_ITU_601...FIMC_ITU_656:
697                 if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
698                         cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A;
699                 break;
700         case FIMC_LCD_WB:
701                 cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
702                 break;
703         default:
704                 v4l2_err(vid_cap->vfd, "Invalid camera bus type selected\n");
705                 return -EINVAL;
706         }
707         writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
708
709         return 0;
710 }
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 }