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
);
40 static u32
fimc_hw_get_in_flip(struct fimc_ctx
*ctx
)
42 u32 flip
= S5P_MSCTRL_FLIP_NORMAL
;
46 flip
= S5P_MSCTRL_FLIP_X_MIRROR
;
49 flip
= S5P_MSCTRL_FLIP_Y_MIRROR
;
52 flip
= S5P_MSCTRL_FLIP_180
;
57 if (ctx
->rotation
<= 90)
60 return (flip
^ S5P_MSCTRL_FLIP_180
) & S5P_MSCTRL_FLIP_180
;
63 static u32
fimc_hw_get_target_flip(struct fimc_ctx
*ctx
)
65 u32 flip
= S5P_CITRGFMT_FLIP_NORMAL
;
69 flip
= S5P_CITRGFMT_FLIP_X_MIRROR
;
72 flip
= S5P_CITRGFMT_FLIP_Y_MIRROR
;
75 flip
= S5P_CITRGFMT_FLIP_180
;
80 if (ctx
->rotation
<= 90)
83 return (flip
^ S5P_CITRGFMT_FLIP_180
) & S5P_CITRGFMT_FLIP_180
;
86 void fimc_hw_set_rotation(struct fimc_ctx
*ctx
)
89 struct fimc_dev
*dev
= ctx
->fimc_dev
;
91 cfg
= readl(dev
->regs
+ S5P_CITRGFMT
);
92 cfg
&= ~(S5P_CITRGFMT_INROT90
| S5P_CITRGFMT_OUTROT90
|
93 S5P_CITRGFMT_FLIP_180
);
96 * The input and output rotator cannot work simultaneously.
97 * Use the output rotator in output DMA mode or the input rotator
98 * in direct fifo output mode.
100 if (ctx
->rotation
== 90 || ctx
->rotation
== 270) {
101 if (ctx
->out_path
== FIMC_LCDFIFO
)
102 cfg
|= S5P_CITRGFMT_INROT90
;
104 cfg
|= S5P_CITRGFMT_OUTROT90
;
107 if (ctx
->out_path
== FIMC_DMA
) {
108 cfg
|= fimc_hw_get_target_flip(ctx
);
109 writel(cfg
, dev
->regs
+ S5P_CITRGFMT
);
112 flip
= readl(dev
->regs
+ S5P_MSCTRL
);
113 flip
&= ~S5P_MSCTRL_FLIP_MASK
;
114 flip
|= fimc_hw_get_in_flip(ctx
);
115 writel(flip
, dev
->regs
+ S5P_MSCTRL
);
119 void fimc_hw_set_target_format(struct fimc_ctx
*ctx
)
122 struct fimc_dev
*dev
= ctx
->fimc_dev
;
123 struct fimc_frame
*frame
= &ctx
->d_frame
;
125 dbg("w= %d, h= %d color: %d", frame
->width
,
126 frame
->height
, frame
->fmt
->color
);
128 cfg
= readl(dev
->regs
+ S5P_CITRGFMT
);
129 cfg
&= ~(S5P_CITRGFMT_FMT_MASK
| S5P_CITRGFMT_HSIZE_MASK
|
130 S5P_CITRGFMT_VSIZE_MASK
);
132 switch (frame
->fmt
->color
) {
133 case S5P_FIMC_RGB565
...S5P_FIMC_RGB888
:
134 cfg
|= S5P_CITRGFMT_RGB
;
136 case S5P_FIMC_YCBCR420
:
137 cfg
|= S5P_CITRGFMT_YCBCR420
;
139 case S5P_FIMC_YCBYCR422
...S5P_FIMC_CRYCBY422
:
140 if (frame
->fmt
->colplanes
== 1)
141 cfg
|= S5P_CITRGFMT_YCBCR422_1P
;
143 cfg
|= S5P_CITRGFMT_YCBCR422
;
149 if (ctx
->rotation
== 90 || ctx
->rotation
== 270) {
150 cfg
|= S5P_CITRGFMT_HSIZE(frame
->height
);
151 cfg
|= S5P_CITRGFMT_VSIZE(frame
->width
);
154 cfg
|= S5P_CITRGFMT_HSIZE(frame
->width
);
155 cfg
|= S5P_CITRGFMT_VSIZE(frame
->height
);
158 writel(cfg
, dev
->regs
+ S5P_CITRGFMT
);
160 cfg
= readl(dev
->regs
+ S5P_CITAREA
) & ~S5P_CITAREA_MASK
;
161 cfg
|= (frame
->width
* frame
->height
);
162 writel(cfg
, dev
->regs
+ S5P_CITAREA
);
165 static void fimc_hw_set_out_dma_size(struct fimc_ctx
*ctx
)
167 struct fimc_dev
*dev
= ctx
->fimc_dev
;
168 struct fimc_frame
*frame
= &ctx
->d_frame
;
171 cfg
= S5P_ORIG_SIZE_HOR(frame
->f_width
);
172 cfg
|= S5P_ORIG_SIZE_VER(frame
->f_height
);
173 writel(cfg
, dev
->regs
+ S5P_ORGOSIZE
);
175 /* Select color space conversion equation (HD/SD size).*/
176 cfg
= readl(dev
->regs
+ S5P_CIGCTRL
);
177 if (frame
->f_width
>= 1280) /* HD */
178 cfg
|= S5P_CIGCTRL_CSC_ITU601_709
;
180 cfg
&= ~S5P_CIGCTRL_CSC_ITU601_709
;
181 writel(cfg
, dev
->regs
+ S5P_CIGCTRL
);
185 void fimc_hw_set_out_dma(struct fimc_ctx
*ctx
)
188 struct fimc_dev
*dev
= ctx
->fimc_dev
;
189 struct fimc_frame
*frame
= &ctx
->d_frame
;
190 struct fimc_dma_offset
*offset
= &frame
->dma_offset
;
192 /* Set the input dma offsets. */
194 cfg
|= S5P_CIO_OFFS_HOR(offset
->y_h
);
195 cfg
|= S5P_CIO_OFFS_VER(offset
->y_v
);
196 writel(cfg
, dev
->regs
+ S5P_CIOYOFF
);
199 cfg
|= S5P_CIO_OFFS_HOR(offset
->cb_h
);
200 cfg
|= S5P_CIO_OFFS_VER(offset
->cb_v
);
201 writel(cfg
, dev
->regs
+ S5P_CIOCBOFF
);
204 cfg
|= S5P_CIO_OFFS_HOR(offset
->cr_h
);
205 cfg
|= S5P_CIO_OFFS_VER(offset
->cr_v
);
206 writel(cfg
, dev
->regs
+ S5P_CIOCROFF
);
208 fimc_hw_set_out_dma_size(ctx
);
210 /* Configure chroma components order. */
211 cfg
= readl(dev
->regs
+ S5P_CIOCTRL
);
213 cfg
&= ~(S5P_CIOCTRL_ORDER2P_MASK
| S5P_CIOCTRL_ORDER422_MASK
|
214 S5P_CIOCTRL_YCBCR_PLANE_MASK
);
216 if (frame
->fmt
->colplanes
== 1)
217 cfg
|= ctx
->out_order_1p
;
218 else if (frame
->fmt
->colplanes
== 2)
219 cfg
|= ctx
->out_order_2p
| S5P_CIOCTRL_YCBCR_2PLANE
;
220 else if (frame
->fmt
->colplanes
== 3)
221 cfg
|= S5P_CIOCTRL_YCBCR_3PLANE
;
223 writel(cfg
, dev
->regs
+ S5P_CIOCTRL
);
226 static void fimc_hw_en_autoload(struct fimc_dev
*dev
, int enable
)
228 u32 cfg
= readl(dev
->regs
+ S5P_ORGISIZE
);
230 cfg
|= S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
232 cfg
&= ~S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
233 writel(cfg
, dev
->regs
+ S5P_ORGISIZE
);
236 void fimc_hw_en_lastirq(struct fimc_dev
*dev
, int enable
)
238 u32 cfg
= readl(dev
->regs
+ S5P_CIOCTRL
);
240 cfg
|= S5P_CIOCTRL_LASTIRQ_ENABLE
;
242 cfg
&= ~S5P_CIOCTRL_LASTIRQ_ENABLE
;
243 writel(cfg
, dev
->regs
+ S5P_CIOCTRL
);
246 void fimc_hw_set_prescaler(struct fimc_ctx
*ctx
)
248 struct fimc_dev
*dev
= ctx
->fimc_dev
;
249 struct fimc_scaler
*sc
= &ctx
->scaler
;
252 shfactor
= 10 - (sc
->hfactor
+ sc
->vfactor
);
254 cfg
= S5P_CISCPRERATIO_SHFACTOR(shfactor
);
255 cfg
|= S5P_CISCPRERATIO_HOR(sc
->pre_hratio
);
256 cfg
|= S5P_CISCPRERATIO_VER(sc
->pre_vratio
);
257 writel(cfg
, dev
->regs
+ S5P_CISCPRERATIO
);
259 cfg
= S5P_CISCPREDST_WIDTH(sc
->pre_dst_width
);
260 cfg
|= S5P_CISCPREDST_HEIGHT(sc
->pre_dst_height
);
261 writel(cfg
, dev
->regs
+ S5P_CISCPREDST
);
264 static void fimc_hw_set_scaler(struct fimc_ctx
*ctx
)
266 struct fimc_dev
*dev
= ctx
->fimc_dev
;
267 struct fimc_scaler
*sc
= &ctx
->scaler
;
268 struct fimc_frame
*src_frame
= &ctx
->s_frame
;
269 struct fimc_frame
*dst_frame
= &ctx
->d_frame
;
272 if (!(ctx
->flags
& FIMC_COLOR_RANGE_NARROW
))
273 cfg
|= (S5P_CISCCTRL_CSCR2Y_WIDE
| S5P_CISCCTRL_CSCY2R_WIDE
);
276 cfg
|= S5P_CISCCTRL_SCALERBYPASS
;
279 cfg
|= S5P_CISCCTRL_SCALEUP_H
;
282 cfg
|= S5P_CISCCTRL_SCALEUP_V
;
285 cfg
|= S5P_CISCCTRL_ONE2ONE
;
288 if (ctx
->in_path
== FIMC_DMA
) {
289 if (src_frame
->fmt
->color
== S5P_FIMC_RGB565
)
290 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB565
;
291 else if (src_frame
->fmt
->color
== S5P_FIMC_RGB666
)
292 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB666
;
293 else if (src_frame
->fmt
->color
== S5P_FIMC_RGB888
)
294 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB888
;
297 if (ctx
->out_path
== FIMC_DMA
) {
298 if (dst_frame
->fmt
->color
== S5P_FIMC_RGB565
)
299 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB565
;
300 else if (dst_frame
->fmt
->color
== S5P_FIMC_RGB666
)
301 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB666
;
302 else if (dst_frame
->fmt
->color
== S5P_FIMC_RGB888
)
303 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB888
;
305 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB888
;
307 if (ctx
->flags
& FIMC_SCAN_MODE_INTERLACED
)
308 cfg
|= S5P_CISCCTRL_INTERLACE
;
311 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
314 void fimc_hw_set_mainscaler(struct fimc_ctx
*ctx
)
316 struct fimc_dev
*dev
= ctx
->fimc_dev
;
317 struct fimc_scaler
*sc
= &ctx
->scaler
;
320 dbg("main_hratio= 0x%X main_vratio= 0x%X",
321 sc
->main_hratio
, sc
->main_vratio
);
323 fimc_hw_set_scaler(ctx
);
325 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
326 cfg
&= ~S5P_CISCCTRL_MHRATIO_MASK
;
327 cfg
&= ~S5P_CISCCTRL_MVRATIO_MASK
;
328 cfg
|= S5P_CISCCTRL_MHRATIO(sc
->main_hratio
);
329 cfg
|= S5P_CISCCTRL_MVRATIO(sc
->main_vratio
);
331 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
334 void fimc_hw_set_mainscaler_ext(struct fimc_ctx
*ctx
)
336 struct fimc_dev
*dev
= ctx
->fimc_dev
;
337 struct fimc_scaler
*sc
= &ctx
->scaler
;
340 dbg("main_hratio= 0x%X main_vratio= 0x%X",
341 sc
->main_hratio
, sc
->main_vratio
);
343 fimc_hw_set_scaler(ctx
);
345 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
346 cfg
&= ~S5P_CISCCTRL_MHRATIO_MASK
;
347 cfg
&= ~S5P_CISCCTRL_MVRATIO_MASK
;
348 cfg
|= S5P_CISCCTRL_MHRATIO_EXT(sc
->main_hratio
);
349 cfg
|= S5P_CISCCTRL_MVRATIO_EXT(sc
->main_vratio
);
351 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
353 cfg_ext
= readl(dev
->regs
+ S5P_CIEXTEN
);
354 cfg_ext
&= ~S5P_CIEXTEN_MHRATIO_EXT_MASK
;
355 cfg_ext
&= ~S5P_CIEXTEN_MVRATIO_EXT_MASK
;
356 cfg_ext
|= S5P_CIEXTEN_MHRATIO_EXT(sc
->main_hratio
);
357 cfg_ext
|= S5P_CIEXTEN_MVRATIO_EXT(sc
->main_vratio
);
359 writel(cfg_ext
, dev
->regs
+ S5P_CIEXTEN
);
362 void fimc_hw_en_capture(struct fimc_ctx
*ctx
)
364 struct fimc_dev
*dev
= ctx
->fimc_dev
;
366 u32 cfg
= readl(dev
->regs
+ S5P_CIIMGCPT
);
368 if (ctx
->out_path
== FIMC_DMA
) {
370 cfg
|= S5P_CIIMGCPT_CPT_FREN_ENABLE
| S5P_CIIMGCPT_IMGCPTEN
;
372 /* Continous frame capture mode (freerun). */
373 cfg
&= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE
|
374 S5P_CIIMGCPT_CPT_FRMOD_CNT
);
375 cfg
|= S5P_CIIMGCPT_IMGCPTEN
;
378 if (ctx
->scaler
.enabled
)
379 cfg
|= S5P_CIIMGCPT_IMGCPTEN_SC
;
381 writel(cfg
| S5P_CIIMGCPT_IMGCPTEN
, dev
->regs
+ S5P_CIIMGCPT
);
384 void fimc_hw_set_effect(struct fimc_ctx
*ctx
)
386 struct fimc_dev
*dev
= ctx
->fimc_dev
;
387 struct fimc_effect
*effect
= &ctx
->effect
;
388 u32 cfg
= (S5P_CIIMGEFF_IE_ENABLE
| S5P_CIIMGEFF_IE_SC_AFTER
);
392 if (effect
->type
== S5P_FIMC_EFFECT_ARBITRARY
) {
393 cfg
|= S5P_CIIMGEFF_PAT_CB(effect
->pat_cb
);
394 cfg
|= S5P_CIIMGEFF_PAT_CR(effect
->pat_cr
);
397 writel(cfg
, dev
->regs
+ S5P_CIIMGEFF
);
400 static void fimc_hw_set_in_dma_size(struct fimc_ctx
*ctx
)
402 struct fimc_dev
*dev
= ctx
->fimc_dev
;
403 struct fimc_frame
*frame
= &ctx
->s_frame
;
407 if (FIMC_LCDFIFO
== ctx
->out_path
)
408 cfg_r
|= S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
410 cfg_o
|= S5P_ORIG_SIZE_HOR(frame
->f_width
);
411 cfg_o
|= S5P_ORIG_SIZE_VER(frame
->f_height
);
412 cfg_r
|= S5P_CIREAL_ISIZE_WIDTH(frame
->width
);
413 cfg_r
|= S5P_CIREAL_ISIZE_HEIGHT(frame
->height
);
415 writel(cfg_o
, dev
->regs
+ S5P_ORGISIZE
);
416 writel(cfg_r
, dev
->regs
+ S5P_CIREAL_ISIZE
);
419 void fimc_hw_set_in_dma(struct fimc_ctx
*ctx
)
421 struct fimc_dev
*dev
= ctx
->fimc_dev
;
422 struct fimc_frame
*frame
= &ctx
->s_frame
;
423 struct fimc_dma_offset
*offset
= &frame
->dma_offset
;
426 /* Set the pixel offsets. */
427 cfg
= S5P_CIO_OFFS_HOR(offset
->y_h
);
428 cfg
|= S5P_CIO_OFFS_VER(offset
->y_v
);
429 writel(cfg
, dev
->regs
+ S5P_CIIYOFF
);
431 cfg
= S5P_CIO_OFFS_HOR(offset
->cb_h
);
432 cfg
|= S5P_CIO_OFFS_VER(offset
->cb_v
);
433 writel(cfg
, dev
->regs
+ S5P_CIICBOFF
);
435 cfg
= S5P_CIO_OFFS_HOR(offset
->cr_h
);
436 cfg
|= S5P_CIO_OFFS_VER(offset
->cr_v
);
437 writel(cfg
, dev
->regs
+ S5P_CIICROFF
);
439 /* Input original and real size. */
440 fimc_hw_set_in_dma_size(ctx
);
442 /* Use DMA autoload only in FIFO mode. */
443 fimc_hw_en_autoload(dev
, ctx
->out_path
== FIMC_LCDFIFO
);
445 /* Set the input DMA to process single frame only. */
446 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
447 cfg
&= ~(S5P_MSCTRL_INFORMAT_MASK
448 | S5P_MSCTRL_IN_BURST_COUNT_MASK
449 | S5P_MSCTRL_INPUT_MASK
450 | S5P_MSCTRL_C_INT_IN_MASK
451 | S5P_MSCTRL_2P_IN_ORDER_MASK
);
453 cfg
|= S5P_MSCTRL_IN_BURST_COUNT(4) | S5P_MSCTRL_INPUT_MEMORY
;
455 switch (frame
->fmt
->color
) {
456 case S5P_FIMC_RGB565
...S5P_FIMC_RGB888
:
457 cfg
|= S5P_MSCTRL_INFORMAT_RGB
;
459 case S5P_FIMC_YCBCR420
:
460 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR420
;
462 if (frame
->fmt
->colplanes
== 2)
463 cfg
|= ctx
->in_order_2p
| S5P_MSCTRL_C_INT_IN_2PLANE
;
465 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
468 case S5P_FIMC_YCBYCR422
...S5P_FIMC_CRYCBY422
:
469 if (frame
->fmt
->colplanes
== 1) {
470 cfg
|= ctx
->in_order_1p
471 | S5P_MSCTRL_INFORMAT_YCBCR422_1P
;
473 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR422
;
475 if (frame
->fmt
->colplanes
== 2)
476 cfg
|= ctx
->in_order_2p
477 | S5P_MSCTRL_C_INT_IN_2PLANE
;
479 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
486 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
488 /* Input/output DMA linear/tiled mode. */
489 cfg
= readl(dev
->regs
+ S5P_CIDMAPARAM
);
490 cfg
&= ~S5P_CIDMAPARAM_TILE_MASK
;
492 if (tiled_fmt(ctx
->s_frame
.fmt
))
493 cfg
|= S5P_CIDMAPARAM_R_64X32
;
495 if (tiled_fmt(ctx
->d_frame
.fmt
))
496 cfg
|= S5P_CIDMAPARAM_W_64X32
;
498 writel(cfg
, dev
->regs
+ S5P_CIDMAPARAM
);
502 void fimc_hw_set_input_path(struct fimc_ctx
*ctx
)
504 struct fimc_dev
*dev
= ctx
->fimc_dev
;
506 u32 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
507 cfg
&= ~S5P_MSCTRL_INPUT_MASK
;
509 if (ctx
->in_path
== FIMC_DMA
)
510 cfg
|= S5P_MSCTRL_INPUT_MEMORY
;
512 cfg
|= S5P_MSCTRL_INPUT_EXTCAM
;
514 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
517 void fimc_hw_set_output_path(struct fimc_ctx
*ctx
)
519 struct fimc_dev
*dev
= ctx
->fimc_dev
;
521 u32 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
522 cfg
&= ~S5P_CISCCTRL_LCDPATHEN_FIFO
;
523 if (ctx
->out_path
== FIMC_LCDFIFO
)
524 cfg
|= S5P_CISCCTRL_LCDPATHEN_FIFO
;
525 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
528 void fimc_hw_set_input_addr(struct fimc_dev
*dev
, struct fimc_addr
*paddr
)
530 u32 cfg
= readl(dev
->regs
+ S5P_CIREAL_ISIZE
);
531 cfg
|= S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
532 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
534 writel(paddr
->y
, dev
->regs
+ S5P_CIIYSA(0));
535 writel(paddr
->cb
, dev
->regs
+ S5P_CIICBSA(0));
536 writel(paddr
->cr
, dev
->regs
+ S5P_CIICRSA(0));
538 cfg
&= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
539 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
542 void fimc_hw_set_output_addr(struct fimc_dev
*dev
,
543 struct fimc_addr
*paddr
, int index
)
545 int i
= (index
== -1) ? 0 : index
;
547 writel(paddr
->y
, dev
->regs
+ S5P_CIOYSA(i
));
548 writel(paddr
->cb
, dev
->regs
+ S5P_CIOCBSA(i
));
549 writel(paddr
->cr
, dev
->regs
+ S5P_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
);
555 int fimc_hw_set_camera_polarity(struct fimc_dev
*fimc
,
556 struct s5p_fimc_isp_info
*cam
)
558 u32 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
560 cfg
&= ~(S5P_CIGCTRL_INVPOLPCLK
| S5P_CIGCTRL_INVPOLVSYNC
|
561 S5P_CIGCTRL_INVPOLHREF
| S5P_CIGCTRL_INVPOLHSYNC
);
563 if (cam
->flags
& FIMC_CLK_INV_PCLK
)
564 cfg
|= S5P_CIGCTRL_INVPOLPCLK
;
566 if (cam
->flags
& FIMC_CLK_INV_VSYNC
)
567 cfg
|= S5P_CIGCTRL_INVPOLVSYNC
;
569 if (cam
->flags
& FIMC_CLK_INV_HREF
)
570 cfg
|= S5P_CIGCTRL_INVPOLHREF
;
572 if (cam
->flags
& FIMC_CLK_INV_HSYNC
)
573 cfg
|= S5P_CIGCTRL_INVPOLHSYNC
;
575 writel(cfg
, fimc
->regs
+ S5P_CIGCTRL
);
580 int fimc_hw_set_camera_source(struct fimc_dev
*fimc
,
581 struct s5p_fimc_isp_info
*cam
)
583 struct fimc_frame
*f
= &fimc
->vid_cap
.ctx
->s_frame
;
588 static const struct {
593 { V4L2_MBUS_FMT_YUYV8_2X8
, S5P_CISRCFMT_ORDER422_YCBYCR
, 8 },
594 { V4L2_MBUS_FMT_YVYU8_2X8
, S5P_CISRCFMT_ORDER422_YCRYCB
, 8 },
595 { V4L2_MBUS_FMT_VYUY8_2X8
, S5P_CISRCFMT_ORDER422_CRYCBY
, 8 },
596 { V4L2_MBUS_FMT_UYVY8_2X8
, S5P_CISRCFMT_ORDER422_CBYCRY
, 8 },
597 /* TODO: Add pixel codes for 16-bit bus width */
600 if (cam
->bus_type
== FIMC_ITU_601
|| cam
->bus_type
== FIMC_ITU_656
) {
601 for (i
= 0; i
< ARRAY_SIZE(pix_desc
); i
++) {
602 if (fimc
->vid_cap
.fmt
.code
== pix_desc
[i
].pixelcode
) {
603 cfg
= pix_desc
[i
].cisrcfmt
;
604 bus_width
= pix_desc
[i
].bus_width
;
609 if (i
== ARRAY_SIZE(pix_desc
)) {
610 v4l2_err(&fimc
->vid_cap
.v4l2_dev
,
611 "Camera color format not supported: %d\n",
612 fimc
->vid_cap
.fmt
.code
);
616 if (cam
->bus_type
== FIMC_ITU_601
) {
618 cfg
|= S5P_CISRCFMT_ITU601_8BIT
;
619 else if (bus_width
== 16)
620 cfg
|= S5P_CISRCFMT_ITU601_16BIT
;
621 } /* else defaults to ITU-R BT.656 8-bit */
624 cfg
|= S5P_CISRCFMT_HSIZE(f
->o_width
) | S5P_CISRCFMT_VSIZE(f
->o_height
);
625 writel(cfg
, fimc
->regs
+ S5P_CISRCFMT
);
630 int fimc_hw_set_camera_offset(struct fimc_dev
*fimc
, struct fimc_frame
*f
)
634 u32 cfg
= readl(fimc
->regs
+ S5P_CIWDOFST
);
636 cfg
&= ~(S5P_CIWDOFST_HOROFF_MASK
| S5P_CIWDOFST_VEROFF_MASK
);
637 cfg
|= S5P_CIWDOFST_OFF_EN
|
638 S5P_CIWDOFST_HOROFF(f
->offs_h
) |
639 S5P_CIWDOFST_VEROFF(f
->offs_v
);
641 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST
);
643 /* See CIWDOFSTn register description in the datasheet for details. */
644 hoff2
= f
->o_width
- f
->width
- f
->offs_h
;
645 voff2
= f
->o_height
- f
->height
- f
->offs_v
;
646 cfg
= S5P_CIWDOFST2_HOROFF(hoff2
) | S5P_CIWDOFST2_VEROFF(voff2
);
648 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST2
);
652 int fimc_hw_set_camera_type(struct fimc_dev
*fimc
,
653 struct s5p_fimc_isp_info
*cam
)
656 struct fimc_vid_cap
*vid_cap
= &fimc
->vid_cap
;
658 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
660 /* Select ITU B interface, disable Writeback path and test pattern. */
661 cfg
&= ~(S5P_CIGCTRL_TESTPAT_MASK
| S5P_CIGCTRL_SELCAM_ITU_A
|
662 S5P_CIGCTRL_SELCAM_MIPI
| S5P_CIGCTRL_CAMIF_SELWB
|
663 S5P_CIGCTRL_SELCAM_MIPI_A
);
665 if (cam
->bus_type
== FIMC_MIPI_CSI2
) {
666 cfg
|= S5P_CIGCTRL_SELCAM_MIPI
;
668 if (cam
->mux_id
== 0)
669 cfg
|= S5P_CIGCTRL_SELCAM_MIPI_A
;
671 /* TODO: add remaining supported formats. */
672 if (vid_cap
->fmt
.code
== V4L2_MBUS_FMT_VYUY8_2X8
) {
673 tmp
= S5P_CSIIMGFMT_YCBCR422_8BIT
;
675 err("camera image format not supported: %d",
679 writel(tmp
| (0x1 << 8), fimc
->regs
+ S5P_CSIIMGFMT
);
681 } else if (cam
->bus_type
== FIMC_ITU_601
||
682 cam
->bus_type
== FIMC_ITU_656
) {
683 if (cam
->mux_id
== 0) /* ITU-A, ITU-B: 0, 1 */
684 cfg
|= S5P_CIGCTRL_SELCAM_ITU_A
;
685 } else if (cam
->bus_type
== FIMC_LCD_WB
) {
686 cfg
|= S5P_CIGCTRL_CAMIF_SELWB
;
688 err("invalid camera bus type selected\n");
691 writel(cfg
, fimc
->regs
+ S5P_CIGCTRL
);