[media] v4l: Support s_crop and g_crop through s/g_selection
[deliverable/linux.git] / drivers / media / video / s5p-fimc / fimc-reg.c
CommitLineData
5fd8f738
SN
1/*
2 * Register interface file for Samsung Camera Interface (FIMC) driver
3 *
4 * Copyright (c) 2010 Samsung Electronics
5 *
6 * Sylwester Nawrocki, s.nawrocki@samsung.com
7 *
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.
11*/
12
13#include <linux/io.h>
14#include <linux/delay.h>
15#include <mach/map.h>
df7e09a3 16#include <media/s5p_fimc.h>
5fd8f738
SN
17
18#include "fimc-core.h"
19
20
21void fimc_hw_reset(struct fimc_dev *dev)
22{
23 u32 cfg;
24
25 cfg = readl(dev->regs + S5P_CISRCFMT);
26 cfg |= S5P_CISRCFMT_ITU601_8BIT;
27 writel(cfg, dev->regs + S5P_CISRCFMT);
28
29 /* Software reset. */
30 cfg = readl(dev->regs + S5P_CIGCTRL);
31 cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL);
32 writel(cfg, dev->regs + S5P_CIGCTRL);
e9e21083 33 udelay(10);
5fd8f738
SN
34
35 cfg = readl(dev->regs + S5P_CIGCTRL);
36 cfg &= ~S5P_CIGCTRL_SWRST;
37 writel(cfg, dev->regs + S5P_CIGCTRL);
2c1bb62e
SN
38
39 if (dev->variant->out_buf_count > 4)
40 fimc_hw_set_dma_seq(dev, 0xF);
5fd8f738
SN
41}
42
ac75934c 43static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
5fd8f738
SN
44{
45 u32 flip = S5P_MSCTRL_FLIP_NORMAL;
46
131b6c61 47 if (ctx->hflip)
5fd8f738 48 flip = S5P_MSCTRL_FLIP_X_MIRROR;
131b6c61 49 if (ctx->vflip)
5fd8f738 50 flip = S5P_MSCTRL_FLIP_Y_MIRROR;
131b6c61 51
ac75934c
SN
52 if (ctx->rotation <= 90)
53 return flip;
5fd8f738 54
ac75934c 55 return (flip ^ S5P_MSCTRL_FLIP_180) & S5P_MSCTRL_FLIP_180;
5fd8f738
SN
56}
57
ac75934c 58static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
5fd8f738
SN
59{
60 u32 flip = S5P_CITRGFMT_FLIP_NORMAL;
61
131b6c61
SN
62 if (ctx->hflip)
63 flip |= S5P_CITRGFMT_FLIP_X_MIRROR;
64 if (ctx->vflip)
65 flip |= S5P_CITRGFMT_FLIP_Y_MIRROR;
66
ac75934c
SN
67 if (ctx->rotation <= 90)
68 return flip;
69
70 return (flip ^ S5P_CITRGFMT_FLIP_180) & S5P_CITRGFMT_FLIP_180;
5fd8f738
SN
71}
72
47654df8
SN
73void fimc_hw_set_rotation(struct fimc_ctx *ctx)
74{
75 u32 cfg, flip;
76 struct fimc_dev *dev = ctx->fimc_dev;
77
78 cfg = readl(dev->regs + S5P_CITRGFMT);
79 cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90 |
ac75934c 80 S5P_CITRGFMT_FLIP_180);
47654df8
SN
81
82 /*
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.
86 */
87 if (ctx->rotation == 90 || ctx->rotation == 270) {
47654df8 88 if (ctx->out_path == FIMC_LCDFIFO)
ac75934c 89 cfg |= S5P_CITRGFMT_INROT90;
47654df8 90 else
ac75934c 91 cfg |= S5P_CITRGFMT_OUTROT90;
47654df8 92 }
47654df8 93
ac75934c
SN
94 if (ctx->out_path == FIMC_DMA) {
95 cfg |= fimc_hw_get_target_flip(ctx);
96 writel(cfg, dev->regs + S5P_CITRGFMT);
97 } else {
98 /* LCD FIFO path */
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);
103 }
47654df8
SN
104}
105
5fd8f738
SN
106void fimc_hw_set_target_format(struct fimc_ctx *ctx)
107{
108 u32 cfg;
109 struct fimc_dev *dev = ctx->fimc_dev;
110 struct fimc_frame *frame = &ctx->d_frame;
111
112 dbg("w= %d, h= %d color: %d", frame->width,
113 frame->height, frame->fmt->color);
114
115 cfg = readl(dev->regs + S5P_CITRGFMT);
116 cfg &= ~(S5P_CITRGFMT_FMT_MASK | S5P_CITRGFMT_HSIZE_MASK |
117 S5P_CITRGFMT_VSIZE_MASK);
118
119 switch (frame->fmt->color) {
dafb9c70 120 case S5P_FIMC_RGB444...S5P_FIMC_RGB888:
5fd8f738
SN
121 cfg |= S5P_CITRGFMT_RGB;
122 break;
123 case S5P_FIMC_YCBCR420:
124 cfg |= S5P_CITRGFMT_YCBCR420;
125 break;
ac75934c 126 case S5P_FIMC_YCBYCR422...S5P_FIMC_CRYCBY422:
ef7af59b 127 if (frame->fmt->colplanes == 1)
5fd8f738
SN
128 cfg |= S5P_CITRGFMT_YCBCR422_1P;
129 else
130 cfg |= S5P_CITRGFMT_YCBCR422;
131 break;
132 default:
133 break;
134 }
135
47654df8
SN
136 if (ctx->rotation == 90 || ctx->rotation == 270) {
137 cfg |= S5P_CITRGFMT_HSIZE(frame->height);
138 cfg |= S5P_CITRGFMT_VSIZE(frame->width);
139 } else {
5fd8f738 140
47654df8
SN
141 cfg |= S5P_CITRGFMT_HSIZE(frame->width);
142 cfg |= S5P_CITRGFMT_VSIZE(frame->height);
5fd8f738 143 }
47654df8 144
5fd8f738
SN
145 writel(cfg, dev->regs + S5P_CITRGFMT);
146
147 cfg = readl(dev->regs + S5P_CITAREA) & ~S5P_CITAREA_MASK;
148 cfg |= (frame->width * frame->height);
149 writel(cfg, dev->regs + S5P_CITAREA);
150}
151
152static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
153{
154 struct fimc_dev *dev = ctx->fimc_dev;
155 struct fimc_frame *frame = &ctx->d_frame;
47654df8 156 u32 cfg;
5fd8f738 157
47654df8
SN
158 cfg = S5P_ORIG_SIZE_HOR(frame->f_width);
159 cfg |= S5P_ORIG_SIZE_VER(frame->f_height);
5fd8f738 160 writel(cfg, dev->regs + S5P_ORGOSIZE);
5f3cc447
SN
161
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;
166 else /* SD */
167 cfg &= ~S5P_CIGCTRL_CSC_ITU601_709;
168 writel(cfg, dev->regs + S5P_CIGCTRL);
169
5fd8f738
SN
170}
171
172void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
173{
174 u32 cfg;
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;
dafb9c70 178 struct fimc_fmt *fmt = frame->fmt;
5fd8f738
SN
179
180 /* Set the input dma offsets. */
181 cfg = 0;
182 cfg |= S5P_CIO_OFFS_HOR(offset->y_h);
183 cfg |= S5P_CIO_OFFS_VER(offset->y_v);
184 writel(cfg, dev->regs + S5P_CIOYOFF);
185
186 cfg = 0;
187 cfg |= S5P_CIO_OFFS_HOR(offset->cb_h);
188 cfg |= S5P_CIO_OFFS_VER(offset->cb_v);
189 writel(cfg, dev->regs + S5P_CIOCBOFF);
190
191 cfg = 0;
192 cfg |= S5P_CIO_OFFS_HOR(offset->cr_h);
193 cfg |= S5P_CIO_OFFS_VER(offset->cr_v);
194 writel(cfg, dev->regs + S5P_CIOCROFF);
195
196 fimc_hw_set_out_dma_size(ctx);
197
198 /* Configure chroma components order. */
199 cfg = readl(dev->regs + S5P_CIOCTRL);
200
201 cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
dafb9c70 202 S5P_CIOCTRL_YCBCR_PLANE_MASK | S5P_CIOCTRL_RGB16FMT_MASK);
5fd8f738 203
dafb9c70 204 if (fmt->colplanes == 1)
5fd8f738 205 cfg |= ctx->out_order_1p;
dafb9c70 206 else if (fmt->colplanes == 2)
5fd8f738 207 cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE;
dafb9c70 208 else if (fmt->colplanes == 3)
5fd8f738
SN
209 cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
210
dafb9c70
SN
211 if (fmt->color == S5P_FIMC_RGB565)
212 cfg |= S5P_CIOCTRL_RGB565;
213 else if (fmt->color == S5P_FIMC_RGB555)
214 cfg |= S5P_CIOCTRL_ARGB1555;
215 else if (fmt->color == S5P_FIMC_RGB444)
216 cfg |= S5P_CIOCTRL_ARGB4444;
217
5fd8f738
SN
218 writel(cfg, dev->regs + S5P_CIOCTRL);
219}
220
221static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
222{
223 u32 cfg = readl(dev->regs + S5P_ORGISIZE);
224 if (enable)
225 cfg |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
226 else
227 cfg &= ~S5P_CIREAL_ISIZE_AUTOLOAD_EN;
228 writel(cfg, dev->regs + S5P_ORGISIZE);
229}
230
231void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
232{
5f3cc447 233 u32 cfg = readl(dev->regs + S5P_CIOCTRL);
5fd8f738
SN
234 if (enable)
235 cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE;
236 else
237 cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE;
238 writel(cfg, dev->regs + S5P_CIOCTRL);
5fd8f738
SN
239}
240
b241c6d6 241void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
5fd8f738
SN
242{
243 struct fimc_dev *dev = ctx->fimc_dev;
244 struct fimc_scaler *sc = &ctx->scaler;
548aafcd 245 u32 cfg, shfactor;
5fd8f738
SN
246
247 shfactor = 10 - (sc->hfactor + sc->vfactor);
248
548aafcd 249 cfg = S5P_CISCPRERATIO_SHFACTOR(shfactor);
5fd8f738
SN
250 cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio);
251 cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio);
252 writel(cfg, dev->regs + S5P_CISCPRERATIO);
253
548aafcd 254 cfg = S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
5fd8f738
SN
255 cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height);
256 writel(cfg, dev->regs + S5P_CISCPREDST);
257}
258
b241c6d6 259static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
5fd8f738
SN
260{
261 struct fimc_dev *dev = ctx->fimc_dev;
262 struct fimc_scaler *sc = &ctx->scaler;
263 struct fimc_frame *src_frame = &ctx->s_frame;
264 struct fimc_frame *dst_frame = &ctx->d_frame;
2c1bb62e
SN
265
266 u32 cfg = readl(dev->regs + S5P_CISCCTRL);
267
268 cfg &= ~(S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE |
269 S5P_CISCCTRL_SCALEUP_H | S5P_CISCCTRL_SCALEUP_V |
270 S5P_CISCCTRL_SCALERBYPASS | S5P_CISCCTRL_ONE2ONE |
271 S5P_CISCCTRL_INRGB_FMT_MASK | S5P_CISCCTRL_OUTRGB_FMT_MASK |
272 S5P_CISCCTRL_INTERLACE | S5P_CISCCTRL_RGB_EXT);
5fd8f738
SN
273
274 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
275 cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
276
277 if (!sc->enabled)
278 cfg |= S5P_CISCCTRL_SCALERBYPASS;
279
280 if (sc->scaleup_h)
281 cfg |= S5P_CISCCTRL_SCALEUP_H;
282
283 if (sc->scaleup_v)
284 cfg |= S5P_CISCCTRL_SCALEUP_V;
285
286 if (sc->copy_mode)
287 cfg |= S5P_CISCCTRL_ONE2ONE;
288
5fd8f738 289 if (ctx->in_path == FIMC_DMA) {
dafb9c70
SN
290 switch (src_frame->fmt->color) {
291 case S5P_FIMC_RGB565:
5fd8f738 292 cfg |= S5P_CISCCTRL_INRGB_FMT_RGB565;
dafb9c70
SN
293 break;
294 case S5P_FIMC_RGB666:
5fd8f738 295 cfg |= S5P_CISCCTRL_INRGB_FMT_RGB666;
dafb9c70
SN
296 break;
297 case S5P_FIMC_RGB888:
5fd8f738 298 cfg |= S5P_CISCCTRL_INRGB_FMT_RGB888;
dafb9c70
SN
299 break;
300 }
5fd8f738
SN
301 }
302
303 if (ctx->out_path == FIMC_DMA) {
dafb9c70
SN
304 u32 color = dst_frame->fmt->color;
305
306 if (color >= S5P_FIMC_RGB444 && color <= S5P_FIMC_RGB565)
5fd8f738 307 cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565;
dafb9c70 308 else if (color == S5P_FIMC_RGB666)
5fd8f738 309 cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666;
dafb9c70 310 else if (color == S5P_FIMC_RGB888)
5fd8f738
SN
311 cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
312 } else {
313 cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
314
315 if (ctx->flags & FIMC_SCAN_MODE_INTERLACED)
316 cfg |= S5P_CISCCTRL_INTERLACE;
317 }
318
b241c6d6
HK
319 writel(cfg, dev->regs + S5P_CISCCTRL);
320}
321
322void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
323{
324 struct fimc_dev *dev = ctx->fimc_dev;
70f66ea2 325 struct samsung_fimc_variant *variant = dev->variant;
b241c6d6
HK
326 struct fimc_scaler *sc = &ctx->scaler;
327 u32 cfg;
328
329 dbg("main_hratio= 0x%X main_vratio= 0x%X",
330 sc->main_hratio, sc->main_vratio);
331
332 fimc_hw_set_scaler(ctx);
333
334 cfg = readl(dev->regs + S5P_CISCCTRL);
2c1bb62e 335 cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK);
b241c6d6 336
70f66ea2 337 if (variant->has_mainscaler_ext) {
70f66ea2
SN
338 cfg |= S5P_CISCCTRL_MHRATIO_EXT(sc->main_hratio);
339 cfg |= S5P_CISCCTRL_MVRATIO_EXT(sc->main_vratio);
340 writel(cfg, dev->regs + S5P_CISCCTRL);
b241c6d6 341
70f66ea2 342 cfg = readl(dev->regs + S5P_CIEXTEN);
b241c6d6 343
70f66ea2
SN
344 cfg &= ~(S5P_CIEXTEN_MVRATIO_EXT_MASK |
345 S5P_CIEXTEN_MHRATIO_EXT_MASK);
346 cfg |= S5P_CIEXTEN_MHRATIO_EXT(sc->main_hratio);
347 cfg |= S5P_CIEXTEN_MVRATIO_EXT(sc->main_vratio);
348 writel(cfg, dev->regs + S5P_CIEXTEN);
349 } else {
70f66ea2
SN
350 cfg |= S5P_CISCCTRL_MHRATIO(sc->main_hratio);
351 cfg |= S5P_CISCCTRL_MVRATIO(sc->main_vratio);
352 writel(cfg, dev->regs + S5P_CISCCTRL);
353 }
5fd8f738
SN
354}
355
356void fimc_hw_en_capture(struct fimc_ctx *ctx)
357{
358 struct fimc_dev *dev = ctx->fimc_dev;
5fd8f738 359
5f3cc447
SN
360 u32 cfg = readl(dev->regs + S5P_CIIMGCPT);
361
362 if (ctx->out_path == FIMC_DMA) {
363 /* one shot mode */
364 cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN;
365 } else {
25985edc 366 /* Continuous frame capture mode (freerun). */
5f3cc447
SN
367 cfg &= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE |
368 S5P_CIIMGCPT_CPT_FRMOD_CNT);
369 cfg |= S5P_CIIMGCPT_IMGCPTEN;
370 }
5fd8f738
SN
371
372 if (ctx->scaler.enabled)
373 cfg |= S5P_CIIMGCPT_IMGCPTEN_SC;
374
375 writel(cfg | S5P_CIIMGCPT_IMGCPTEN, dev->regs + S5P_CIIMGCPT);
376}
377
ee7160e5 378void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active)
5fd8f738
SN
379{
380 struct fimc_dev *dev = ctx->fimc_dev;
381 struct fimc_effect *effect = &ctx->effect;
ee7160e5 382 u32 cfg = 0;
5fd8f738 383
ee7160e5
SN
384 if (active) {
385 cfg |= S5P_CIIMGEFF_IE_SC_AFTER | S5P_CIIMGEFF_IE_ENABLE;
386 cfg |= effect->type;
387 if (effect->type == S5P_FIMC_EFFECT_ARBITRARY) {
388 cfg |= S5P_CIIMGEFF_PAT_CB(effect->pat_cb);
389 cfg |= S5P_CIIMGEFF_PAT_CR(effect->pat_cr);
390 }
5fd8f738
SN
391 }
392
393 writel(cfg, dev->regs + S5P_CIIMGEFF);
394}
395
dafb9c70
SN
396void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx)
397{
398 struct fimc_dev *dev = ctx->fimc_dev;
399 struct fimc_frame *frame = &ctx->d_frame;
400 u32 cfg;
401
402 if (!(frame->fmt->flags & FMT_HAS_ALPHA))
403 return;
404
405 cfg = readl(dev->regs + S5P_CIOCTRL);
406 cfg &= ~S5P_CIOCTRL_ALPHA_OUT_MASK;
407 cfg |= (frame->alpha << 4);
408 writel(cfg, dev->regs + S5P_CIOCTRL);
409}
410
5fd8f738
SN
411static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
412{
413 struct fimc_dev *dev = ctx->fimc_dev;
414 struct fimc_frame *frame = &ctx->s_frame;
415 u32 cfg_o = 0;
416 u32 cfg_r = 0;
417
418 if (FIMC_LCDFIFO == ctx->out_path)
548aafcd 419 cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
5fd8f738
SN
420
421 cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width);
422 cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height);
423 cfg_r |= S5P_CIREAL_ISIZE_WIDTH(frame->width);
424 cfg_r |= S5P_CIREAL_ISIZE_HEIGHT(frame->height);
425
426 writel(cfg_o, dev->regs + S5P_ORGISIZE);
427 writel(cfg_r, dev->regs + S5P_CIREAL_ISIZE);
428}
429
430void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
431{
432 struct fimc_dev *dev = ctx->fimc_dev;
433 struct fimc_frame *frame = &ctx->s_frame;
434 struct fimc_dma_offset *offset = &frame->dma_offset;
548aafcd 435 u32 cfg;
5fd8f738
SN
436
437 /* Set the pixel offsets. */
548aafcd 438 cfg = S5P_CIO_OFFS_HOR(offset->y_h);
5fd8f738
SN
439 cfg |= S5P_CIO_OFFS_VER(offset->y_v);
440 writel(cfg, dev->regs + S5P_CIIYOFF);
441
548aafcd 442 cfg = S5P_CIO_OFFS_HOR(offset->cb_h);
5fd8f738
SN
443 cfg |= S5P_CIO_OFFS_VER(offset->cb_v);
444 writel(cfg, dev->regs + S5P_CIICBOFF);
445
548aafcd 446 cfg = S5P_CIO_OFFS_HOR(offset->cr_h);
5fd8f738
SN
447 cfg |= S5P_CIO_OFFS_VER(offset->cr_v);
448 writel(cfg, dev->regs + S5P_CIICROFF);
449
450 /* Input original and real size. */
451 fimc_hw_set_in_dma_size(ctx);
452
548aafcd 453 /* Use DMA autoload only in FIFO mode. */
5fd8f738
SN
454 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO);
455
456 /* Set the input DMA to process single frame only. */
457 cfg = readl(dev->regs + S5P_MSCTRL);
ac75934c 458 cfg &= ~(S5P_MSCTRL_INFORMAT_MASK
5fd8f738
SN
459 | S5P_MSCTRL_IN_BURST_COUNT_MASK
460 | S5P_MSCTRL_INPUT_MASK
461 | S5P_MSCTRL_C_INT_IN_MASK
462 | S5P_MSCTRL_2P_IN_ORDER_MASK);
463
5bbe425e
HK
464 cfg |= (S5P_MSCTRL_IN_BURST_COUNT(4)
465 | S5P_MSCTRL_INPUT_MEMORY
466 | S5P_MSCTRL_FIFO_CTRL_FULL);
5fd8f738
SN
467
468 switch (frame->fmt->color) {
d9160afd 469 case S5P_FIMC_RGB565...S5P_FIMC_RGB888:
5fd8f738
SN
470 cfg |= S5P_MSCTRL_INFORMAT_RGB;
471 break;
472 case S5P_FIMC_YCBCR420:
473 cfg |= S5P_MSCTRL_INFORMAT_YCBCR420;
474
ef7af59b 475 if (frame->fmt->colplanes == 2)
5fd8f738
SN
476 cfg |= ctx->in_order_2p | S5P_MSCTRL_C_INT_IN_2PLANE;
477 else
478 cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
479
480 break;
d9160afd 481 case S5P_FIMC_YCBYCR422...S5P_FIMC_CRYCBY422:
ef7af59b 482 if (frame->fmt->colplanes == 1) {
5fd8f738
SN
483 cfg |= ctx->in_order_1p
484 | S5P_MSCTRL_INFORMAT_YCBCR422_1P;
485 } else {
486 cfg |= S5P_MSCTRL_INFORMAT_YCBCR422;
487
ef7af59b 488 if (frame->fmt->colplanes == 2)
5fd8f738
SN
489 cfg |= ctx->in_order_2p
490 | S5P_MSCTRL_C_INT_IN_2PLANE;
491 else
492 cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
493 }
494 break;
495 default:
496 break;
497 }
498
5fd8f738
SN
499 writel(cfg, dev->regs + S5P_MSCTRL);
500
501 /* Input/output DMA linear/tiled mode. */
502 cfg = readl(dev->regs + S5P_CIDMAPARAM);
503 cfg &= ~S5P_CIDMAPARAM_TILE_MASK;
504
505 if (tiled_fmt(ctx->s_frame.fmt))
506 cfg |= S5P_CIDMAPARAM_R_64X32;
507
508 if (tiled_fmt(ctx->d_frame.fmt))
509 cfg |= S5P_CIDMAPARAM_W_64X32;
510
511 writel(cfg, dev->regs + S5P_CIDMAPARAM);
512}
513
514
515void fimc_hw_set_input_path(struct fimc_ctx *ctx)
516{
517 struct fimc_dev *dev = ctx->fimc_dev;
518
519 u32 cfg = readl(dev->regs + S5P_MSCTRL);
520 cfg &= ~S5P_MSCTRL_INPUT_MASK;
521
522 if (ctx->in_path == FIMC_DMA)
523 cfg |= S5P_MSCTRL_INPUT_MEMORY;
524 else
525 cfg |= S5P_MSCTRL_INPUT_EXTCAM;
526
527 writel(cfg, dev->regs + S5P_MSCTRL);
528}
529
530void fimc_hw_set_output_path(struct fimc_ctx *ctx)
531{
532 struct fimc_dev *dev = ctx->fimc_dev;
533
534 u32 cfg = readl(dev->regs + S5P_CISCCTRL);
535 cfg &= ~S5P_CISCCTRL_LCDPATHEN_FIFO;
536 if (ctx->out_path == FIMC_LCDFIFO)
537 cfg |= S5P_CISCCTRL_LCDPATHEN_FIFO;
538 writel(cfg, dev->regs + S5P_CISCCTRL);
539}
540
541void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
542{
548aafcd 543 u32 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
5fd8f738
SN
544 cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS;
545 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
546
77e62082
SN
547 writel(paddr->y, dev->regs + S5P_CIIYSA(0));
548 writel(paddr->cb, dev->regs + S5P_CIICBSA(0));
549 writel(paddr->cr, dev->regs + S5P_CIICRSA(0));
5fd8f738
SN
550
551 cfg &= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS;
552 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
553}
554
548aafcd
SN
555void fimc_hw_set_output_addr(struct fimc_dev *dev,
556 struct fimc_addr *paddr, int index)
5fd8f738 557{
548aafcd
SN
558 int i = (index == -1) ? 0 : index;
559 do {
5fd8f738
SN
560 writel(paddr->y, dev->regs + S5P_CIOYSA(i));
561 writel(paddr->cb, dev->regs + S5P_CIOCBSA(i));
562 writel(paddr->cr, dev->regs + S5P_CIOCRSA(i));
548aafcd
SN
563 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
564 i, paddr->y, paddr->cb, paddr->cr);
565 } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
5fd8f738 566}
5f3cc447
SN
567
568int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
df7e09a3 569 struct s5p_fimc_isp_info *cam)
5f3cc447
SN
570{
571 u32 cfg = readl(fimc->regs + S5P_CIGCTRL);
572
573 cfg &= ~(S5P_CIGCTRL_INVPOLPCLK | S5P_CIGCTRL_INVPOLVSYNC |
12ecf56d
SN
574 S5P_CIGCTRL_INVPOLHREF | S5P_CIGCTRL_INVPOLHSYNC |
575 S5P_CIGCTRL_INVPOLFIELD);
5f3cc447 576
12ecf56d 577 if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
5f3cc447
SN
578 cfg |= S5P_CIGCTRL_INVPOLPCLK;
579
12ecf56d 580 if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
5f3cc447
SN
581 cfg |= S5P_CIGCTRL_INVPOLVSYNC;
582
12ecf56d 583 if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
5f3cc447
SN
584 cfg |= S5P_CIGCTRL_INVPOLHREF;
585
12ecf56d 586 if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
5f3cc447
SN
587 cfg |= S5P_CIGCTRL_INVPOLHSYNC;
588
12ecf56d
SN
589 if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW)
590 cfg |= S5P_CIGCTRL_INVPOLFIELD;
591
5f3cc447
SN
592 writel(cfg, fimc->regs + S5P_CIGCTRL);
593
594 return 0;
595}
596
597int fimc_hw_set_camera_source(struct fimc_dev *fimc,
df7e09a3 598 struct s5p_fimc_isp_info *cam)
5f3cc447
SN
599{
600 struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
601 u32 cfg = 0;
3d0ce7ed
SN
602 u32 bus_width;
603 int i;
604
605 static const struct {
606 u32 pixelcode;
607 u32 cisrcfmt;
608 u16 bus_width;
609 } pix_desc[] = {
610 { V4L2_MBUS_FMT_YUYV8_2X8, S5P_CISRCFMT_ORDER422_YCBYCR, 8 },
611 { V4L2_MBUS_FMT_YVYU8_2X8, S5P_CISRCFMT_ORDER422_YCRYCB, 8 },
612 { V4L2_MBUS_FMT_VYUY8_2X8, S5P_CISRCFMT_ORDER422_CRYCBY, 8 },
613 { V4L2_MBUS_FMT_UYVY8_2X8, S5P_CISRCFMT_ORDER422_CBYCRY, 8 },
614 /* TODO: Add pixel codes for 16-bit bus width */
615 };
5f3cc447
SN
616
617 if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) {
3d0ce7ed 618 for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
237e0265 619 if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) {
3d0ce7ed
SN
620 cfg = pix_desc[i].cisrcfmt;
621 bus_width = pix_desc[i].bus_width;
622 break;
623 }
624 }
5f3cc447 625
3d0ce7ed 626 if (i == ARRAY_SIZE(pix_desc)) {
30c9939d 627 v4l2_err(fimc->vid_cap.vfd,
3d0ce7ed 628 "Camera color format not supported: %d\n",
237e0265 629 fimc->vid_cap.mf.code);
5f3cc447
SN
630 return -EINVAL;
631 }
632
633 if (cam->bus_type == FIMC_ITU_601) {
3d0ce7ed 634 if (bus_width == 8)
5f3cc447 635 cfg |= S5P_CISRCFMT_ITU601_8BIT;
3d0ce7ed 636 else if (bus_width == 16)
5f3cc447 637 cfg |= S5P_CISRCFMT_ITU601_16BIT;
5f3cc447 638 } /* else defaults to ITU-R BT.656 8-bit */
ee7160e5
SN
639 } else if (cam->bus_type == FIMC_MIPI_CSI2) {
640 if (fimc_fmt_is_jpeg(f->fmt->color))
641 cfg |= S5P_CISRCFMT_ITU601_8BIT;
5f3cc447
SN
642 }
643
644 cfg |= S5P_CISRCFMT_HSIZE(f->o_width) | S5P_CISRCFMT_VSIZE(f->o_height);
645 writel(cfg, fimc->regs + S5P_CISRCFMT);
646 return 0;
647}
648
649
650int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
651{
652 u32 hoff2, voff2;
653
654 u32 cfg = readl(fimc->regs + S5P_CIWDOFST);
655
656 cfg &= ~(S5P_CIWDOFST_HOROFF_MASK | S5P_CIWDOFST_VEROFF_MASK);
657 cfg |= S5P_CIWDOFST_OFF_EN |
658 S5P_CIWDOFST_HOROFF(f->offs_h) |
659 S5P_CIWDOFST_VEROFF(f->offs_v);
660
661 writel(cfg, fimc->regs + S5P_CIWDOFST);
662
663 /* See CIWDOFSTn register description in the datasheet for details. */
664 hoff2 = f->o_width - f->width - f->offs_h;
665 voff2 = f->o_height - f->height - f->offs_v;
666 cfg = S5P_CIWDOFST2_HOROFF(hoff2) | S5P_CIWDOFST2_VEROFF(voff2);
667
668 writel(cfg, fimc->regs + S5P_CIWDOFST2);
669 return 0;
670}
671
672int fimc_hw_set_camera_type(struct fimc_dev *fimc,
df7e09a3 673 struct s5p_fimc_isp_info *cam)
5f3cc447
SN
674{
675 u32 cfg, tmp;
676 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
677
678 cfg = readl(fimc->regs + S5P_CIGCTRL);
679
680 /* Select ITU B interface, disable Writeback path and test pattern. */
681 cfg &= ~(S5P_CIGCTRL_TESTPAT_MASK | S5P_CIGCTRL_SELCAM_ITU_A |
682 S5P_CIGCTRL_SELCAM_MIPI | S5P_CIGCTRL_CAMIF_SELWB |
ee7160e5 683 S5P_CIGCTRL_SELCAM_MIPI_A | S5P_CIGCTRL_CAM_JPEG);
5f3cc447
SN
684
685 if (cam->bus_type == FIMC_MIPI_CSI2) {
686 cfg |= S5P_CIGCTRL_SELCAM_MIPI;
687
688 if (cam->mux_id == 0)
689 cfg |= S5P_CIGCTRL_SELCAM_MIPI_A;
690
691 /* TODO: add remaining supported formats. */
ee7160e5
SN
692 switch (vid_cap->mf.code) {
693 case V4L2_MBUS_FMT_VYUY8_2X8:
5f3cc447 694 tmp = S5P_CSIIMGFMT_YCBCR422_8BIT;
ee7160e5
SN
695 break;
696 case V4L2_MBUS_FMT_JPEG_1X8:
697 tmp = S5P_CSIIMGFMT_USER(1);
698 cfg |= S5P_CIGCTRL_CAM_JPEG;
699 break;
700 default:
30c9939d
SN
701 v4l2_err(fimc->vid_cap.vfd,
702 "Not supported camera pixel format: %d",
237e0265 703 vid_cap->mf.code);
5f3cc447
SN
704 return -EINVAL;
705 }
e0eec9af
SN
706 tmp |= (cam->csi_data_align == 32) << 8;
707
708 writel(tmp, fimc->regs + S5P_CSIIMGFMT);
5f3cc447
SN
709
710 } else if (cam->bus_type == FIMC_ITU_601 ||
e0eec9af 711 cam->bus_type == FIMC_ITU_656) {
5f3cc447
SN
712 if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
713 cfg |= S5P_CIGCTRL_SELCAM_ITU_A;
714 } else if (cam->bus_type == FIMC_LCD_WB) {
715 cfg |= S5P_CIGCTRL_CAMIF_SELWB;
716 } else {
717 err("invalid camera bus type selected\n");
718 return -EINVAL;
719 }
720 writel(cfg, fimc->regs + S5P_CIGCTRL);
721
722 return 0;
723}
This page took 0.175652 seconds and 5 git commands to generate.