diff options
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-reg.c')
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-reg.c | 321 |
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 | |||
40 | void 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 | ||
77 | static u32 fimc_hw_get_in_flip(u32 ctx_flip) | 40 | static 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 | ||
80 | void 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 | |||
117 | void fimc_hw_set_target_format(struct fimc_ctx *ctx) | 120 | void 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 | ||
182 | void fimc_hw_set_out_dma(struct fimc_ctx *ctx) | 191 | void 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 | ||
233 | void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable) | 242 | void 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 | ||
250 | void fimc_hw_set_prescaler(struct fimc_ctx *ctx) | 252 | static 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) | |||
325 | void fimc_hw_en_capture(struct fimc_ctx *ctx) | 328 | void 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 | ||
502 | void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr) | 507 | void 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 | ||
518 | void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr) | 521 | void 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 | |||
534 | int 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 | |||
559 | int 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 | |||
604 | int 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 | |||
626 | int 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 | } |