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(u32 ctx_flip
)
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
;
59 static u32
fimc_hw_get_target_flip(u32 ctx_flip
)
61 u32 flip
= S5P_CITRGFMT_FLIP_NORMAL
;
65 flip
= S5P_CITRGFMT_FLIP_X_MIRROR
;
68 flip
= S5P_CITRGFMT_FLIP_Y_MIRROR
;
71 flip
= S5P_CITRGFMT_FLIP_180
;
80 void fimc_hw_set_rotation(struct fimc_ctx
*ctx
)
83 struct fimc_dev
*dev
= ctx
->fimc_dev
;
85 cfg
= readl(dev
->regs
+ S5P_CITRGFMT
);
86 cfg
&= ~(S5P_CITRGFMT_INROT90
| S5P_CITRGFMT_OUTROT90
|
87 S5P_CITRGFMT_FLIP_180
);
89 flip
= readl(dev
->regs
+ S5P_MSCTRL
);
90 flip
&= ~S5P_MSCTRL_FLIP_MASK
;
93 * The input and output rotator cannot work simultaneously.
94 * Use the output rotator in output DMA mode or the input rotator
95 * in direct fifo output mode.
97 if (ctx
->rotation
== 90 || ctx
->rotation
== 270) {
98 if (ctx
->out_path
== FIMC_LCDFIFO
) {
99 cfg
|= S5P_CITRGFMT_INROT90
;
100 if (ctx
->rotation
== 270)
101 flip
|= S5P_MSCTRL_FLIP_180
;
103 cfg
|= S5P_CITRGFMT_OUTROT90
;
104 if (ctx
->rotation
== 270)
105 cfg
|= S5P_CITRGFMT_FLIP_180
;
107 } else if (ctx
->rotation
== 180) {
108 if (ctx
->out_path
== FIMC_LCDFIFO
)
109 flip
|= S5P_MSCTRL_FLIP_180
;
111 cfg
|= S5P_CITRGFMT_FLIP_180
;
113 if (ctx
->rotation
== 180 || ctx
->rotation
== 270)
114 writel(flip
, dev
->regs
+ S5P_MSCTRL
);
116 cfg
|= fimc_hw_get_target_flip(ctx
->flip
);
117 writel(cfg
, dev
->regs
+ S5P_CITRGFMT
);
120 void fimc_hw_set_target_format(struct fimc_ctx
*ctx
)
123 struct fimc_dev
*dev
= ctx
->fimc_dev
;
124 struct fimc_frame
*frame
= &ctx
->d_frame
;
126 dbg("w= %d, h= %d color: %d", frame
->width
,
127 frame
->height
, frame
->fmt
->color
);
129 cfg
= readl(dev
->regs
+ S5P_CITRGFMT
);
130 cfg
&= ~(S5P_CITRGFMT_FMT_MASK
| S5P_CITRGFMT_HSIZE_MASK
|
131 S5P_CITRGFMT_VSIZE_MASK
);
133 switch (frame
->fmt
->color
) {
134 case S5P_FIMC_RGB565
:
135 case S5P_FIMC_RGB666
:
136 case S5P_FIMC_RGB888
:
137 cfg
|= S5P_CITRGFMT_RGB
;
139 case S5P_FIMC_YCBCR420
:
140 cfg
|= S5P_CITRGFMT_YCBCR420
;
142 case S5P_FIMC_YCBYCR422
:
143 case S5P_FIMC_YCRYCB422
:
144 case S5P_FIMC_CBYCRY422
:
145 case S5P_FIMC_CRYCBY422
:
146 if (frame
->fmt
->colplanes
== 1)
147 cfg
|= S5P_CITRGFMT_YCBCR422_1P
;
149 cfg
|= S5P_CITRGFMT_YCBCR422
;
155 if (ctx
->rotation
== 90 || ctx
->rotation
== 270) {
156 cfg
|= S5P_CITRGFMT_HSIZE(frame
->height
);
157 cfg
|= S5P_CITRGFMT_VSIZE(frame
->width
);
160 cfg
|= S5P_CITRGFMT_HSIZE(frame
->width
);
161 cfg
|= S5P_CITRGFMT_VSIZE(frame
->height
);
164 writel(cfg
, dev
->regs
+ S5P_CITRGFMT
);
166 cfg
= readl(dev
->regs
+ S5P_CITAREA
) & ~S5P_CITAREA_MASK
;
167 cfg
|= (frame
->width
* frame
->height
);
168 writel(cfg
, dev
->regs
+ S5P_CITAREA
);
171 static void fimc_hw_set_out_dma_size(struct fimc_ctx
*ctx
)
173 struct fimc_dev
*dev
= ctx
->fimc_dev
;
174 struct fimc_frame
*frame
= &ctx
->d_frame
;
177 cfg
= S5P_ORIG_SIZE_HOR(frame
->f_width
);
178 cfg
|= S5P_ORIG_SIZE_VER(frame
->f_height
);
179 writel(cfg
, dev
->regs
+ S5P_ORGOSIZE
);
181 /* Select color space conversion equation (HD/SD size).*/
182 cfg
= readl(dev
->regs
+ S5P_CIGCTRL
);
183 if (frame
->f_width
>= 1280) /* HD */
184 cfg
|= S5P_CIGCTRL_CSC_ITU601_709
;
186 cfg
&= ~S5P_CIGCTRL_CSC_ITU601_709
;
187 writel(cfg
, dev
->regs
+ S5P_CIGCTRL
);
191 void fimc_hw_set_out_dma(struct fimc_ctx
*ctx
)
194 struct fimc_dev
*dev
= ctx
->fimc_dev
;
195 struct fimc_frame
*frame
= &ctx
->d_frame
;
196 struct fimc_dma_offset
*offset
= &frame
->dma_offset
;
198 /* Set the input dma offsets. */
200 cfg
|= S5P_CIO_OFFS_HOR(offset
->y_h
);
201 cfg
|= S5P_CIO_OFFS_VER(offset
->y_v
);
202 writel(cfg
, dev
->regs
+ S5P_CIOYOFF
);
205 cfg
|= S5P_CIO_OFFS_HOR(offset
->cb_h
);
206 cfg
|= S5P_CIO_OFFS_VER(offset
->cb_v
);
207 writel(cfg
, dev
->regs
+ S5P_CIOCBOFF
);
210 cfg
|= S5P_CIO_OFFS_HOR(offset
->cr_h
);
211 cfg
|= S5P_CIO_OFFS_VER(offset
->cr_v
);
212 writel(cfg
, dev
->regs
+ S5P_CIOCROFF
);
214 fimc_hw_set_out_dma_size(ctx
);
216 /* Configure chroma components order. */
217 cfg
= readl(dev
->regs
+ S5P_CIOCTRL
);
219 cfg
&= ~(S5P_CIOCTRL_ORDER2P_MASK
| S5P_CIOCTRL_ORDER422_MASK
|
220 S5P_CIOCTRL_YCBCR_PLANE_MASK
);
222 if (frame
->fmt
->colplanes
== 1)
223 cfg
|= ctx
->out_order_1p
;
224 else if (frame
->fmt
->colplanes
== 2)
225 cfg
|= ctx
->out_order_2p
| S5P_CIOCTRL_YCBCR_2PLANE
;
226 else if (frame
->fmt
->colplanes
== 3)
227 cfg
|= S5P_CIOCTRL_YCBCR_3PLANE
;
229 writel(cfg
, dev
->regs
+ S5P_CIOCTRL
);
232 static void fimc_hw_en_autoload(struct fimc_dev
*dev
, int enable
)
234 u32 cfg
= readl(dev
->regs
+ S5P_ORGISIZE
);
236 cfg
|= S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
238 cfg
&= ~S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
239 writel(cfg
, dev
->regs
+ S5P_ORGISIZE
);
242 void fimc_hw_en_lastirq(struct fimc_dev
*dev
, int enable
)
244 u32 cfg
= readl(dev
->regs
+ S5P_CIOCTRL
);
246 cfg
|= S5P_CIOCTRL_LASTIRQ_ENABLE
;
248 cfg
&= ~S5P_CIOCTRL_LASTIRQ_ENABLE
;
249 writel(cfg
, dev
->regs
+ S5P_CIOCTRL
);
252 static void fimc_hw_set_prescaler(struct fimc_ctx
*ctx
)
254 struct fimc_dev
*dev
= ctx
->fimc_dev
;
255 struct fimc_scaler
*sc
= &ctx
->scaler
;
258 shfactor
= 10 - (sc
->hfactor
+ sc
->vfactor
);
260 cfg
= S5P_CISCPRERATIO_SHFACTOR(shfactor
);
261 cfg
|= S5P_CISCPRERATIO_HOR(sc
->pre_hratio
);
262 cfg
|= S5P_CISCPRERATIO_VER(sc
->pre_vratio
);
263 writel(cfg
, dev
->regs
+ S5P_CISCPRERATIO
);
265 cfg
= S5P_CISCPREDST_WIDTH(sc
->pre_dst_width
);
266 cfg
|= S5P_CISCPREDST_HEIGHT(sc
->pre_dst_height
);
267 writel(cfg
, dev
->regs
+ S5P_CISCPREDST
);
270 void fimc_hw_set_scaler(struct fimc_ctx
*ctx
)
272 struct fimc_dev
*dev
= ctx
->fimc_dev
;
273 struct fimc_scaler
*sc
= &ctx
->scaler
;
274 struct fimc_frame
*src_frame
= &ctx
->s_frame
;
275 struct fimc_frame
*dst_frame
= &ctx
->d_frame
;
278 fimc_hw_set_prescaler(ctx
);
280 if (!(ctx
->flags
& FIMC_COLOR_RANGE_NARROW
))
281 cfg
|= (S5P_CISCCTRL_CSCR2Y_WIDE
| S5P_CISCCTRL_CSCY2R_WIDE
);
284 cfg
|= S5P_CISCCTRL_SCALERBYPASS
;
287 cfg
|= S5P_CISCCTRL_SCALEUP_H
;
290 cfg
|= S5P_CISCCTRL_SCALEUP_V
;
293 cfg
|= S5P_CISCCTRL_ONE2ONE
;
296 if (ctx
->in_path
== FIMC_DMA
) {
297 if (src_frame
->fmt
->color
== S5P_FIMC_RGB565
)
298 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB565
;
299 else if (src_frame
->fmt
->color
== S5P_FIMC_RGB666
)
300 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB666
;
301 else if (src_frame
->fmt
->color
== S5P_FIMC_RGB888
)
302 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB888
;
305 if (ctx
->out_path
== FIMC_DMA
) {
306 if (dst_frame
->fmt
->color
== S5P_FIMC_RGB565
)
307 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB565
;
308 else if (dst_frame
->fmt
->color
== S5P_FIMC_RGB666
)
309 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB666
;
310 else if (dst_frame
->fmt
->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 dbg("main_hratio= 0x%X main_vratio= 0x%X",
320 sc
->main_hratio
, sc
->main_vratio
);
322 cfg
|= S5P_CISCCTRL_SC_HORRATIO(sc
->main_hratio
);
323 cfg
|= S5P_CISCCTRL_SC_VERRATIO(sc
->main_vratio
);
325 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
328 void fimc_hw_en_capture(struct fimc_ctx
*ctx
)
330 struct fimc_dev
*dev
= ctx
->fimc_dev
;
332 u32 cfg
= readl(dev
->regs
+ S5P_CIIMGCPT
);
334 if (ctx
->out_path
== FIMC_DMA
) {
336 cfg
|= S5P_CIIMGCPT_CPT_FREN_ENABLE
| S5P_CIIMGCPT_IMGCPTEN
;
338 /* Continous frame capture mode (freerun). */
339 cfg
&= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE
|
340 S5P_CIIMGCPT_CPT_FRMOD_CNT
);
341 cfg
|= S5P_CIIMGCPT_IMGCPTEN
;
344 if (ctx
->scaler
.enabled
)
345 cfg
|= S5P_CIIMGCPT_IMGCPTEN_SC
;
347 writel(cfg
| S5P_CIIMGCPT_IMGCPTEN
, dev
->regs
+ S5P_CIIMGCPT
);
350 void fimc_hw_set_effect(struct fimc_ctx
*ctx
)
352 struct fimc_dev
*dev
= ctx
->fimc_dev
;
353 struct fimc_effect
*effect
= &ctx
->effect
;
354 u32 cfg
= (S5P_CIIMGEFF_IE_ENABLE
| S5P_CIIMGEFF_IE_SC_AFTER
);
358 if (effect
->type
== S5P_FIMC_EFFECT_ARBITRARY
) {
359 cfg
|= S5P_CIIMGEFF_PAT_CB(effect
->pat_cb
);
360 cfg
|= S5P_CIIMGEFF_PAT_CR(effect
->pat_cr
);
363 writel(cfg
, dev
->regs
+ S5P_CIIMGEFF
);
366 static void fimc_hw_set_in_dma_size(struct fimc_ctx
*ctx
)
368 struct fimc_dev
*dev
= ctx
->fimc_dev
;
369 struct fimc_frame
*frame
= &ctx
->s_frame
;
373 if (FIMC_LCDFIFO
== ctx
->out_path
)
374 cfg_r
|= S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
376 cfg_o
|= S5P_ORIG_SIZE_HOR(frame
->f_width
);
377 cfg_o
|= S5P_ORIG_SIZE_VER(frame
->f_height
);
378 cfg_r
|= S5P_CIREAL_ISIZE_WIDTH(frame
->width
);
379 cfg_r
|= S5P_CIREAL_ISIZE_HEIGHT(frame
->height
);
381 writel(cfg_o
, dev
->regs
+ S5P_ORGISIZE
);
382 writel(cfg_r
, dev
->regs
+ S5P_CIREAL_ISIZE
);
385 void fimc_hw_set_in_dma(struct fimc_ctx
*ctx
)
387 struct fimc_dev
*dev
= ctx
->fimc_dev
;
388 struct fimc_frame
*frame
= &ctx
->s_frame
;
389 struct fimc_dma_offset
*offset
= &frame
->dma_offset
;
392 /* Set the pixel offsets. */
393 cfg
= S5P_CIO_OFFS_HOR(offset
->y_h
);
394 cfg
|= S5P_CIO_OFFS_VER(offset
->y_v
);
395 writel(cfg
, dev
->regs
+ S5P_CIIYOFF
);
397 cfg
= S5P_CIO_OFFS_HOR(offset
->cb_h
);
398 cfg
|= S5P_CIO_OFFS_VER(offset
->cb_v
);
399 writel(cfg
, dev
->regs
+ S5P_CIICBOFF
);
401 cfg
= S5P_CIO_OFFS_HOR(offset
->cr_h
);
402 cfg
|= S5P_CIO_OFFS_VER(offset
->cr_v
);
403 writel(cfg
, dev
->regs
+ S5P_CIICROFF
);
405 /* Input original and real size. */
406 fimc_hw_set_in_dma_size(ctx
);
408 /* Use DMA autoload only in FIFO mode. */
409 fimc_hw_en_autoload(dev
, ctx
->out_path
== FIMC_LCDFIFO
);
411 /* Set the input DMA to process single frame only. */
412 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
413 cfg
&= ~(S5P_MSCTRL_FLIP_MASK
414 | S5P_MSCTRL_INFORMAT_MASK
415 | S5P_MSCTRL_IN_BURST_COUNT_MASK
416 | S5P_MSCTRL_INPUT_MASK
417 | S5P_MSCTRL_C_INT_IN_MASK
418 | S5P_MSCTRL_2P_IN_ORDER_MASK
);
420 cfg
|= S5P_MSCTRL_IN_BURST_COUNT(4) | S5P_MSCTRL_INPUT_MEMORY
;
422 switch (frame
->fmt
->color
) {
423 case S5P_FIMC_RGB565
...S5P_FIMC_RGB888
:
424 cfg
|= S5P_MSCTRL_INFORMAT_RGB
;
426 case S5P_FIMC_YCBCR420
:
427 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR420
;
429 if (frame
->fmt
->colplanes
== 2)
430 cfg
|= ctx
->in_order_2p
| S5P_MSCTRL_C_INT_IN_2PLANE
;
432 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
435 case S5P_FIMC_YCBYCR422
...S5P_FIMC_CRYCBY422
:
436 if (frame
->fmt
->colplanes
== 1) {
437 cfg
|= ctx
->in_order_1p
438 | S5P_MSCTRL_INFORMAT_YCBCR422_1P
;
440 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR422
;
442 if (frame
->fmt
->colplanes
== 2)
443 cfg
|= ctx
->in_order_2p
444 | S5P_MSCTRL_C_INT_IN_2PLANE
;
446 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
454 * Input DMA flip mode (and rotation).
455 * Do not allow simultaneous rotation and flipping.
457 if (!ctx
->rotation
&& ctx
->out_path
== FIMC_LCDFIFO
)
458 cfg
|= fimc_hw_get_in_flip(ctx
->flip
);
460 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
462 /* Input/output DMA linear/tiled mode. */
463 cfg
= readl(dev
->regs
+ S5P_CIDMAPARAM
);
464 cfg
&= ~S5P_CIDMAPARAM_TILE_MASK
;
466 if (tiled_fmt(ctx
->s_frame
.fmt
))
467 cfg
|= S5P_CIDMAPARAM_R_64X32
;
469 if (tiled_fmt(ctx
->d_frame
.fmt
))
470 cfg
|= S5P_CIDMAPARAM_W_64X32
;
472 writel(cfg
, dev
->regs
+ S5P_CIDMAPARAM
);
476 void fimc_hw_set_input_path(struct fimc_ctx
*ctx
)
478 struct fimc_dev
*dev
= ctx
->fimc_dev
;
480 u32 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
481 cfg
&= ~S5P_MSCTRL_INPUT_MASK
;
483 if (ctx
->in_path
== FIMC_DMA
)
484 cfg
|= S5P_MSCTRL_INPUT_MEMORY
;
486 cfg
|= S5P_MSCTRL_INPUT_EXTCAM
;
488 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
491 void fimc_hw_set_output_path(struct fimc_ctx
*ctx
)
493 struct fimc_dev
*dev
= ctx
->fimc_dev
;
495 u32 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
496 cfg
&= ~S5P_CISCCTRL_LCDPATHEN_FIFO
;
497 if (ctx
->out_path
== FIMC_LCDFIFO
)
498 cfg
|= S5P_CISCCTRL_LCDPATHEN_FIFO
;
499 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
502 void fimc_hw_set_input_addr(struct fimc_dev
*dev
, struct fimc_addr
*paddr
)
504 u32 cfg
= readl(dev
->regs
+ S5P_CIREAL_ISIZE
);
505 cfg
|= S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
506 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
508 writel(paddr
->y
, dev
->regs
+ S5P_CIIYSA(0));
509 writel(paddr
->cb
, dev
->regs
+ S5P_CIICBSA(0));
510 writel(paddr
->cr
, dev
->regs
+ S5P_CIICRSA(0));
512 cfg
&= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
513 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
516 void fimc_hw_set_output_addr(struct fimc_dev
*dev
,
517 struct fimc_addr
*paddr
, int index
)
519 int i
= (index
== -1) ? 0 : index
;
521 writel(paddr
->y
, dev
->regs
+ S5P_CIOYSA(i
));
522 writel(paddr
->cb
, dev
->regs
+ S5P_CIOCBSA(i
));
523 writel(paddr
->cr
, dev
->regs
+ S5P_CIOCRSA(i
));
524 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
525 i
, paddr
->y
, paddr
->cb
, paddr
->cr
);
526 } while (index
== -1 && ++i
< FIMC_MAX_OUT_BUFS
);
529 int fimc_hw_set_camera_polarity(struct fimc_dev
*fimc
,
530 struct s5p_fimc_isp_info
*cam
)
532 u32 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
534 cfg
&= ~(S5P_CIGCTRL_INVPOLPCLK
| S5P_CIGCTRL_INVPOLVSYNC
|
535 S5P_CIGCTRL_INVPOLHREF
| S5P_CIGCTRL_INVPOLHSYNC
);
537 if (cam
->flags
& FIMC_CLK_INV_PCLK
)
538 cfg
|= S5P_CIGCTRL_INVPOLPCLK
;
540 if (cam
->flags
& FIMC_CLK_INV_VSYNC
)
541 cfg
|= S5P_CIGCTRL_INVPOLVSYNC
;
543 if (cam
->flags
& FIMC_CLK_INV_HREF
)
544 cfg
|= S5P_CIGCTRL_INVPOLHREF
;
546 if (cam
->flags
& FIMC_CLK_INV_HSYNC
)
547 cfg
|= S5P_CIGCTRL_INVPOLHSYNC
;
549 writel(cfg
, fimc
->regs
+ S5P_CIGCTRL
);
554 int fimc_hw_set_camera_source(struct fimc_dev
*fimc
,
555 struct s5p_fimc_isp_info
*cam
)
557 struct fimc_frame
*f
= &fimc
->vid_cap
.ctx
->s_frame
;
562 static const struct {
567 { V4L2_MBUS_FMT_YUYV8_2X8
, S5P_CISRCFMT_ORDER422_YCBYCR
, 8 },
568 { V4L2_MBUS_FMT_YVYU8_2X8
, S5P_CISRCFMT_ORDER422_YCRYCB
, 8 },
569 { V4L2_MBUS_FMT_VYUY8_2X8
, S5P_CISRCFMT_ORDER422_CRYCBY
, 8 },
570 { V4L2_MBUS_FMT_UYVY8_2X8
, S5P_CISRCFMT_ORDER422_CBYCRY
, 8 },
571 /* TODO: Add pixel codes for 16-bit bus width */
574 if (cam
->bus_type
== FIMC_ITU_601
|| cam
->bus_type
== FIMC_ITU_656
) {
575 for (i
= 0; i
< ARRAY_SIZE(pix_desc
); i
++) {
576 if (fimc
->vid_cap
.fmt
.code
== pix_desc
[i
].pixelcode
) {
577 cfg
= pix_desc
[i
].cisrcfmt
;
578 bus_width
= pix_desc
[i
].bus_width
;
583 if (i
== ARRAY_SIZE(pix_desc
)) {
584 v4l2_err(&fimc
->vid_cap
.v4l2_dev
,
585 "Camera color format not supported: %d\n",
586 fimc
->vid_cap
.fmt
.code
);
590 if (cam
->bus_type
== FIMC_ITU_601
) {
592 cfg
|= S5P_CISRCFMT_ITU601_8BIT
;
593 else if (bus_width
== 16)
594 cfg
|= S5P_CISRCFMT_ITU601_16BIT
;
595 } /* else defaults to ITU-R BT.656 8-bit */
598 cfg
|= S5P_CISRCFMT_HSIZE(f
->o_width
) | S5P_CISRCFMT_VSIZE(f
->o_height
);
599 writel(cfg
, fimc
->regs
+ S5P_CISRCFMT
);
604 int fimc_hw_set_camera_offset(struct fimc_dev
*fimc
, struct fimc_frame
*f
)
608 u32 cfg
= readl(fimc
->regs
+ S5P_CIWDOFST
);
610 cfg
&= ~(S5P_CIWDOFST_HOROFF_MASK
| S5P_CIWDOFST_VEROFF_MASK
);
611 cfg
|= S5P_CIWDOFST_OFF_EN
|
612 S5P_CIWDOFST_HOROFF(f
->offs_h
) |
613 S5P_CIWDOFST_VEROFF(f
->offs_v
);
615 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST
);
617 /* See CIWDOFSTn register description in the datasheet for details. */
618 hoff2
= f
->o_width
- f
->width
- f
->offs_h
;
619 voff2
= f
->o_height
- f
->height
- f
->offs_v
;
620 cfg
= S5P_CIWDOFST2_HOROFF(hoff2
) | S5P_CIWDOFST2_VEROFF(voff2
);
622 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST2
);
626 int fimc_hw_set_camera_type(struct fimc_dev
*fimc
,
627 struct s5p_fimc_isp_info
*cam
)
630 struct fimc_vid_cap
*vid_cap
= &fimc
->vid_cap
;
632 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
634 /* Select ITU B interface, disable Writeback path and test pattern. */
635 cfg
&= ~(S5P_CIGCTRL_TESTPAT_MASK
| S5P_CIGCTRL_SELCAM_ITU_A
|
636 S5P_CIGCTRL_SELCAM_MIPI
| S5P_CIGCTRL_CAMIF_SELWB
|
637 S5P_CIGCTRL_SELCAM_MIPI_A
);
639 if (cam
->bus_type
== FIMC_MIPI_CSI2
) {
640 cfg
|= S5P_CIGCTRL_SELCAM_MIPI
;
642 if (cam
->mux_id
== 0)
643 cfg
|= S5P_CIGCTRL_SELCAM_MIPI_A
;
645 /* TODO: add remaining supported formats. */
646 if (vid_cap
->fmt
.code
== V4L2_MBUS_FMT_VYUY8_2X8
) {
647 tmp
= S5P_CSIIMGFMT_YCBCR422_8BIT
;
649 err("camera image format not supported: %d",
653 writel(tmp
| (0x1 << 8), fimc
->regs
+ S5P_CSIIMGFMT
);
655 } else if (cam
->bus_type
== FIMC_ITU_601
||
656 cam
->bus_type
== FIMC_ITU_656
) {
657 if (cam
->mux_id
== 0) /* ITU-A, ITU-B: 0, 1 */
658 cfg
|= S5P_CIGCTRL_SELCAM_ITU_A
;
659 } else if (cam
->bus_type
== FIMC_LCD_WB
) {
660 cfg
|= S5P_CIGCTRL_CAMIF_SELWB
;
662 err("invalid camera bus type selected\n");
665 writel(cfg
, fimc
->regs
+ S5P_CIGCTRL
);