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 samsung_fimc_variant
*variant
= dev
->variant
;
318 struct fimc_scaler
*sc
= &ctx
->scaler
;
321 dbg("main_hratio= 0x%X main_vratio= 0x%X",
322 sc
->main_hratio
, sc
->main_vratio
);
324 fimc_hw_set_scaler(ctx
);
326 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
328 if (variant
->has_mainscaler_ext
) {
329 cfg
&= ~(S5P_CISCCTRL_MHRATIO_MASK
| S5P_CISCCTRL_MVRATIO_MASK
);
330 cfg
|= S5P_CISCCTRL_MHRATIO_EXT(sc
->main_hratio
);
331 cfg
|= S5P_CISCCTRL_MVRATIO_EXT(sc
->main_vratio
);
332 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
334 cfg
= readl(dev
->regs
+ S5P_CIEXTEN
);
336 cfg
&= ~(S5P_CIEXTEN_MVRATIO_EXT_MASK
|
337 S5P_CIEXTEN_MHRATIO_EXT_MASK
);
338 cfg
|= S5P_CIEXTEN_MHRATIO_EXT(sc
->main_hratio
);
339 cfg
|= S5P_CIEXTEN_MVRATIO_EXT(sc
->main_vratio
);
340 writel(cfg
, dev
->regs
+ S5P_CIEXTEN
);
342 cfg
&= ~(S5P_CISCCTRL_MHRATIO_MASK
| S5P_CISCCTRL_MVRATIO_MASK
);
343 cfg
|= S5P_CISCCTRL_MHRATIO(sc
->main_hratio
);
344 cfg
|= S5P_CISCCTRL_MVRATIO(sc
->main_vratio
);
345 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
349 void fimc_hw_en_capture(struct fimc_ctx
*ctx
)
351 struct fimc_dev
*dev
= ctx
->fimc_dev
;
353 u32 cfg
= readl(dev
->regs
+ S5P_CIIMGCPT
);
355 if (ctx
->out_path
== FIMC_DMA
) {
357 cfg
|= S5P_CIIMGCPT_CPT_FREN_ENABLE
| S5P_CIIMGCPT_IMGCPTEN
;
359 /* Continuous frame capture mode (freerun). */
360 cfg
&= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE
|
361 S5P_CIIMGCPT_CPT_FRMOD_CNT
);
362 cfg
|= S5P_CIIMGCPT_IMGCPTEN
;
365 if (ctx
->scaler
.enabled
)
366 cfg
|= S5P_CIIMGCPT_IMGCPTEN_SC
;
368 writel(cfg
| S5P_CIIMGCPT_IMGCPTEN
, dev
->regs
+ S5P_CIIMGCPT
);
371 void fimc_hw_set_effect(struct fimc_ctx
*ctx
)
373 struct fimc_dev
*dev
= ctx
->fimc_dev
;
374 struct fimc_effect
*effect
= &ctx
->effect
;
375 u32 cfg
= (S5P_CIIMGEFF_IE_ENABLE
| S5P_CIIMGEFF_IE_SC_AFTER
);
379 if (effect
->type
== S5P_FIMC_EFFECT_ARBITRARY
) {
380 cfg
|= S5P_CIIMGEFF_PAT_CB(effect
->pat_cb
);
381 cfg
|= S5P_CIIMGEFF_PAT_CR(effect
->pat_cr
);
384 writel(cfg
, dev
->regs
+ S5P_CIIMGEFF
);
387 static void fimc_hw_set_in_dma_size(struct fimc_ctx
*ctx
)
389 struct fimc_dev
*dev
= ctx
->fimc_dev
;
390 struct fimc_frame
*frame
= &ctx
->s_frame
;
394 if (FIMC_LCDFIFO
== ctx
->out_path
)
395 cfg_r
|= S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
397 cfg_o
|= S5P_ORIG_SIZE_HOR(frame
->f_width
);
398 cfg_o
|= S5P_ORIG_SIZE_VER(frame
->f_height
);
399 cfg_r
|= S5P_CIREAL_ISIZE_WIDTH(frame
->width
);
400 cfg_r
|= S5P_CIREAL_ISIZE_HEIGHT(frame
->height
);
402 writel(cfg_o
, dev
->regs
+ S5P_ORGISIZE
);
403 writel(cfg_r
, dev
->regs
+ S5P_CIREAL_ISIZE
);
406 void fimc_hw_set_in_dma(struct fimc_ctx
*ctx
)
408 struct fimc_dev
*dev
= ctx
->fimc_dev
;
409 struct fimc_frame
*frame
= &ctx
->s_frame
;
410 struct fimc_dma_offset
*offset
= &frame
->dma_offset
;
413 /* Set the pixel offsets. */
414 cfg
= S5P_CIO_OFFS_HOR(offset
->y_h
);
415 cfg
|= S5P_CIO_OFFS_VER(offset
->y_v
);
416 writel(cfg
, dev
->regs
+ S5P_CIIYOFF
);
418 cfg
= S5P_CIO_OFFS_HOR(offset
->cb_h
);
419 cfg
|= S5P_CIO_OFFS_VER(offset
->cb_v
);
420 writel(cfg
, dev
->regs
+ S5P_CIICBOFF
);
422 cfg
= S5P_CIO_OFFS_HOR(offset
->cr_h
);
423 cfg
|= S5P_CIO_OFFS_VER(offset
->cr_v
);
424 writel(cfg
, dev
->regs
+ S5P_CIICROFF
);
426 /* Input original and real size. */
427 fimc_hw_set_in_dma_size(ctx
);
429 /* Use DMA autoload only in FIFO mode. */
430 fimc_hw_en_autoload(dev
, ctx
->out_path
== FIMC_LCDFIFO
);
432 /* Set the input DMA to process single frame only. */
433 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
434 cfg
&= ~(S5P_MSCTRL_INFORMAT_MASK
435 | S5P_MSCTRL_IN_BURST_COUNT_MASK
436 | S5P_MSCTRL_INPUT_MASK
437 | S5P_MSCTRL_C_INT_IN_MASK
438 | S5P_MSCTRL_2P_IN_ORDER_MASK
);
440 cfg
|= (S5P_MSCTRL_IN_BURST_COUNT(4)
441 | S5P_MSCTRL_INPUT_MEMORY
442 | S5P_MSCTRL_FIFO_CTRL_FULL
);
444 switch (frame
->fmt
->color
) {
445 case S5P_FIMC_RGB565
...S5P_FIMC_RGB888
:
446 cfg
|= S5P_MSCTRL_INFORMAT_RGB
;
448 case S5P_FIMC_YCBCR420
:
449 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR420
;
451 if (frame
->fmt
->colplanes
== 2)
452 cfg
|= ctx
->in_order_2p
| S5P_MSCTRL_C_INT_IN_2PLANE
;
454 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
457 case S5P_FIMC_YCBYCR422
...S5P_FIMC_CRYCBY422
:
458 if (frame
->fmt
->colplanes
== 1) {
459 cfg
|= ctx
->in_order_1p
460 | S5P_MSCTRL_INFORMAT_YCBCR422_1P
;
462 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR422
;
464 if (frame
->fmt
->colplanes
== 2)
465 cfg
|= ctx
->in_order_2p
466 | S5P_MSCTRL_C_INT_IN_2PLANE
;
468 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
475 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
477 /* Input/output DMA linear/tiled mode. */
478 cfg
= readl(dev
->regs
+ S5P_CIDMAPARAM
);
479 cfg
&= ~S5P_CIDMAPARAM_TILE_MASK
;
481 if (tiled_fmt(ctx
->s_frame
.fmt
))
482 cfg
|= S5P_CIDMAPARAM_R_64X32
;
484 if (tiled_fmt(ctx
->d_frame
.fmt
))
485 cfg
|= S5P_CIDMAPARAM_W_64X32
;
487 writel(cfg
, dev
->regs
+ S5P_CIDMAPARAM
);
491 void fimc_hw_set_input_path(struct fimc_ctx
*ctx
)
493 struct fimc_dev
*dev
= ctx
->fimc_dev
;
495 u32 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
496 cfg
&= ~S5P_MSCTRL_INPUT_MASK
;
498 if (ctx
->in_path
== FIMC_DMA
)
499 cfg
|= S5P_MSCTRL_INPUT_MEMORY
;
501 cfg
|= S5P_MSCTRL_INPUT_EXTCAM
;
503 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
506 void fimc_hw_set_output_path(struct fimc_ctx
*ctx
)
508 struct fimc_dev
*dev
= ctx
->fimc_dev
;
510 u32 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
511 cfg
&= ~S5P_CISCCTRL_LCDPATHEN_FIFO
;
512 if (ctx
->out_path
== FIMC_LCDFIFO
)
513 cfg
|= S5P_CISCCTRL_LCDPATHEN_FIFO
;
514 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
517 void fimc_hw_set_input_addr(struct fimc_dev
*dev
, struct fimc_addr
*paddr
)
519 u32 cfg
= readl(dev
->regs
+ S5P_CIREAL_ISIZE
);
520 cfg
|= S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
521 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
523 writel(paddr
->y
, dev
->regs
+ S5P_CIIYSA(0));
524 writel(paddr
->cb
, dev
->regs
+ S5P_CIICBSA(0));
525 writel(paddr
->cr
, dev
->regs
+ S5P_CIICRSA(0));
527 cfg
&= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
528 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
531 void fimc_hw_set_output_addr(struct fimc_dev
*dev
,
532 struct fimc_addr
*paddr
, int index
)
534 int i
= (index
== -1) ? 0 : index
;
536 writel(paddr
->y
, dev
->regs
+ S5P_CIOYSA(i
));
537 writel(paddr
->cb
, dev
->regs
+ S5P_CIOCBSA(i
));
538 writel(paddr
->cr
, dev
->regs
+ S5P_CIOCRSA(i
));
539 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
540 i
, paddr
->y
, paddr
->cb
, paddr
->cr
);
541 } while (index
== -1 && ++i
< FIMC_MAX_OUT_BUFS
);
544 int fimc_hw_set_camera_polarity(struct fimc_dev
*fimc
,
545 struct s5p_fimc_isp_info
*cam
)
547 u32 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
549 cfg
&= ~(S5P_CIGCTRL_INVPOLPCLK
| S5P_CIGCTRL_INVPOLVSYNC
|
550 S5P_CIGCTRL_INVPOLHREF
| S5P_CIGCTRL_INVPOLHSYNC
);
552 if (cam
->flags
& FIMC_CLK_INV_PCLK
)
553 cfg
|= S5P_CIGCTRL_INVPOLPCLK
;
555 if (cam
->flags
& FIMC_CLK_INV_VSYNC
)
556 cfg
|= S5P_CIGCTRL_INVPOLVSYNC
;
558 if (cam
->flags
& FIMC_CLK_INV_HREF
)
559 cfg
|= S5P_CIGCTRL_INVPOLHREF
;
561 if (cam
->flags
& FIMC_CLK_INV_HSYNC
)
562 cfg
|= S5P_CIGCTRL_INVPOLHSYNC
;
564 writel(cfg
, fimc
->regs
+ S5P_CIGCTRL
);
569 int fimc_hw_set_camera_source(struct fimc_dev
*fimc
,
570 struct s5p_fimc_isp_info
*cam
)
572 struct fimc_frame
*f
= &fimc
->vid_cap
.ctx
->s_frame
;
577 static const struct {
582 { V4L2_MBUS_FMT_YUYV8_2X8
, S5P_CISRCFMT_ORDER422_YCBYCR
, 8 },
583 { V4L2_MBUS_FMT_YVYU8_2X8
, S5P_CISRCFMT_ORDER422_YCRYCB
, 8 },
584 { V4L2_MBUS_FMT_VYUY8_2X8
, S5P_CISRCFMT_ORDER422_CRYCBY
, 8 },
585 { V4L2_MBUS_FMT_UYVY8_2X8
, S5P_CISRCFMT_ORDER422_CBYCRY
, 8 },
586 /* TODO: Add pixel codes for 16-bit bus width */
589 if (cam
->bus_type
== FIMC_ITU_601
|| cam
->bus_type
== FIMC_ITU_656
) {
590 for (i
= 0; i
< ARRAY_SIZE(pix_desc
); i
++) {
591 if (fimc
->vid_cap
.fmt
.code
== pix_desc
[i
].pixelcode
) {
592 cfg
= pix_desc
[i
].cisrcfmt
;
593 bus_width
= pix_desc
[i
].bus_width
;
598 if (i
== ARRAY_SIZE(pix_desc
)) {
599 v4l2_err(&fimc
->vid_cap
.v4l2_dev
,
600 "Camera color format not supported: %d\n",
601 fimc
->vid_cap
.fmt
.code
);
605 if (cam
->bus_type
== FIMC_ITU_601
) {
607 cfg
|= S5P_CISRCFMT_ITU601_8BIT
;
608 else if (bus_width
== 16)
609 cfg
|= S5P_CISRCFMT_ITU601_16BIT
;
610 } /* else defaults to ITU-R BT.656 8-bit */
613 cfg
|= S5P_CISRCFMT_HSIZE(f
->o_width
) | S5P_CISRCFMT_VSIZE(f
->o_height
);
614 writel(cfg
, fimc
->regs
+ S5P_CISRCFMT
);
619 int fimc_hw_set_camera_offset(struct fimc_dev
*fimc
, struct fimc_frame
*f
)
623 u32 cfg
= readl(fimc
->regs
+ S5P_CIWDOFST
);
625 cfg
&= ~(S5P_CIWDOFST_HOROFF_MASK
| S5P_CIWDOFST_VEROFF_MASK
);
626 cfg
|= S5P_CIWDOFST_OFF_EN
|
627 S5P_CIWDOFST_HOROFF(f
->offs_h
) |
628 S5P_CIWDOFST_VEROFF(f
->offs_v
);
630 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST
);
632 /* See CIWDOFSTn register description in the datasheet for details. */
633 hoff2
= f
->o_width
- f
->width
- f
->offs_h
;
634 voff2
= f
->o_height
- f
->height
- f
->offs_v
;
635 cfg
= S5P_CIWDOFST2_HOROFF(hoff2
) | S5P_CIWDOFST2_VEROFF(voff2
);
637 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST2
);
641 int fimc_hw_set_camera_type(struct fimc_dev
*fimc
,
642 struct s5p_fimc_isp_info
*cam
)
645 struct fimc_vid_cap
*vid_cap
= &fimc
->vid_cap
;
647 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
649 /* Select ITU B interface, disable Writeback path and test pattern. */
650 cfg
&= ~(S5P_CIGCTRL_TESTPAT_MASK
| S5P_CIGCTRL_SELCAM_ITU_A
|
651 S5P_CIGCTRL_SELCAM_MIPI
| S5P_CIGCTRL_CAMIF_SELWB
|
652 S5P_CIGCTRL_SELCAM_MIPI_A
);
654 if (cam
->bus_type
== FIMC_MIPI_CSI2
) {
655 cfg
|= S5P_CIGCTRL_SELCAM_MIPI
;
657 if (cam
->mux_id
== 0)
658 cfg
|= S5P_CIGCTRL_SELCAM_MIPI_A
;
660 /* TODO: add remaining supported formats. */
661 if (vid_cap
->fmt
.code
== V4L2_MBUS_FMT_VYUY8_2X8
) {
662 tmp
= S5P_CSIIMGFMT_YCBCR422_8BIT
;
664 err("camera image format not supported: %d",
668 tmp
|= (cam
->csi_data_align
== 32) << 8;
670 writel(tmp
, fimc
->regs
+ S5P_CSIIMGFMT
);
672 } else if (cam
->bus_type
== FIMC_ITU_601
||
673 cam
->bus_type
== FIMC_ITU_656
) {
674 if (cam
->mux_id
== 0) /* ITU-A, ITU-B: 0, 1 */
675 cfg
|= S5P_CIGCTRL_SELCAM_ITU_A
;
676 } else if (cam
->bus_type
== FIMC_LCD_WB
) {
677 cfg
|= S5P_CIGCTRL_CAMIF_SELWB
;
679 err("invalid camera bus type selected\n");
682 writel(cfg
, fimc
->regs
+ S5P_CIGCTRL
);