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_RGB565
...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
;
179 /* Set the input dma offsets. */
181 cfg
|= S5P_CIO_OFFS_HOR(offset
->y_h
);
182 cfg
|= S5P_CIO_OFFS_VER(offset
->y_v
);
183 writel(cfg
, dev
->regs
+ S5P_CIOYOFF
);
186 cfg
|= S5P_CIO_OFFS_HOR(offset
->cb_h
);
187 cfg
|= S5P_CIO_OFFS_VER(offset
->cb_v
);
188 writel(cfg
, dev
->regs
+ S5P_CIOCBOFF
);
191 cfg
|= S5P_CIO_OFFS_HOR(offset
->cr_h
);
192 cfg
|= S5P_CIO_OFFS_VER(offset
->cr_v
);
193 writel(cfg
, dev
->regs
+ S5P_CIOCROFF
);
195 fimc_hw_set_out_dma_size(ctx
);
197 /* Configure chroma components order. */
198 cfg
= readl(dev
->regs
+ S5P_CIOCTRL
);
200 cfg
&= ~(S5P_CIOCTRL_ORDER2P_MASK
| S5P_CIOCTRL_ORDER422_MASK
|
201 S5P_CIOCTRL_YCBCR_PLANE_MASK
);
203 if (frame
->fmt
->colplanes
== 1)
204 cfg
|= ctx
->out_order_1p
;
205 else if (frame
->fmt
->colplanes
== 2)
206 cfg
|= ctx
->out_order_2p
| S5P_CIOCTRL_YCBCR_2PLANE
;
207 else if (frame
->fmt
->colplanes
== 3)
208 cfg
|= S5P_CIOCTRL_YCBCR_3PLANE
;
210 writel(cfg
, dev
->regs
+ S5P_CIOCTRL
);
213 static void fimc_hw_en_autoload(struct fimc_dev
*dev
, int enable
)
215 u32 cfg
= readl(dev
->regs
+ S5P_ORGISIZE
);
217 cfg
|= S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
219 cfg
&= ~S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
220 writel(cfg
, dev
->regs
+ S5P_ORGISIZE
);
223 void fimc_hw_en_lastirq(struct fimc_dev
*dev
, int enable
)
225 u32 cfg
= readl(dev
->regs
+ S5P_CIOCTRL
);
227 cfg
|= S5P_CIOCTRL_LASTIRQ_ENABLE
;
229 cfg
&= ~S5P_CIOCTRL_LASTIRQ_ENABLE
;
230 writel(cfg
, dev
->regs
+ S5P_CIOCTRL
);
233 void fimc_hw_set_prescaler(struct fimc_ctx
*ctx
)
235 struct fimc_dev
*dev
= ctx
->fimc_dev
;
236 struct fimc_scaler
*sc
= &ctx
->scaler
;
239 shfactor
= 10 - (sc
->hfactor
+ sc
->vfactor
);
241 cfg
= S5P_CISCPRERATIO_SHFACTOR(shfactor
);
242 cfg
|= S5P_CISCPRERATIO_HOR(sc
->pre_hratio
);
243 cfg
|= S5P_CISCPRERATIO_VER(sc
->pre_vratio
);
244 writel(cfg
, dev
->regs
+ S5P_CISCPRERATIO
);
246 cfg
= S5P_CISCPREDST_WIDTH(sc
->pre_dst_width
);
247 cfg
|= S5P_CISCPREDST_HEIGHT(sc
->pre_dst_height
);
248 writel(cfg
, dev
->regs
+ S5P_CISCPREDST
);
251 static void fimc_hw_set_scaler(struct fimc_ctx
*ctx
)
253 struct fimc_dev
*dev
= ctx
->fimc_dev
;
254 struct fimc_scaler
*sc
= &ctx
->scaler
;
255 struct fimc_frame
*src_frame
= &ctx
->s_frame
;
256 struct fimc_frame
*dst_frame
= &ctx
->d_frame
;
258 u32 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
260 cfg
&= ~(S5P_CISCCTRL_CSCR2Y_WIDE
| S5P_CISCCTRL_CSCY2R_WIDE
|
261 S5P_CISCCTRL_SCALEUP_H
| S5P_CISCCTRL_SCALEUP_V
|
262 S5P_CISCCTRL_SCALERBYPASS
| S5P_CISCCTRL_ONE2ONE
|
263 S5P_CISCCTRL_INRGB_FMT_MASK
| S5P_CISCCTRL_OUTRGB_FMT_MASK
|
264 S5P_CISCCTRL_INTERLACE
| S5P_CISCCTRL_RGB_EXT
);
266 if (!(ctx
->flags
& FIMC_COLOR_RANGE_NARROW
))
267 cfg
|= (S5P_CISCCTRL_CSCR2Y_WIDE
| S5P_CISCCTRL_CSCY2R_WIDE
);
270 cfg
|= S5P_CISCCTRL_SCALERBYPASS
;
273 cfg
|= S5P_CISCCTRL_SCALEUP_H
;
276 cfg
|= S5P_CISCCTRL_SCALEUP_V
;
279 cfg
|= S5P_CISCCTRL_ONE2ONE
;
282 if (ctx
->in_path
== FIMC_DMA
) {
283 if (src_frame
->fmt
->color
== S5P_FIMC_RGB565
)
284 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB565
;
285 else if (src_frame
->fmt
->color
== S5P_FIMC_RGB666
)
286 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB666
;
287 else if (src_frame
->fmt
->color
== S5P_FIMC_RGB888
)
288 cfg
|= S5P_CISCCTRL_INRGB_FMT_RGB888
;
291 if (ctx
->out_path
== FIMC_DMA
) {
292 if (dst_frame
->fmt
->color
== S5P_FIMC_RGB565
)
293 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB565
;
294 else if (dst_frame
->fmt
->color
== S5P_FIMC_RGB666
)
295 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB666
;
296 else if (dst_frame
->fmt
->color
== S5P_FIMC_RGB888
)
297 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB888
;
299 cfg
|= S5P_CISCCTRL_OUTRGB_FMT_RGB888
;
301 if (ctx
->flags
& FIMC_SCAN_MODE_INTERLACED
)
302 cfg
|= S5P_CISCCTRL_INTERLACE
;
305 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
308 void fimc_hw_set_mainscaler(struct fimc_ctx
*ctx
)
310 struct fimc_dev
*dev
= ctx
->fimc_dev
;
311 struct samsung_fimc_variant
*variant
= dev
->variant
;
312 struct fimc_scaler
*sc
= &ctx
->scaler
;
315 dbg("main_hratio= 0x%X main_vratio= 0x%X",
316 sc
->main_hratio
, sc
->main_vratio
);
318 fimc_hw_set_scaler(ctx
);
320 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
321 cfg
&= ~(S5P_CISCCTRL_MHRATIO_MASK
| S5P_CISCCTRL_MVRATIO_MASK
);
323 if (variant
->has_mainscaler_ext
) {
324 cfg
|= S5P_CISCCTRL_MHRATIO_EXT(sc
->main_hratio
);
325 cfg
|= S5P_CISCCTRL_MVRATIO_EXT(sc
->main_vratio
);
326 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
328 cfg
= readl(dev
->regs
+ S5P_CIEXTEN
);
330 cfg
&= ~(S5P_CIEXTEN_MVRATIO_EXT_MASK
|
331 S5P_CIEXTEN_MHRATIO_EXT_MASK
);
332 cfg
|= S5P_CIEXTEN_MHRATIO_EXT(sc
->main_hratio
);
333 cfg
|= S5P_CIEXTEN_MVRATIO_EXT(sc
->main_vratio
);
334 writel(cfg
, dev
->regs
+ S5P_CIEXTEN
);
336 cfg
|= S5P_CISCCTRL_MHRATIO(sc
->main_hratio
);
337 cfg
|= S5P_CISCCTRL_MVRATIO(sc
->main_vratio
);
338 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
342 void fimc_hw_en_capture(struct fimc_ctx
*ctx
)
344 struct fimc_dev
*dev
= ctx
->fimc_dev
;
346 u32 cfg
= readl(dev
->regs
+ S5P_CIIMGCPT
);
348 if (ctx
->out_path
== FIMC_DMA
) {
350 cfg
|= S5P_CIIMGCPT_CPT_FREN_ENABLE
| S5P_CIIMGCPT_IMGCPTEN
;
352 /* Continuous frame capture mode (freerun). */
353 cfg
&= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE
|
354 S5P_CIIMGCPT_CPT_FRMOD_CNT
);
355 cfg
|= S5P_CIIMGCPT_IMGCPTEN
;
358 if (ctx
->scaler
.enabled
)
359 cfg
|= S5P_CIIMGCPT_IMGCPTEN_SC
;
361 writel(cfg
| S5P_CIIMGCPT_IMGCPTEN
, dev
->regs
+ S5P_CIIMGCPT
);
364 void fimc_hw_set_effect(struct fimc_ctx
*ctx
, bool active
)
366 struct fimc_dev
*dev
= ctx
->fimc_dev
;
367 struct fimc_effect
*effect
= &ctx
->effect
;
371 cfg
|= S5P_CIIMGEFF_IE_SC_AFTER
| S5P_CIIMGEFF_IE_ENABLE
;
373 if (effect
->type
== S5P_FIMC_EFFECT_ARBITRARY
) {
374 cfg
|= S5P_CIIMGEFF_PAT_CB(effect
->pat_cb
);
375 cfg
|= S5P_CIIMGEFF_PAT_CR(effect
->pat_cr
);
379 writel(cfg
, dev
->regs
+ S5P_CIIMGEFF
);
382 static void fimc_hw_set_in_dma_size(struct fimc_ctx
*ctx
)
384 struct fimc_dev
*dev
= ctx
->fimc_dev
;
385 struct fimc_frame
*frame
= &ctx
->s_frame
;
389 if (FIMC_LCDFIFO
== ctx
->out_path
)
390 cfg_r
|= S5P_CIREAL_ISIZE_AUTOLOAD_EN
;
392 cfg_o
|= S5P_ORIG_SIZE_HOR(frame
->f_width
);
393 cfg_o
|= S5P_ORIG_SIZE_VER(frame
->f_height
);
394 cfg_r
|= S5P_CIREAL_ISIZE_WIDTH(frame
->width
);
395 cfg_r
|= S5P_CIREAL_ISIZE_HEIGHT(frame
->height
);
397 writel(cfg_o
, dev
->regs
+ S5P_ORGISIZE
);
398 writel(cfg_r
, dev
->regs
+ S5P_CIREAL_ISIZE
);
401 void fimc_hw_set_in_dma(struct fimc_ctx
*ctx
)
403 struct fimc_dev
*dev
= ctx
->fimc_dev
;
404 struct fimc_frame
*frame
= &ctx
->s_frame
;
405 struct fimc_dma_offset
*offset
= &frame
->dma_offset
;
408 /* Set the pixel offsets. */
409 cfg
= S5P_CIO_OFFS_HOR(offset
->y_h
);
410 cfg
|= S5P_CIO_OFFS_VER(offset
->y_v
);
411 writel(cfg
, dev
->regs
+ S5P_CIIYOFF
);
413 cfg
= S5P_CIO_OFFS_HOR(offset
->cb_h
);
414 cfg
|= S5P_CIO_OFFS_VER(offset
->cb_v
);
415 writel(cfg
, dev
->regs
+ S5P_CIICBOFF
);
417 cfg
= S5P_CIO_OFFS_HOR(offset
->cr_h
);
418 cfg
|= S5P_CIO_OFFS_VER(offset
->cr_v
);
419 writel(cfg
, dev
->regs
+ S5P_CIICROFF
);
421 /* Input original and real size. */
422 fimc_hw_set_in_dma_size(ctx
);
424 /* Use DMA autoload only in FIFO mode. */
425 fimc_hw_en_autoload(dev
, ctx
->out_path
== FIMC_LCDFIFO
);
427 /* Set the input DMA to process single frame only. */
428 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
429 cfg
&= ~(S5P_MSCTRL_INFORMAT_MASK
430 | S5P_MSCTRL_IN_BURST_COUNT_MASK
431 | S5P_MSCTRL_INPUT_MASK
432 | S5P_MSCTRL_C_INT_IN_MASK
433 | S5P_MSCTRL_2P_IN_ORDER_MASK
);
435 cfg
|= (S5P_MSCTRL_IN_BURST_COUNT(4)
436 | S5P_MSCTRL_INPUT_MEMORY
437 | S5P_MSCTRL_FIFO_CTRL_FULL
);
439 switch (frame
->fmt
->color
) {
440 case S5P_FIMC_RGB565
...S5P_FIMC_RGB888
:
441 cfg
|= S5P_MSCTRL_INFORMAT_RGB
;
443 case S5P_FIMC_YCBCR420
:
444 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR420
;
446 if (frame
->fmt
->colplanes
== 2)
447 cfg
|= ctx
->in_order_2p
| S5P_MSCTRL_C_INT_IN_2PLANE
;
449 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
452 case S5P_FIMC_YCBYCR422
...S5P_FIMC_CRYCBY422
:
453 if (frame
->fmt
->colplanes
== 1) {
454 cfg
|= ctx
->in_order_1p
455 | S5P_MSCTRL_INFORMAT_YCBCR422_1P
;
457 cfg
|= S5P_MSCTRL_INFORMAT_YCBCR422
;
459 if (frame
->fmt
->colplanes
== 2)
460 cfg
|= ctx
->in_order_2p
461 | S5P_MSCTRL_C_INT_IN_2PLANE
;
463 cfg
|= S5P_MSCTRL_C_INT_IN_3PLANE
;
470 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
472 /* Input/output DMA linear/tiled mode. */
473 cfg
= readl(dev
->regs
+ S5P_CIDMAPARAM
);
474 cfg
&= ~S5P_CIDMAPARAM_TILE_MASK
;
476 if (tiled_fmt(ctx
->s_frame
.fmt
))
477 cfg
|= S5P_CIDMAPARAM_R_64X32
;
479 if (tiled_fmt(ctx
->d_frame
.fmt
))
480 cfg
|= S5P_CIDMAPARAM_W_64X32
;
482 writel(cfg
, dev
->regs
+ S5P_CIDMAPARAM
);
486 void fimc_hw_set_input_path(struct fimc_ctx
*ctx
)
488 struct fimc_dev
*dev
= ctx
->fimc_dev
;
490 u32 cfg
= readl(dev
->regs
+ S5P_MSCTRL
);
491 cfg
&= ~S5P_MSCTRL_INPUT_MASK
;
493 if (ctx
->in_path
== FIMC_DMA
)
494 cfg
|= S5P_MSCTRL_INPUT_MEMORY
;
496 cfg
|= S5P_MSCTRL_INPUT_EXTCAM
;
498 writel(cfg
, dev
->regs
+ S5P_MSCTRL
);
501 void fimc_hw_set_output_path(struct fimc_ctx
*ctx
)
503 struct fimc_dev
*dev
= ctx
->fimc_dev
;
505 u32 cfg
= readl(dev
->regs
+ S5P_CISCCTRL
);
506 cfg
&= ~S5P_CISCCTRL_LCDPATHEN_FIFO
;
507 if (ctx
->out_path
== FIMC_LCDFIFO
)
508 cfg
|= S5P_CISCCTRL_LCDPATHEN_FIFO
;
509 writel(cfg
, dev
->regs
+ S5P_CISCCTRL
);
512 void fimc_hw_set_input_addr(struct fimc_dev
*dev
, struct fimc_addr
*paddr
)
514 u32 cfg
= readl(dev
->regs
+ S5P_CIREAL_ISIZE
);
515 cfg
|= S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
516 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
518 writel(paddr
->y
, dev
->regs
+ S5P_CIIYSA(0));
519 writel(paddr
->cb
, dev
->regs
+ S5P_CIICBSA(0));
520 writel(paddr
->cr
, dev
->regs
+ S5P_CIICRSA(0));
522 cfg
&= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS
;
523 writel(cfg
, dev
->regs
+ S5P_CIREAL_ISIZE
);
526 void fimc_hw_set_output_addr(struct fimc_dev
*dev
,
527 struct fimc_addr
*paddr
, int index
)
529 int i
= (index
== -1) ? 0 : index
;
531 writel(paddr
->y
, dev
->regs
+ S5P_CIOYSA(i
));
532 writel(paddr
->cb
, dev
->regs
+ S5P_CIOCBSA(i
));
533 writel(paddr
->cr
, dev
->regs
+ S5P_CIOCRSA(i
));
534 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
535 i
, paddr
->y
, paddr
->cb
, paddr
->cr
);
536 } while (index
== -1 && ++i
< FIMC_MAX_OUT_BUFS
);
539 int fimc_hw_set_camera_polarity(struct fimc_dev
*fimc
,
540 struct s5p_fimc_isp_info
*cam
)
542 u32 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
544 cfg
&= ~(S5P_CIGCTRL_INVPOLPCLK
| S5P_CIGCTRL_INVPOLVSYNC
|
545 S5P_CIGCTRL_INVPOLHREF
| S5P_CIGCTRL_INVPOLHSYNC
|
546 S5P_CIGCTRL_INVPOLFIELD
);
548 if (cam
->flags
& V4L2_MBUS_PCLK_SAMPLE_FALLING
)
549 cfg
|= S5P_CIGCTRL_INVPOLPCLK
;
551 if (cam
->flags
& V4L2_MBUS_VSYNC_ACTIVE_LOW
)
552 cfg
|= S5P_CIGCTRL_INVPOLVSYNC
;
554 if (cam
->flags
& V4L2_MBUS_HSYNC_ACTIVE_LOW
)
555 cfg
|= S5P_CIGCTRL_INVPOLHREF
;
557 if (cam
->flags
& V4L2_MBUS_HSYNC_ACTIVE_LOW
)
558 cfg
|= S5P_CIGCTRL_INVPOLHSYNC
;
560 if (cam
->flags
& V4L2_MBUS_FIELD_EVEN_LOW
)
561 cfg
|= S5P_CIGCTRL_INVPOLFIELD
;
563 writel(cfg
, fimc
->regs
+ S5P_CIGCTRL
);
568 int fimc_hw_set_camera_source(struct fimc_dev
*fimc
,
569 struct s5p_fimc_isp_info
*cam
)
571 struct fimc_frame
*f
= &fimc
->vid_cap
.ctx
->s_frame
;
576 static const struct {
581 { V4L2_MBUS_FMT_YUYV8_2X8
, S5P_CISRCFMT_ORDER422_YCBYCR
, 8 },
582 { V4L2_MBUS_FMT_YVYU8_2X8
, S5P_CISRCFMT_ORDER422_YCRYCB
, 8 },
583 { V4L2_MBUS_FMT_VYUY8_2X8
, S5P_CISRCFMT_ORDER422_CRYCBY
, 8 },
584 { V4L2_MBUS_FMT_UYVY8_2X8
, S5P_CISRCFMT_ORDER422_CBYCRY
, 8 },
585 /* TODO: Add pixel codes for 16-bit bus width */
588 if (cam
->bus_type
== FIMC_ITU_601
|| cam
->bus_type
== FIMC_ITU_656
) {
589 for (i
= 0; i
< ARRAY_SIZE(pix_desc
); i
++) {
590 if (fimc
->vid_cap
.mf
.code
== pix_desc
[i
].pixelcode
) {
591 cfg
= pix_desc
[i
].cisrcfmt
;
592 bus_width
= pix_desc
[i
].bus_width
;
597 if (i
== ARRAY_SIZE(pix_desc
)) {
598 v4l2_err(fimc
->vid_cap
.vfd
,
599 "Camera color format not supported: %d\n",
600 fimc
->vid_cap
.mf
.code
);
604 if (cam
->bus_type
== FIMC_ITU_601
) {
606 cfg
|= S5P_CISRCFMT_ITU601_8BIT
;
607 else if (bus_width
== 16)
608 cfg
|= S5P_CISRCFMT_ITU601_16BIT
;
609 } /* else defaults to ITU-R BT.656 8-bit */
610 } else if (cam
->bus_type
== FIMC_MIPI_CSI2
) {
611 if (fimc_fmt_is_jpeg(f
->fmt
->color
))
612 cfg
|= S5P_CISRCFMT_ITU601_8BIT
;
615 cfg
|= S5P_CISRCFMT_HSIZE(f
->o_width
) | S5P_CISRCFMT_VSIZE(f
->o_height
);
616 writel(cfg
, fimc
->regs
+ S5P_CISRCFMT
);
621 int fimc_hw_set_camera_offset(struct fimc_dev
*fimc
, struct fimc_frame
*f
)
625 u32 cfg
= readl(fimc
->regs
+ S5P_CIWDOFST
);
627 cfg
&= ~(S5P_CIWDOFST_HOROFF_MASK
| S5P_CIWDOFST_VEROFF_MASK
);
628 cfg
|= S5P_CIWDOFST_OFF_EN
|
629 S5P_CIWDOFST_HOROFF(f
->offs_h
) |
630 S5P_CIWDOFST_VEROFF(f
->offs_v
);
632 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST
);
634 /* See CIWDOFSTn register description in the datasheet for details. */
635 hoff2
= f
->o_width
- f
->width
- f
->offs_h
;
636 voff2
= f
->o_height
- f
->height
- f
->offs_v
;
637 cfg
= S5P_CIWDOFST2_HOROFF(hoff2
) | S5P_CIWDOFST2_VEROFF(voff2
);
639 writel(cfg
, fimc
->regs
+ S5P_CIWDOFST2
);
643 int fimc_hw_set_camera_type(struct fimc_dev
*fimc
,
644 struct s5p_fimc_isp_info
*cam
)
647 struct fimc_vid_cap
*vid_cap
= &fimc
->vid_cap
;
649 cfg
= readl(fimc
->regs
+ S5P_CIGCTRL
);
651 /* Select ITU B interface, disable Writeback path and test pattern. */
652 cfg
&= ~(S5P_CIGCTRL_TESTPAT_MASK
| S5P_CIGCTRL_SELCAM_ITU_A
|
653 S5P_CIGCTRL_SELCAM_MIPI
| S5P_CIGCTRL_CAMIF_SELWB
|
654 S5P_CIGCTRL_SELCAM_MIPI_A
| S5P_CIGCTRL_CAM_JPEG
);
656 if (cam
->bus_type
== FIMC_MIPI_CSI2
) {
657 cfg
|= S5P_CIGCTRL_SELCAM_MIPI
;
659 if (cam
->mux_id
== 0)
660 cfg
|= S5P_CIGCTRL_SELCAM_MIPI_A
;
662 /* TODO: add remaining supported formats. */
663 switch (vid_cap
->mf
.code
) {
664 case V4L2_MBUS_FMT_VYUY8_2X8
:
665 tmp
= S5P_CSIIMGFMT_YCBCR422_8BIT
;
667 case V4L2_MBUS_FMT_JPEG_1X8
:
668 tmp
= S5P_CSIIMGFMT_USER(1);
669 cfg
|= S5P_CIGCTRL_CAM_JPEG
;
672 v4l2_err(fimc
->vid_cap
.vfd
,
673 "Not supported camera pixel format: %d",
677 tmp
|= (cam
->csi_data_align
== 32) << 8;
679 writel(tmp
, 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
);