2 * Register interface file for Samsung Camera Interface (FIMC) driver
4 * Copyright (c) 2010 Samsung Electronics
6 * Sylwester Nawrocki, s.nawrocki@samsung.com
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 #include <linux/delay.h>
16 #include <media/s5p_fimc.h>
18 #include "fimc-core.h"
21 void fimc_hw_reset(struct fimc_dev
*dev
)
25 cfg
= readl(dev
->regs
+ S5P_CISRCFMT
);
26 cfg
|= S5P_CISRCFMT_ITU601_8BIT
;
27 writel(cfg
, dev
->regs
+ S5P_CISRCFMT
);
30 cfg
= readl(dev
->regs
+ S5P_CIGCTRL
);
31 cfg
|= (S5P_CIGCTRL_SWRST
| S5P_CIGCTRL_IRQ_LEVEL
);
32 writel(cfg
, dev
->regs
+ S5P_CIGCTRL
);
35 cfg
= readl(dev
->regs
+ S5P_CIGCTRL
);
36 cfg
&= ~S5P_CIGCTRL_SWRST
;
37 writel(cfg
, dev
->regs
+ S5P_CIGCTRL
);
39 if (dev
->variant
->out_buf_count
> 4)
40 fimc_hw_set_dma_seq(dev
, 0xF);
43 static u32
fimc_hw_get_in_flip(struct fimc_ctx
*ctx
)
45 u32 flip
= S5P_MSCTRL_FLIP_NORMAL
;
48 flip
= S5P_MSCTRL_FLIP_X_MIRROR
;
50 flip
= S5P_MSCTRL_FLIP_Y_MIRROR
;
52 if (ctx
->rotation
<= 90)
55 return (flip
^ S5P_MSCTRL_FLIP_180
) & S5P_MSCTRL_FLIP_180
;
58 static u32
fimc_hw_get_target_flip(struct fimc_ctx
*ctx
)
60 u32 flip
= S5P_CITRGFMT_FLIP_NORMAL
;
63 flip
|= S5P_CITRGFMT_FLIP_X_MIRROR
;
65 flip
|= S5P_CITRGFMT_FLIP_Y_MIRROR
;
67 if (ctx
->rotation
<= 90)
70 return (flip
^ S5P_CITRGFMT_FLIP_180
) & S5P_CITRGFMT_FLIP_180
;
73 void fimc_hw_set_rotation(struct fimc_ctx
*ctx
)
76 struct fimc_dev
*dev
= ctx
->fimc_dev
;
78 cfg
= readl(dev
->regs
+ S5P_CITRGFMT
);
79 cfg
&= ~(S5P_CITRGFMT_INROT90
| S5P_CITRGFMT_OUTROT90
|
80 S5P_CITRGFMT_FLIP_180
);
83 * The input and output rotator cannot work simultaneously.
84 * Use the output rotator in output DMA mode or the input rotator
85 * in direct fifo output mode.
87 if (ctx
->rotation
== 90 || ctx
->rotation
== 270) {
88 if (ctx
->out_path
== FIMC_LCDFIFO
)
89 cfg
|= S5P_CITRGFMT_INROT90
;
91 cfg
|= S5P_CITRGFMT_OUTROT90
;
94 if (ctx
->out_path
== FIMC_DMA
) {
95 cfg
|= fimc_hw_get_target_flip(ctx
);
96 writel(cfg
, dev
->regs
+ S5P_CITRGFMT
);
99 flip
= readl(dev
->regs
+ S5P_MSCTRL
);
100 flip
&= ~S5P_MSCTRL_FLIP_MASK
;
101 flip
|= fimc_hw_get_in_flip(ctx
);
102 writel(flip
, dev
->regs
+ S5P_MSCTRL
);
106 void fimc_hw_set_target_format(struct fimc_ctx
*ctx
)
109 struct fimc_dev
*dev
= ctx
->fimc_dev
;
110 struct fimc_frame
*frame
= &ctx
->d_frame
;
112 dbg("w= %d, h= %d color: %d", frame
->width
,
113 frame
->height
, frame
->fmt
->color
);
115 cfg
= readl(dev
->regs
+ S5P_CITRGFMT
);
116 cfg
&= ~(S5P_CITRGFMT_FMT_MASK
| S5P_CITRGFMT_HSIZE_MASK
|
117 S5P_CITRGFMT_VSIZE_MASK
);
119 switch (frame
->fmt
->color
) {
120 case S5P_FIMC_RGB444
...S5P_FIMC_RGB888
:
121 cfg
|= S5P_CITRGFMT_RGB
;
123 case S5P_FIMC_YCBCR420
:
124 cfg
|= S5P_CITRGFMT_YCBCR420
;
126 case S5P_FIMC_YCBYCR422
...S5P_FIMC_CRYCBY422
:
127 if (frame
->fmt
->colplanes
== 1)
128 cfg
|= S5P_CITRGFMT_YCBCR422_1P
;
130 cfg
|= S5P_CITRGFMT_YCBCR422
;
136 if (ctx
->rotation
== 90 || ctx
->rotation
== 270) {
137 cfg
|= S5P_CITRGFMT_HSIZE(frame
->height
);
138 cfg
|= S5P_CITRGFMT_VSIZE(frame
->width
);
141 cfg
|= S5P_CITRGFMT_HSIZE(frame
->width
);
142 cfg
|= S5P_CITRGFMT_VSIZE(frame
->height
);
145 writel(cfg
, dev
->regs
+ S5P_CITRGFMT
);
147 cfg
= readl(dev
->regs
+ S5P_CITAREA
) & ~S5P_CITAREA_MASK
;
148 cfg
|= (frame
->width
* frame
->height
);
149 writel(cfg
, dev
->regs
+ S5P_CITAREA
);
152 static void fimc_hw_set_out_dma_size(struct fimc_ctx
*ctx
)
154 struct fimc_dev
*dev
= ctx
->fimc_dev
;
155 struct fimc_frame
*frame
= &ctx
->d_frame
;
158 cfg
= S5P_ORIG_SIZE_HOR(frame
->f_width
);
159 cfg
|= S5P_ORIG_SIZE_VER(frame
->f_height
);
160 writel(cfg
, dev
->regs
+ S5P_ORGOSIZE
);
162 /* Select color space conversion equation (HD/SD size).*/
163 cfg
= readl(dev
->regs
+ S5P_CIGCTRL
);
164 if (frame
->f_width
>= 1280) /* HD */
165 cfg
|= S5P_CIGCTRL_CSC_ITU601_709
;
167 cfg
&= ~S5P_CIGCTRL_CSC_ITU601_709
;
168 writel(cfg
, dev
->regs
+ S5P_CIGCTRL
);
172 void fimc_hw_set_out_dma(struct fimc_ctx
*ctx
)
175 struct fimc_dev
*dev
= ctx
->fimc_dev
;
176 struct fimc_frame
*frame
= &ctx
->d_frame
;
177 struct fimc_dma_offset
*offset
= &frame
->dma_offset
;
178 struct fimc_fmt
*fmt
= frame
->fmt
;
180 /* Set the input dma offsets. */
182 cfg
|= S5P_CIO_OFFS_HOR(offset
->y_h
);
183 cfg
|= S5P_CIO_OFFS_VER(offset
->y_v
);
184 writel(cfg
, dev
->regs
+ S5P_CIOYOFF
);
187 cfg
|= S5P_CIO_OFFS_HOR(offset
->cb_h
);
188 cfg
|= S5P_CIO_OFFS_VER(offset
->cb_v
);
189 writel(cfg
, dev
->regs
+ S5P_CIOCBOFF
);
192 cfg
|= S5P_CIO_OFFS_HOR(offset
->cr_h
);
193 cfg
|= S5P_CIO_OFFS_VER(offset
->cr_v
);
194 writel(cfg
, dev
->regs
+ S5P_CIOCROFF
);
196 fimc_hw_set_out_dma_size(ctx
);
198 /* Configure chroma components order. */
199 cfg
= readl(dev
->regs
+ S5P_CIOCTRL
);
201 cfg
&= ~(S5P_CIOCTRL_ORDER2P_MASK
| S5P_CIOCTRL_ORDER422_MASK
|
202 S5P_CIOCTRL_YCBCR_PLANE_MASK
| S5P_CIOCTRL_RGB16FMT_MASK
);
204 if (fmt
->colplanes
== 1)
205 cfg
|= ctx
->out_order_1p
;
206 else if (fmt
->colplanes
== 2)
207 cfg
|= ctx
->out_order_2p
| S5P_CIOCTRL_YCBCR_2PLANE
;
208 else if (fmt
->colplanes
== 3)
209 cfg
|= S5P_CIOCTRL_YCBCR_3PLANE
;
211 if (fmt
->color
== S5P_FIMC_RGB565
)
212 cfg
|= S5P_CIOCTRL_RGB565
;
213 else if (fmt
->color
== S5P_FIMC_RGB555
)
214 cfg
|= S5P_CIOCTRL_ARGB1555
;
215 else if (fmt
->color
== S5P_FIMC_RGB444
)
216 cfg
|= S5P_CIOCTRL_ARGB4444
;
218 writel(cfg
, dev
->regs
+ S5P_CIOCTRL
);
221 static void fimc_hw_en_autoload(struct fimc_dev
*dev
, int enable
)
223 u32 cfg
= readl(dev
->regs
+ S5P_ORGISIZE
);
225 cfg
|= S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
227 cfg
&= ~S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
228 writel(cfg
, dev
->regs
+ S5P_ORGISIZE
);
231 void fimc_hw_en_lastirq(struct fimc_dev
*dev
, int enable
)
233 u32 cfg
= readl(dev
->regs
+ S5P_CIOCTRL
);
235 cfg
|= S5P_CIOCTRL_LASTIRQ_ENABLE
;
237 cfg
&= ~S5P_CIOCTRL_LASTIRQ_ENABLE
;
238 writel(cfg
, dev
->regs
+ S5P_CIOCTRL
);
241 void fimc_hw_set_prescaler(struct fimc_ctx
*ctx
)
243 struct fimc_dev
*dev
= ctx
->fimc_dev
;
244 struct fimc_scaler
*sc
= &ctx
->scaler
;
247 shfactor
= 10 - (sc
->hfactor
+ sc
->vfactor
);
249 cfg
= S5P_CISCPRERATIO_SHFACTOR(shfactor
);
250 cfg
|= S5P_CISCPRERATIO_HOR(sc
->pre_hratio
);
251 cfg
|= S5P_CISCPRERATIO_VER(sc
->pre_vratio
);
252 writel(cfg
, dev
->regs
+ S5P_CISCPRERATIO
);
254 cfg
= S5P_CISCPREDST_WIDTH(sc
->pre_dst_width
);
255 cfg
|= S5P_CISCPREDST_HEIGHT(sc
->pre_dst_height
);
256 writel(cfg
, dev
->regs
+ S5P_CISCPREDST
);
259 static void fimc_hw_set_scaler(struct fimc_ctx
*ctx
)
261 struct fimc_dev
*dev
= ctx
->fimc_dev
;
262 struct fimc_scaler
*sc
= &ctx
->scaler
;
263 struct fimc_frame
*src_frame
= &ctx
->s_frame
;
264 struct fimc_frame
*dst_frame
= &ctx
->d_frame
;
266 u32 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
268 cfg
&= ~(S5P_CISCCTRL_CSCR2Y_WIDE
| S5P_CISCCTRL_CSCY2R_WIDE
|
269 S5P_CISCCTRL_SCALEUP_H
| S5P_CISCCTRL_SCALEUP_V
|
270 S5P_CISCCTRL_SCALERBYPASS
| S5P_CISCCTRL_ONE2ONE
|
271 S5P_CISCCTRL_INRGB_FMT_MASK
| S5P_CISCCTRL_OUTRGB_FMT_MASK
|
272 S5P_CISCCTRL_INTERLACE
| S5P_CISCCTRL_RGB_EXT
);
274 if (!(ctx
->flags
& FIMC_COLOR_RANGE_NARROW
))
275 cfg
|= (S5P_CISCCTRL_CSCR2Y_WIDE
| S5P_CISCCTRL_CSCY2R_WIDE
);
278 cfg
|= S5P_CISCCTRL_SCALERBYPASS
;
281 cfg
|= S5P_CISCCTRL_SCALEUP_H
;
284 cfg
|= S5P_CISCCTRL_SCALEUP_V
;
287 cfg
|= S5P_CISCCTRL_ONE2ONE
;
289 if (ctx
->in_path
== FIMC_DMA
) {
290 switch (src_frame
->fmt
->color
) {
291 case S5P_FIMC_RGB565
:
292 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB565
;
294 case S5P_FIMC_RGB666
:
295 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB666
;
297 case S5P_FIMC_RGB888
:
298 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB888
;
303 if (ctx
->out_path
== FIMC_DMA
) {
304 u32 color
= dst_frame
->fmt
->color
;
306 if (color
>= S5P_FIMC_RGB444
&& color
<= S5P_FIMC_RGB565
)
307 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB565
;
308 else if (color
== S5P_FIMC_RGB666
)
309 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB666
;
310 else if (color
== S5P_FIMC_RGB888
)
311 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB888
;
313 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB888
;
315 if (ctx
->flags
& FIMC_SCAN_MODE_INTERLACED
)
316 cfg
|= S5P_CISCCTRL_INTERLACE
;
319 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
322 void fimc_hw_set_mainscaler(struct fimc_ctx
*ctx
)
324 struct fimc_dev
*dev
= ctx
->fimc_dev
;
325 struct samsung_fimc_variant
*variant
= dev
->variant
;
326 struct fimc_scaler
*sc
= &ctx
->scaler
;
329 dbg("main_hratio= 0x%X main_vratio= 0x%X",
330 sc
->main_hratio
, sc
->main_vratio
);
332 fimc_hw_set_scaler(ctx
);
334 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
335 cfg
&= ~(S5P_CISCCTRL_MHRATIO_MASK
| S5P_CISCCTRL_MVRATIO_MASK
);
337 if (variant
->has_mainscaler_ext
) {
338 cfg
|= S5P_CISCCTRL_MHRATIO_EXT(sc
->main_hratio
);
339 cfg
|= S5P_CISCCTRL_MVRATIO_EXT(sc
->main_vratio
);
340 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
342 cfg
= readl(dev
->regs
+ S5P_CIEXTEN
);
344 cfg
&= ~(S5P_CIEXTEN_MVRATIO_EXT_MASK
|
345 S5P_CIEXTEN_MHRATIO_EXT_MASK
);
346 cfg
|= S5P_CIEXTEN_MHRATIO_EXT(sc
->main_hratio
);
347 cfg
|= S5P_CIEXTEN_MVRATIO_EXT(sc
->main_vratio
);
348 writel(cfg
, dev
->regs
+ S5P_CIEXTEN
);
350 cfg
|= S5P_CISCCTRL_MHRATIO(sc
->main_hratio
);
351 cfg
|= S5P_CISCCTRL_MVRATIO(sc
->main_vratio
);
352 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
356 void fimc_hw_en_capture(struct fimc_ctx
*ctx
)
358 struct fimc_dev
*dev
= ctx
->fimc_dev
;
360 u32 cfg
= readl(dev
->regs
+ S5P_CIIMGCPT
);
362 if (ctx
->out_path
== FIMC_DMA
) {
364 cfg
|= S5P_CIIMGCPT_CPT_FREN_ENABLE
| S5P_CIIMGCPT_IMGCPTEN
;
366 /* Continuous frame capture mode (freerun). */
367 cfg
&= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE
|
368 S5P_CIIMGCPT_CPT_FRMOD_CNT
);
369 cfg
|= S5P_CIIMGCPT_IMGCPTEN
;
372 if (ctx
->scaler
.enabled
)
373 cfg
|= S5P_CIIMGCPT_IMGCPTEN_SC
;
375 writel(cfg
| S5P_CIIMGCPT_IMGCPTEN
, dev
->regs
+ S5P_CIIMGCPT
);
378 void fimc_hw_set_effect(struct fimc_ctx
*ctx
, bool active
)
380 struct fimc_dev
*dev
= ctx
->fimc_dev
;
381 struct fimc_effect
*effect
= &ctx
->effect
;
385 cfg
|= S5P_CIIMGEFF_IE_SC_AFTER
| S5P_CIIMGEFF_IE_ENABLE
;
387 if (effect
->type
== S5P_FIMC_EFFECT_ARBITRARY
) {
388 cfg
|= S5P_CIIMGEFF_PAT_CB(effect
->pat_cb
);
389 cfg
|= S5P_CIIMGEFF_PAT_CR(effect
->pat_cr
);
393 writel(cfg
, dev
->regs
+ S5P_CIIMGEFF
);
396 void fimc_hw_set_rgb_alpha(struct fimc_ctx
*ctx
)
398 struct fimc_dev
*dev
= ctx
->fimc_dev
;
399 struct fimc_frame
*frame
= &ctx
->d_frame
;
402 if (!(frame
->fmt
->flags
& FMT_HAS_ALPHA
))
405 cfg
= readl(dev
->regs
+ S5P_CIOCTRL
);
406 cfg
&= ~S5P_CIOCTRL_ALPHA_OUT_MASK
;
407 cfg
|= (frame
->alpha
<< 4);
408 writel(cfg
, dev
->regs
+ S5P_CIOCTRL
);
411 static void fimc_hw_set_in_dma_size(struct fimc_ctx
*ctx
)
413 struct fimc_dev
*dev
= ctx
->fimc_dev
;
414 struct fimc_frame
*frame
= &ctx
->s_frame
;
418 if (FIMC_LCDFIFO
== ctx
->out_path
)
419 cfg_r
|= S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
421 cfg_o
|= S5P_ORIG_SIZE_HOR(frame
->f_width
);
422 cfg_o
|= S5P_ORIG_SIZE_VER(frame
->f_height
);
423 cfg_r
|= S5P_CIREAL_ISIZE_WIDTH(frame
->width
);
424 cfg_r
|= S5P_CIREAL_ISIZE_HEIGHT(frame
->height
);
426 writel(cfg_o
, dev
->regs
+ S5P_ORGISIZE
);
427 writel(cfg_r
, dev
->regs
+ S5P_CIREAL_ISIZE
);
430 void fimc_hw_set_in_dma(struct fimc_ctx
*ctx
)
432 struct fimc_dev
*dev
= ctx
->fimc_dev
;
433 struct fimc_frame
*frame
= &ctx
->s_frame
;
434 struct fimc_dma_offset
*offset
= &frame
->dma_offset
;
437 /* Set the pixel offsets. */
438 cfg
= S5P_CIO_OFFS_HOR(offset
->y_h
);
439 cfg
|= S5P_CIO_OFFS_VER(offset
->y_v
);
440 writel(cfg
, dev
->regs
+ S5P_CIIYOFF
);
442 cfg
= S5P_CIO_OFFS_HOR(offset
->cb_h
);
443 cfg
|= S5P_CIO_OFFS_VER(offset
->cb_v
);
444 writel(cfg
, dev
->regs
+ S5P_CIICBOFF
);
446 cfg
= S5P_CIO_OFFS_HOR(offset
->cr_h
);
447 cfg
|= S5P_CIO_OFFS_VER(offset
->cr_v
);
448 writel(cfg
, dev
->regs
+ S5P_CIICROFF
);
450 /* Input original and real size. */
451 fimc_hw_set_in_dma_size(ctx
);
453 /* Use DMA autoload only in FIFO mode. */
454 fimc_hw_en_autoload(dev
, ctx
->out_path
== FIMC_LCDFIFO
);
456 /* Set the input DMA to process single frame only. */
457 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
458 cfg
&= ~(S5P_MSCTRL_INFORMAT_MASK
459 | S5P_MSCTRL_IN_BURST_COUNT_MASK
460 | S5P_MSCTRL_INPUT_MASK
461 | S5P_MSCTRL_C_INT_IN_MASK
462 | S5P_MSCTRL_2P_IN_ORDER_MASK
);
464 cfg
|= (S5P_MSCTRL_IN_BURST_COUNT(4)
465 | S5P_MSCTRL_INPUT_MEMORY
466 | S5P_MSCTRL_FIFO_CTRL_FULL
);
468 switch (frame
->fmt
->color
) {
469 case S5P_FIMC_RGB565
...S5P_FIMC_RGB888
:
470 cfg
|= S5P_MSCTRL_INFORMAT_RGB
;
472 case S5P_FIMC_YCBCR420
:
473 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR420
;
475 if (frame
->fmt
->colplanes
== 2)
476 cfg
|= ctx
->in_order_2p
| S5P_MSCTRL_C_INT_IN_2PLANE
;
478 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
481 case S5P_FIMC_YCBYCR422
...S5P_FIMC_CRYCBY422
:
482 if (frame
->fmt
->colplanes
== 1) {
483 cfg
|= ctx
->in_order_1p
484 | S5P_MSCTRL_INFORMAT_YCBCR422_1P
;
486 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR422
;
488 if (frame
->fmt
->colplanes
== 2)
489 cfg
|= ctx
->in_order_2p
490 | S5P_MSCTRL_C_INT_IN_2PLANE
;
492 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
499 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
501 /* Input/output DMA linear/tiled mode. */
502 cfg
= readl(dev
->regs
+ S5P_CIDMAPARAM
);
503 cfg
&= ~S5P_CIDMAPARAM_TILE_MASK
;
505 if (tiled_fmt(ctx
->s_frame
.fmt
))
506 cfg
|= S5P_CIDMAPARAM_R_64X32
;
508 if (tiled_fmt(ctx
->d_frame
.fmt
))
509 cfg
|= S5P_CIDMAPARAM_W_64X32
;
511 writel(cfg
, dev
->regs
+ S5P_CIDMAPARAM
);
515 void fimc_hw_set_input_path(struct fimc_ctx
*ctx
)
517 struct fimc_dev
*dev
= ctx
->fimc_dev
;
519 u32 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
520 cfg
&= ~S5P_MSCTRL_INPUT_MASK
;
522 if (ctx
->in_path
== FIMC_DMA
)
523 cfg
|= S5P_MSCTRL_INPUT_MEMORY
;
525 cfg
|= S5P_MSCTRL_INPUT_EXTCAM
;
527 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
530 void fimc_hw_set_output_path(struct fimc_ctx
*ctx
)
532 struct fimc_dev
*dev
= ctx
->fimc_dev
;
534 u32 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
535 cfg
&= ~S5P_CISCCTRL_LCDPATHEN_FIFO
;
536 if (ctx
->out_path
== FIMC_LCDFIFO
)
537 cfg
|= S5P_CISCCTRL_LCDPATHEN_FIFO
;
538 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
541 void fimc_hw_set_input_addr(struct fimc_dev
*dev
, struct fimc_addr
*paddr
)
543 u32 cfg
= readl(dev
->regs
+ S5P_CIREAL_ISIZE
);
544 cfg
|= S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
545 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
547 writel(paddr
->y
, dev
->regs
+ S5P_CIIYSA(0));
548 writel(paddr
->cb
, dev
->regs
+ S5P_CIICBSA(0));
549 writel(paddr
->cr
, dev
->regs
+ S5P_CIICRSA(0));
551 cfg
&= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
552 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
555 void fimc_hw_set_output_addr(struct fimc_dev
*dev
,
556 struct fimc_addr
*paddr
, int index
)
558 int i
= (index
== -1) ? 0 : index
;
560 writel(paddr
->y
, dev
->regs
+ S5P_CIOYSA(i
));
561 writel(paddr
->cb
, dev
->regs
+ S5P_CIOCBSA(i
));
562 writel(paddr
->cr
, dev
->regs
+ S5P_CIOCRSA(i
));
563 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
564 i
, paddr
->y
, paddr
->cb
, paddr
->cr
);
565 } while (index
== -1 && ++i
< FIMC_MAX_OUT_BUFS
);
568 int fimc_hw_set_camera_polarity(struct fimc_dev
*fimc
,
569 struct s5p_fimc_isp_info
*cam
)
571 u32 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
573 cfg
&= ~(S5P_CIGCTRL_INVPOLPCLK
| S5P_CIGCTRL_INVPOLVSYNC
|
574 S5P_CIGCTRL_INVPOLHREF
| S5P_CIGCTRL_INVPOLHSYNC
|
575 S5P_CIGCTRL_INVPOLFIELD
);
577 if (cam
->flags
& V4L2_MBUS_PCLK_SAMPLE_FALLING
)
578 cfg
|= S5P_CIGCTRL_INVPOLPCLK
;
580 if (cam
->flags
& V4L2_MBUS_VSYNC_ACTIVE_LOW
)
581 cfg
|= S5P_CIGCTRL_INVPOLVSYNC
;
583 if (cam
->flags
& V4L2_MBUS_HSYNC_ACTIVE_LOW
)
584 cfg
|= S5P_CIGCTRL_INVPOLHREF
;
586 if (cam
->flags
& V4L2_MBUS_HSYNC_ACTIVE_LOW
)
587 cfg
|= S5P_CIGCTRL_INVPOLHSYNC
;
589 if (cam
->flags
& V4L2_MBUS_FIELD_EVEN_LOW
)
590 cfg
|= S5P_CIGCTRL_INVPOLFIELD
;
592 writel(cfg
, fimc
->regs
+ S5P_CIGCTRL
);
597 int fimc_hw_set_camera_source(struct fimc_dev
*fimc
,
598 struct s5p_fimc_isp_info
*cam
)
600 struct fimc_frame
*f
= &fimc
->vid_cap
.ctx
->s_frame
;
605 static const struct {
610 { V4L2_MBUS_FMT_YUYV8_2X8
, S5P_CISRCFMT_ORDER422_YCBYCR
, 8 },
611 { V4L2_MBUS_FMT_YVYU8_2X8
, S5P_CISRCFMT_ORDER422_YCRYCB
, 8 },
612 { V4L2_MBUS_FMT_VYUY8_2X8
, S5P_CISRCFMT_ORDER422_CRYCBY
, 8 },
613 { V4L2_MBUS_FMT_UYVY8_2X8
, S5P_CISRCFMT_ORDER422_CBYCRY
, 8 },
614 /* TODO: Add pixel codes for 16-bit bus width */
617 if (cam
->bus_type
== FIMC_ITU_601
|| cam
->bus_type
== FIMC_ITU_656
) {
618 for (i
= 0; i
< ARRAY_SIZE(pix_desc
); i
++) {
619 if (fimc
->vid_cap
.mf
.code
== pix_desc
[i
].pixelcode
) {
620 cfg
= pix_desc
[i
].cisrcfmt
;
621 bus_width
= pix_desc
[i
].bus_width
;
626 if (i
== ARRAY_SIZE(pix_desc
)) {
627 v4l2_err(fimc
->vid_cap
.vfd
,
628 "Camera color format not supported: %d\n",
629 fimc
->vid_cap
.mf
.code
);
633 if (cam
->bus_type
== FIMC_ITU_601
) {
635 cfg
|= S5P_CISRCFMT_ITU601_8BIT
;
636 else if (bus_width
== 16)
637 cfg
|= S5P_CISRCFMT_ITU601_16BIT
;
638 } /* else defaults to ITU-R BT.656 8-bit */
639 } else if (cam
->bus_type
== FIMC_MIPI_CSI2
) {
640 if (fimc_fmt_is_jpeg(f
->fmt
->color
))
641 cfg
|= S5P_CISRCFMT_ITU601_8BIT
;
644 cfg
|= S5P_CISRCFMT_HSIZE(f
->o_width
) | S5P_CISRCFMT_VSIZE(f
->o_height
);
645 writel(cfg
, fimc
->regs
+ S5P_CISRCFMT
);
650 int fimc_hw_set_camera_offset(struct fimc_dev
*fimc
, struct fimc_frame
*f
)
654 u32 cfg
= readl(fimc
->regs
+ S5P_CIWDOFST
);
656 cfg
&= ~(S5P_CIWDOFST_HOROFF_MASK
| S5P_CIWDOFST_VEROFF_MASK
);
657 cfg
|= S5P_CIWDOFST_OFF_EN
|
658 S5P_CIWDOFST_HOROFF(f
->offs_h
) |
659 S5P_CIWDOFST_VEROFF(f
->offs_v
);
661 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST
);
663 /* See CIWDOFSTn register description in the datasheet for details. */
664 hoff2
= f
->o_width
- f
->width
- f
->offs_h
;
665 voff2
= f
->o_height
- f
->height
- f
->offs_v
;
666 cfg
= S5P_CIWDOFST2_HOROFF(hoff2
) | S5P_CIWDOFST2_VEROFF(voff2
);
668 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST2
);
672 int fimc_hw_set_camera_type(struct fimc_dev
*fimc
,
673 struct s5p_fimc_isp_info
*cam
)
676 struct fimc_vid_cap
*vid_cap
= &fimc
->vid_cap
;
678 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
680 /* Select ITU B interface, disable Writeback path and test pattern. */
681 cfg
&= ~(S5P_CIGCTRL_TESTPAT_MASK
| S5P_CIGCTRL_SELCAM_ITU_A
|
682 S5P_CIGCTRL_SELCAM_MIPI
| S5P_CIGCTRL_CAMIF_SELWB
|
683 S5P_CIGCTRL_SELCAM_MIPI_A
| S5P_CIGCTRL_CAM_JPEG
);
685 if (cam
->bus_type
== FIMC_MIPI_CSI2
) {
686 cfg
|= S5P_CIGCTRL_SELCAM_MIPI
;
688 if (cam
->mux_id
== 0)
689 cfg
|= S5P_CIGCTRL_SELCAM_MIPI_A
;
691 /* TODO: add remaining supported formats. */
692 switch (vid_cap
->mf
.code
) {
693 case V4L2_MBUS_FMT_VYUY8_2X8
:
694 tmp
= S5P_CSIIMGFMT_YCBCR422_8BIT
;
696 case V4L2_MBUS_FMT_JPEG_1X8
:
697 tmp
= S5P_CSIIMGFMT_USER(1);
698 cfg
|= S5P_CIGCTRL_CAM_JPEG
;
701 v4l2_err(fimc
->vid_cap
.vfd
,
702 "Not supported camera pixel format: %d",
706 tmp
|= (cam
->csi_data_align
== 32) << 8;
708 writel(tmp
, fimc
->regs
+ S5P_CSIIMGFMT
);
710 } else if (cam
->bus_type
== FIMC_ITU_601
||
711 cam
->bus_type
== FIMC_ITU_656
) {
712 if (cam
->mux_id
== 0) /* ITU-A, ITU-B: 0, 1 */
713 cfg
|= S5P_CIGCTRL_SELCAM_ITU_A
;
714 } else if (cam
->bus_type
== FIMC_LCD_WB
) {
715 cfg
|= S5P_CIGCTRL_CAMIF_SELWB
;
717 err("invalid camera bus type selected\n");
720 writel(cfg
, fimc
->regs
+ S5P_CIGCTRL
);