aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc/fimc-reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-reg.c')
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c321
1 files changed, 231 insertions, 90 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
index 5570f1ce0c9c..511631a2e5c3 100644
--- a/drivers/media/video/s5p-fimc/fimc-reg.c
+++ b/drivers/media/video/s5p-fimc/fimc-reg.c
@@ -13,6 +13,7 @@
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <mach/map.h> 15#include <mach/map.h>
16#include <media/s3c_fimc.h>
16 17
17#include "fimc-core.h" 18#include "fimc-core.h"
18 19
@@ -29,49 +30,11 @@ void fimc_hw_reset(struct fimc_dev *dev)
29 cfg = readl(dev->regs + S5P_CIGCTRL); 30 cfg = readl(dev->regs + S5P_CIGCTRL);
30 cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL); 31 cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL);
31 writel(cfg, dev->regs + S5P_CIGCTRL); 32 writel(cfg, dev->regs + S5P_CIGCTRL);
32 msleep(1); 33 udelay(1000);
33 34
34 cfg = readl(dev->regs + S5P_CIGCTRL); 35 cfg = readl(dev->regs + S5P_CIGCTRL);
35 cfg &= ~S5P_CIGCTRL_SWRST; 36 cfg &= ~S5P_CIGCTRL_SWRST;
36 writel(cfg, dev->regs + S5P_CIGCTRL); 37 writel(cfg, dev->regs + S5P_CIGCTRL);
37
38}
39
40void fimc_hw_set_rotation(struct fimc_ctx *ctx)
41{
42 u32 cfg, flip;
43 struct fimc_dev *dev = ctx->fimc_dev;
44
45 cfg = readl(dev->regs + S5P_CITRGFMT);
46 cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90);
47
48 flip = readl(dev->regs + S5P_MSCTRL);
49 flip &= ~S5P_MSCTRL_FLIP_MASK;
50
51 /*
52 * The input and output rotator cannot work simultaneously.
53 * Use the output rotator in output DMA mode or the input rotator
54 * in direct fifo output mode.
55 */
56 if (ctx->rotation == 90 || ctx->rotation == 270) {
57 if (ctx->out_path == FIMC_LCDFIFO) {
58 cfg |= S5P_CITRGFMT_INROT90;
59 if (ctx->rotation == 270)
60 flip |= S5P_MSCTRL_FLIP_180;
61 } else {
62 cfg |= S5P_CITRGFMT_OUTROT90;
63 if (ctx->rotation == 270)
64 cfg |= S5P_CITRGFMT_FLIP_180;
65 }
66 } else if (ctx->rotation == 180) {
67 if (ctx->out_path == FIMC_LCDFIFO)
68 flip |= S5P_MSCTRL_FLIP_180;
69 else
70 cfg |= S5P_CITRGFMT_FLIP_180;
71 }
72 if (ctx->rotation == 180 || ctx->rotation == 270)
73 writel(flip, dev->regs + S5P_MSCTRL);
74 writel(cfg, dev->regs + S5P_CITRGFMT);
75} 38}
76 39
77static u32 fimc_hw_get_in_flip(u32 ctx_flip) 40static u32 fimc_hw_get_in_flip(u32 ctx_flip)
@@ -114,6 +77,46 @@ static u32 fimc_hw_get_target_flip(u32 ctx_flip)
114 return flip; 77 return flip;
115} 78}
116 79
80void fimc_hw_set_rotation(struct fimc_ctx *ctx)
81{
82 u32 cfg, flip;
83 struct fimc_dev *dev = ctx->fimc_dev;
84
85 cfg = readl(dev->regs + S5P_CITRGFMT);
86 cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90 |
87 S5P_CITRGFMT_FLIP_180);
88
89 flip = readl(dev->regs + S5P_MSCTRL);
90 flip &= ~S5P_MSCTRL_FLIP_MASK;
91
92 /*
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.
96 */
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;
102 } else {
103 cfg |= S5P_CITRGFMT_OUTROT90;
104 if (ctx->rotation == 270)
105 cfg |= S5P_CITRGFMT_FLIP_180;
106 }
107 } else if (ctx->rotation == 180) {
108 if (ctx->out_path == FIMC_LCDFIFO)
109 flip |= S5P_MSCTRL_FLIP_180;
110 else
111 cfg |= S5P_CITRGFMT_FLIP_180;
112 }
113 if (ctx->rotation == 180 || ctx->rotation == 270)
114 writel(flip, dev->regs + S5P_MSCTRL);
115
116 cfg |= fimc_hw_get_target_flip(ctx->flip);
117 writel(cfg, dev->regs + S5P_CITRGFMT);
118}
119
117void fimc_hw_set_target_format(struct fimc_ctx *ctx) 120void fimc_hw_set_target_format(struct fimc_ctx *ctx)
118{ 121{
119 u32 cfg; 122 u32 cfg;
@@ -149,13 +152,15 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx)
149 break; 152 break;
150 } 153 }
151 154
152 cfg |= S5P_CITRGFMT_HSIZE(frame->width); 155 if (ctx->rotation == 90 || ctx->rotation == 270) {
153 cfg |= S5P_CITRGFMT_VSIZE(frame->height); 156 cfg |= S5P_CITRGFMT_HSIZE(frame->height);
157 cfg |= S5P_CITRGFMT_VSIZE(frame->width);
158 } else {
154 159
155 if (ctx->rotation == 0) { 160 cfg |= S5P_CITRGFMT_HSIZE(frame->width);
156 cfg &= ~S5P_CITRGFMT_FLIP_MASK; 161 cfg |= S5P_CITRGFMT_VSIZE(frame->height);
157 cfg |= fimc_hw_get_target_flip(ctx->flip);
158 } 162 }
163
159 writel(cfg, dev->regs + S5P_CITRGFMT); 164 writel(cfg, dev->regs + S5P_CITRGFMT);
160 165
161 cfg = readl(dev->regs + S5P_CITAREA) & ~S5P_CITAREA_MASK; 166 cfg = readl(dev->regs + S5P_CITAREA) & ~S5P_CITAREA_MASK;
@@ -167,16 +172,20 @@ static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
167{ 172{
168 struct fimc_dev *dev = ctx->fimc_dev; 173 struct fimc_dev *dev = ctx->fimc_dev;
169 struct fimc_frame *frame = &ctx->d_frame; 174 struct fimc_frame *frame = &ctx->d_frame;
170 u32 cfg = 0; 175 u32 cfg;
171 176
172 if (ctx->rotation == 90 || ctx->rotation == 270) { 177 cfg = S5P_ORIG_SIZE_HOR(frame->f_width);
173 cfg |= S5P_ORIG_SIZE_HOR(frame->f_height); 178 cfg |= S5P_ORIG_SIZE_VER(frame->f_height);
174 cfg |= S5P_ORIG_SIZE_VER(frame->f_width);
175 } else {
176 cfg |= S5P_ORIG_SIZE_HOR(frame->f_width);
177 cfg |= S5P_ORIG_SIZE_VER(frame->f_height);
178 }
179 writel(cfg, dev->regs + S5P_ORGOSIZE); 179 writel(cfg, dev->regs + S5P_ORGOSIZE);
180
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;
185 else /* SD */
186 cfg &= ~S5P_CIGCTRL_CSC_ITU601_709;
187 writel(cfg, dev->regs + S5P_CIGCTRL);
188
180} 189}
181 190
182void fimc_hw_set_out_dma(struct fimc_ctx *ctx) 191void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
@@ -232,36 +241,28 @@ static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
232 241
233void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable) 242void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
234{ 243{
235 unsigned long flags; 244 u32 cfg = readl(dev->regs + S5P_CIOCTRL);
236 u32 cfg;
237
238 spin_lock_irqsave(&dev->slock, flags);
239
240 cfg = readl(dev->regs + S5P_CIOCTRL);
241 if (enable) 245 if (enable)
242 cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE; 246 cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE;
243 else 247 else
244 cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE; 248 cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE;
245 writel(cfg, dev->regs + S5P_CIOCTRL); 249 writel(cfg, dev->regs + S5P_CIOCTRL);
246
247 spin_unlock_irqrestore(&dev->slock, flags);
248} 250}
249 251
250void fimc_hw_set_prescaler(struct fimc_ctx *ctx) 252static void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
251{ 253{
252 struct fimc_dev *dev = ctx->fimc_dev; 254 struct fimc_dev *dev = ctx->fimc_dev;
253 struct fimc_scaler *sc = &ctx->scaler; 255 struct fimc_scaler *sc = &ctx->scaler;
254 u32 cfg = 0, shfactor; 256 u32 cfg, shfactor;
255 257
256 shfactor = 10 - (sc->hfactor + sc->vfactor); 258 shfactor = 10 - (sc->hfactor + sc->vfactor);
257 259
258 cfg |= S5P_CISCPRERATIO_SHFACTOR(shfactor); 260 cfg = S5P_CISCPRERATIO_SHFACTOR(shfactor);
259 cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio); 261 cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio);
260 cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio); 262 cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio);
261 writel(cfg, dev->regs + S5P_CISCPRERATIO); 263 writel(cfg, dev->regs + S5P_CISCPRERATIO);
262 264
263 cfg = 0; 265 cfg = S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
264 cfg |= S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
265 cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height); 266 cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height);
266 writel(cfg, dev->regs + S5P_CISCPREDST); 267 writel(cfg, dev->regs + S5P_CISCPREDST);
267} 268}
@@ -274,6 +275,8 @@ void fimc_hw_set_scaler(struct fimc_ctx *ctx)
274 struct fimc_frame *dst_frame = &ctx->d_frame; 275 struct fimc_frame *dst_frame = &ctx->d_frame;
275 u32 cfg = 0; 276 u32 cfg = 0;
276 277
278 fimc_hw_set_prescaler(ctx);
279
277 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW)) 280 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
278 cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE); 281 cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
279 282
@@ -325,14 +328,18 @@ void fimc_hw_set_scaler(struct fimc_ctx *ctx)
325void fimc_hw_en_capture(struct fimc_ctx *ctx) 328void fimc_hw_en_capture(struct fimc_ctx *ctx)
326{ 329{
327 struct fimc_dev *dev = ctx->fimc_dev; 330 struct fimc_dev *dev = ctx->fimc_dev;
328 u32 cfg;
329 331
330 cfg = readl(dev->regs + S5P_CIIMGCPT); 332 u32 cfg = readl(dev->regs + S5P_CIIMGCPT);
331 /* One shot mode for output DMA or freerun for FIFO. */ 333
332 if (ctx->out_path == FIMC_DMA) 334 if (ctx->out_path == FIMC_DMA) {
333 cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE; 335 /* one shot mode */
334 else 336 cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN;
335 cfg &= ~S5P_CIIMGCPT_CPT_FREN_ENABLE; 337 } else {
338 /* Continous frame capture mode (freerun). */
339 cfg &= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE |
340 S5P_CIIMGCPT_CPT_FRMOD_CNT);
341 cfg |= S5P_CIIMGCPT_IMGCPTEN;
342 }
336 343
337 if (ctx->scaler.enabled) 344 if (ctx->scaler.enabled)
338 cfg |= S5P_CIIMGCPT_IMGCPTEN_SC; 345 cfg |= S5P_CIIMGCPT_IMGCPTEN_SC;
@@ -364,7 +371,7 @@ static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
364 u32 cfg_r = 0; 371 u32 cfg_r = 0;
365 372
366 if (FIMC_LCDFIFO == ctx->out_path) 373 if (FIMC_LCDFIFO == ctx->out_path)
367 cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN; 374 cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
368 375
369 cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width); 376 cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width);
370 cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height); 377 cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height);
@@ -380,27 +387,25 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
380 struct fimc_dev *dev = ctx->fimc_dev; 387 struct fimc_dev *dev = ctx->fimc_dev;
381 struct fimc_frame *frame = &ctx->s_frame; 388 struct fimc_frame *frame = &ctx->s_frame;
382 struct fimc_dma_offset *offset = &frame->dma_offset; 389 struct fimc_dma_offset *offset = &frame->dma_offset;
383 u32 cfg = 0; 390 u32 cfg;
384 391
385 /* Set the pixel offsets. */ 392 /* Set the pixel offsets. */
386 cfg |= S5P_CIO_OFFS_HOR(offset->y_h); 393 cfg = S5P_CIO_OFFS_HOR(offset->y_h);
387 cfg |= S5P_CIO_OFFS_VER(offset->y_v); 394 cfg |= S5P_CIO_OFFS_VER(offset->y_v);
388 writel(cfg, dev->regs + S5P_CIIYOFF); 395 writel(cfg, dev->regs + S5P_CIIYOFF);
389 396
390 cfg = 0; 397 cfg = S5P_CIO_OFFS_HOR(offset->cb_h);
391 cfg |= S5P_CIO_OFFS_HOR(offset->cb_h);
392 cfg |= S5P_CIO_OFFS_VER(offset->cb_v); 398 cfg |= S5P_CIO_OFFS_VER(offset->cb_v);
393 writel(cfg, dev->regs + S5P_CIICBOFF); 399 writel(cfg, dev->regs + S5P_CIICBOFF);
394 400
395 cfg = 0; 401 cfg = S5P_CIO_OFFS_HOR(offset->cr_h);
396 cfg |= S5P_CIO_OFFS_HOR(offset->cr_h);
397 cfg |= S5P_CIO_OFFS_VER(offset->cr_v); 402 cfg |= S5P_CIO_OFFS_VER(offset->cr_v);
398 writel(cfg, dev->regs + S5P_CIICROFF); 403 writel(cfg, dev->regs + S5P_CIICROFF);
399 404
400 /* Input original and real size. */ 405 /* Input original and real size. */
401 fimc_hw_set_in_dma_size(ctx); 406 fimc_hw_set_in_dma_size(ctx);
402 407
403 /* Autoload is used currently only in FIFO mode. */ 408 /* Use DMA autoload only in FIFO mode. */
404 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO); 409 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO);
405 410
406 /* Set the input DMA to process single frame only. */ 411 /* Set the input DMA to process single frame only. */
@@ -501,27 +506,163 @@ void fimc_hw_set_output_path(struct fimc_ctx *ctx)
501 506
502void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr) 507void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
503{ 508{
504 u32 cfg = 0; 509 u32 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
505
506 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
507 cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS; 510 cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS;
508 writel(cfg, dev->regs + S5P_CIREAL_ISIZE); 511 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
509 512
510 writel(paddr->y, dev->regs + S5P_CIIYSA0); 513 writel(paddr->y, dev->regs + S5P_CIIYSA(0));
511 writel(paddr->cb, dev->regs + S5P_CIICBSA0); 514 writel(paddr->cb, dev->regs + S5P_CIICBSA(0));
512 writel(paddr->cr, dev->regs + S5P_CIICRSA0); 515 writel(paddr->cr, dev->regs + S5P_CIICRSA(0));
513 516
514 cfg &= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS; 517 cfg &= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS;
515 writel(cfg, dev->regs + S5P_CIREAL_ISIZE); 518 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
516} 519}
517 520
518void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr) 521void fimc_hw_set_output_addr(struct fimc_dev *dev,
522 struct fimc_addr *paddr, int index)
519{ 523{
520 int i; 524 int i = (index == -1) ? 0 : index;
521 /* Set all the output register sets to point to single video buffer. */ 525 do {
522 for (i = 0; i < FIMC_MAX_OUT_BUFS; i++) {
523 writel(paddr->y, dev->regs + S5P_CIOYSA(i)); 526 writel(paddr->y, dev->regs + S5P_CIOYSA(i));
524 writel(paddr->cb, dev->regs + S5P_CIOCBSA(i)); 527 writel(paddr->cb, dev->regs + S5P_CIOCBSA(i));
525 writel(paddr->cr, dev->regs + S5P_CIOCRSA(i)); 528 writel(paddr->cr, dev->regs + S5P_CIOCRSA(i));
529 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
530 i, paddr->y, paddr->cb, paddr->cr);
531 } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
532}
533
534int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
535 struct s3c_fimc_isp_info *cam)
536{
537 u32 cfg = readl(fimc->regs + S5P_CIGCTRL);
538
539 cfg &= ~(S5P_CIGCTRL_INVPOLPCLK | S5P_CIGCTRL_INVPOLVSYNC |
540 S5P_CIGCTRL_INVPOLHREF | S5P_CIGCTRL_INVPOLHSYNC);
541
542 if (cam->flags & FIMC_CLK_INV_PCLK)
543 cfg |= S5P_CIGCTRL_INVPOLPCLK;
544
545 if (cam->flags & FIMC_CLK_INV_VSYNC)
546 cfg |= S5P_CIGCTRL_INVPOLVSYNC;
547
548 if (cam->flags & FIMC_CLK_INV_HREF)
549 cfg |= S5P_CIGCTRL_INVPOLHREF;
550
551 if (cam->flags & FIMC_CLK_INV_HSYNC)
552 cfg |= S5P_CIGCTRL_INVPOLHSYNC;
553
554 writel(cfg, fimc->regs + S5P_CIGCTRL);
555
556 return 0;
557}
558
559int fimc_hw_set_camera_source(struct fimc_dev *fimc,
560 struct s3c_fimc_isp_info *cam)
561{
562 struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
563 u32 cfg = 0;
564
565 if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) {
566
567 switch (fimc->vid_cap.fmt.code) {
568 case V4L2_MBUS_FMT_YUYV8_2X8:
569 cfg = S5P_CISRCFMT_ORDER422_YCBYCR;
570 break;
571 case V4L2_MBUS_FMT_YVYU8_2X8:
572 cfg = S5P_CISRCFMT_ORDER422_YCRYCB;
573 break;
574 case V4L2_MBUS_FMT_VYUY8_2X8:
575 cfg = S5P_CISRCFMT_ORDER422_CRYCBY;
576 break;
577 case V4L2_MBUS_FMT_UYVY8_2X8:
578 cfg = S5P_CISRCFMT_ORDER422_CBYCRY;
579 break;
580 default:
581 err("camera image format not supported: %d",
582 fimc->vid_cap.fmt.code);
583 return -EINVAL;
584 }
585
586 if (cam->bus_type == FIMC_ITU_601) {
587 if (cam->bus_width == 8) {
588 cfg |= S5P_CISRCFMT_ITU601_8BIT;
589 } else if (cam->bus_width == 16) {
590 cfg |= S5P_CISRCFMT_ITU601_16BIT;
591 } else {
592 err("invalid bus width: %d", cam->bus_width);
593 return -EINVAL;
594 }
595 } /* else defaults to ITU-R BT.656 8-bit */
526 } 596 }
597
598 cfg |= S5P_CISRCFMT_HSIZE(f->o_width) | S5P_CISRCFMT_VSIZE(f->o_height);
599 writel(cfg, fimc->regs + S5P_CISRCFMT);
600 return 0;
601}
602
603
604int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
605{
606 u32 hoff2, voff2;
607
608 u32 cfg = readl(fimc->regs + S5P_CIWDOFST);
609
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);
614
615 writel(cfg, fimc->regs + S5P_CIWDOFST);
616
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);
621
622 writel(cfg, fimc->regs + S5P_CIWDOFST2);
623 return 0;
624}
625
626int fimc_hw_set_camera_type(struct fimc_dev *fimc,
627 struct s3c_fimc_isp_info *cam)
628{
629 u32 cfg, tmp;
630 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
631
632 cfg = readl(fimc->regs + S5P_CIGCTRL);
633
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);
638
639 if (cam->bus_type == FIMC_MIPI_CSI2) {
640 cfg |= S5P_CIGCTRL_SELCAM_MIPI;
641
642 if (cam->mux_id == 0)
643 cfg |= S5P_CIGCTRL_SELCAM_MIPI_A;
644
645 /* TODO: add remaining supported formats. */
646 if (vid_cap->fmt.code == V4L2_MBUS_FMT_VYUY8_2X8) {
647 tmp = S5P_CSIIMGFMT_YCBCR422_8BIT;
648 } else {
649 err("camera image format not supported: %d",
650 vid_cap->fmt.code);
651 return -EINVAL;
652 }
653 writel(tmp | (0x1 << 8), fimc->regs + S5P_CSIIMGFMT);
654
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;
661 } else {
662 err("invalid camera bus type selected\n");
663 return -EINVAL;
664 }
665 writel(cfg, fimc->regs + S5P_CIGCTRL);
666
667 return 0;
527} 668}