~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/media/video/s5p-fimc/fimc-reg.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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>
 
16
#include <media/s3c_fimc.h>
 
17
 
 
18
#include "fimc-core.h"
 
19
 
 
20
 
 
21
void 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);
 
33
        udelay(1000);
 
34
 
 
35
        cfg = readl(dev->regs + S5P_CIGCTRL);
 
36
        cfg &= ~S5P_CIGCTRL_SWRST;
 
37
        writel(cfg, dev->regs + S5P_CIGCTRL);
 
38
}
 
39
 
 
40
static u32 fimc_hw_get_in_flip(u32 ctx_flip)
 
41
{
 
42
        u32 flip = S5P_MSCTRL_FLIP_NORMAL;
 
43
 
 
44
        switch (ctx_flip) {
 
45
        case FLIP_X_AXIS:
 
46
                flip = S5P_MSCTRL_FLIP_X_MIRROR;
 
47
                break;
 
48
        case FLIP_Y_AXIS:
 
49
                flip = S5P_MSCTRL_FLIP_Y_MIRROR;
 
50
                break;
 
51
        case FLIP_XY_AXIS:
 
52
                flip = S5P_MSCTRL_FLIP_180;
 
53
                break;
 
54
        }
 
55
 
 
56
        return flip;
 
57
}
 
58
 
 
59
static u32 fimc_hw_get_target_flip(u32 ctx_flip)
 
60
{
 
61
        u32 flip = S5P_CITRGFMT_FLIP_NORMAL;
 
62
 
 
63
        switch (ctx_flip) {
 
64
        case FLIP_X_AXIS:
 
65
                flip = S5P_CITRGFMT_FLIP_X_MIRROR;
 
66
                break;
 
67
        case FLIP_Y_AXIS:
 
68
                flip = S5P_CITRGFMT_FLIP_Y_MIRROR;
 
69
                break;
 
70
        case FLIP_XY_AXIS:
 
71
                flip = S5P_CITRGFMT_FLIP_180;
 
72
                break;
 
73
        case FLIP_NONE:
 
74
                break;
 
75
 
 
76
        }
 
77
        return flip;
 
78
}
 
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
 
 
120
void fimc_hw_set_target_format(struct fimc_ctx *ctx)
 
121
{
 
122
        u32 cfg;
 
123
        struct fimc_dev *dev = ctx->fimc_dev;
 
124
        struct fimc_frame *frame = &ctx->d_frame;
 
125
 
 
126
        dbg("w= %d, h= %d color: %d", frame->width,
 
127
                frame->height, frame->fmt->color);
 
128
 
 
129
        cfg = readl(dev->regs + S5P_CITRGFMT);
 
130
        cfg &= ~(S5P_CITRGFMT_FMT_MASK | S5P_CITRGFMT_HSIZE_MASK |
 
131
                  S5P_CITRGFMT_VSIZE_MASK);
 
132
 
 
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;
 
138
                break;
 
139
        case S5P_FIMC_YCBCR420:
 
140
                cfg |= S5P_CITRGFMT_YCBCR420;
 
141
                break;
 
142
        case S5P_FIMC_YCBYCR422:
 
143
        case S5P_FIMC_YCRYCB422:
 
144
        case S5P_FIMC_CBYCRY422:
 
145
        case S5P_FIMC_CRYCBY422:
 
146
                if (frame->fmt->planes_cnt == 1)
 
147
                        cfg |= S5P_CITRGFMT_YCBCR422_1P;
 
148
                else
 
149
                        cfg |= S5P_CITRGFMT_YCBCR422;
 
150
                break;
 
151
        default:
 
152
                break;
 
153
        }
 
154
 
 
155
        if (ctx->rotation == 90 || ctx->rotation == 270) {
 
156
                cfg |= S5P_CITRGFMT_HSIZE(frame->height);
 
157
                cfg |= S5P_CITRGFMT_VSIZE(frame->width);
 
158
        } else {
 
159
 
 
160
                cfg |= S5P_CITRGFMT_HSIZE(frame->width);
 
161
                cfg |= S5P_CITRGFMT_VSIZE(frame->height);
 
162
        }
 
163
 
 
164
        writel(cfg, dev->regs + S5P_CITRGFMT);
 
165
 
 
166
        cfg = readl(dev->regs + S5P_CITAREA) & ~S5P_CITAREA_MASK;
 
167
        cfg |= (frame->width * frame->height);
 
168
        writel(cfg, dev->regs + S5P_CITAREA);
 
169
}
 
170
 
 
171
static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
 
172
{
 
173
        struct fimc_dev *dev = ctx->fimc_dev;
 
174
        struct fimc_frame *frame = &ctx->d_frame;
 
175
        u32 cfg;
 
176
 
 
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);
 
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
 
 
189
}
 
190
 
 
191
void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
 
192
{
 
193
        u32 cfg;
 
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;
 
197
 
 
198
        /* Set the input dma offsets. */
 
199
        cfg = 0;
 
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);
 
203
 
 
204
        cfg = 0;
 
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);
 
208
 
 
209
        cfg = 0;
 
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);
 
213
 
 
214
        fimc_hw_set_out_dma_size(ctx);
 
215
 
 
216
        /* Configure chroma components order. */
 
217
        cfg = readl(dev->regs + S5P_CIOCTRL);
 
218
 
 
219
        cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
 
220
                 S5P_CIOCTRL_YCBCR_PLANE_MASK);
 
221
 
 
222
        if (frame->fmt->planes_cnt == 1)
 
223
                cfg |= ctx->out_order_1p;
 
224
        else if (frame->fmt->planes_cnt == 2)
 
225
                cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE;
 
226
        else if (frame->fmt->planes_cnt == 3)
 
227
                cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
 
228
 
 
229
        writel(cfg, dev->regs + S5P_CIOCTRL);
 
230
}
 
231
 
 
232
static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
 
233
{
 
234
        u32 cfg = readl(dev->regs + S5P_ORGISIZE);
 
235
        if (enable)
 
236
                cfg |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
 
237
        else
 
238
                cfg &= ~S5P_CIREAL_ISIZE_AUTOLOAD_EN;
 
239
        writel(cfg, dev->regs + S5P_ORGISIZE);
 
240
}
 
241
 
 
242
void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
 
243
{
 
244
        u32 cfg = readl(dev->regs + S5P_CIOCTRL);
 
245
        if (enable)
 
246
                cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE;
 
247
        else
 
248
                cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE;
 
249
        writel(cfg, dev->regs + S5P_CIOCTRL);
 
250
}
 
251
 
 
252
static void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
 
253
{
 
254
        struct fimc_dev *dev =  ctx->fimc_dev;
 
255
        struct fimc_scaler *sc = &ctx->scaler;
 
256
        u32 cfg, shfactor;
 
257
 
 
258
        shfactor = 10 - (sc->hfactor + sc->vfactor);
 
259
 
 
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);
 
264
 
 
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);
 
268
}
 
269
 
 
270
void fimc_hw_set_scaler(struct fimc_ctx *ctx)
 
271
{
 
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;
 
276
        u32 cfg = 0;
 
277
 
 
278
        fimc_hw_set_prescaler(ctx);
 
279
 
 
280
        if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
 
281
                cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
 
282
 
 
283
        if (!sc->enabled)
 
284
                cfg |= S5P_CISCCTRL_SCALERBYPASS;
 
285
 
 
286
        if (sc->scaleup_h)
 
287
                cfg |= S5P_CISCCTRL_SCALEUP_H;
 
288
 
 
289
        if (sc->scaleup_v)
 
290
                cfg |= S5P_CISCCTRL_SCALEUP_V;
 
291
 
 
292
        if (sc->copy_mode)
 
293
                cfg |= S5P_CISCCTRL_ONE2ONE;
 
294
 
 
295
 
 
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;
 
303
        }
 
304
 
 
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;
 
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
 
 
319
        dbg("main_hratio= 0x%X  main_vratio= 0x%X",
 
320
                sc->main_hratio, sc->main_vratio);
 
321
 
 
322
        cfg |= S5P_CISCCTRL_SC_HORRATIO(sc->main_hratio);
 
323
        cfg |= S5P_CISCCTRL_SC_VERRATIO(sc->main_vratio);
 
324
 
 
325
        writel(cfg, dev->regs + S5P_CISCCTRL);
 
326
}
 
327
 
 
328
void fimc_hw_en_capture(struct fimc_ctx *ctx)
 
329
{
 
330
        struct fimc_dev *dev = ctx->fimc_dev;
 
331
 
 
332
        u32 cfg = readl(dev->regs + S5P_CIIMGCPT);
 
333
 
 
334
        if (ctx->out_path == FIMC_DMA) {
 
335
                /* one shot mode */
 
336
                cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN;
 
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
        }
 
343
 
 
344
        if (ctx->scaler.enabled)
 
345
                cfg |= S5P_CIIMGCPT_IMGCPTEN_SC;
 
346
 
 
347
        writel(cfg | S5P_CIIMGCPT_IMGCPTEN, dev->regs + S5P_CIIMGCPT);
 
348
}
 
349
 
 
350
void fimc_hw_set_effect(struct fimc_ctx *ctx)
 
351
{
 
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);
 
355
 
 
356
        cfg |= effect->type;
 
357
 
 
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);
 
361
        }
 
362
 
 
363
        writel(cfg, dev->regs + S5P_CIIMGEFF);
 
364
}
 
365
 
 
366
static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
 
367
{
 
368
        struct fimc_dev *dev = ctx->fimc_dev;
 
369
        struct fimc_frame *frame = &ctx->s_frame;
 
370
        u32 cfg_o = 0;
 
371
        u32 cfg_r = 0;
 
372
 
 
373
        if (FIMC_LCDFIFO == ctx->out_path)
 
374
                cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
 
375
 
 
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);
 
380
 
 
381
        writel(cfg_o, dev->regs + S5P_ORGISIZE);
 
382
        writel(cfg_r, dev->regs + S5P_CIREAL_ISIZE);
 
383
}
 
384
 
 
385
void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
 
386
{
 
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;
 
390
        u32 cfg;
 
391
 
 
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);
 
396
 
 
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);
 
400
 
 
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);
 
404
 
 
405
        /* Input original and real size. */
 
406
        fimc_hw_set_in_dma_size(ctx);
 
407
 
 
408
        /* Use DMA autoload only in FIFO mode. */
 
409
        fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO);
 
410
 
 
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);
 
419
 
 
420
        cfg |= (S5P_MSCTRL_FRAME_COUNT(1) | S5P_MSCTRL_INPUT_MEMORY);
 
421
 
 
422
        switch (frame->fmt->color) {
 
423
        case S5P_FIMC_RGB565:
 
424
        case S5P_FIMC_RGB666:
 
425
        case S5P_FIMC_RGB888:
 
426
                cfg |= S5P_MSCTRL_INFORMAT_RGB;
 
427
                break;
 
428
        case S5P_FIMC_YCBCR420:
 
429
                cfg |= S5P_MSCTRL_INFORMAT_YCBCR420;
 
430
 
 
431
                if (frame->fmt->planes_cnt == 2)
 
432
                        cfg |= ctx->in_order_2p | S5P_MSCTRL_C_INT_IN_2PLANE;
 
433
                else
 
434
                        cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
 
435
 
 
436
                break;
 
437
        case S5P_FIMC_YCBYCR422:
 
438
        case S5P_FIMC_YCRYCB422:
 
439
        case S5P_FIMC_CBYCRY422:
 
440
        case S5P_FIMC_CRYCBY422:
 
441
                if (frame->fmt->planes_cnt == 1) {
 
442
                        cfg |= ctx->in_order_1p
 
443
                                | S5P_MSCTRL_INFORMAT_YCBCR422_1P;
 
444
                } else {
 
445
                        cfg |= S5P_MSCTRL_INFORMAT_YCBCR422;
 
446
 
 
447
                        if (frame->fmt->planes_cnt == 2)
 
448
                                cfg |= ctx->in_order_2p
 
449
                                        | S5P_MSCTRL_C_INT_IN_2PLANE;
 
450
                        else
 
451
                                cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
 
452
                }
 
453
                break;
 
454
        default:
 
455
                break;
 
456
        }
 
457
 
 
458
        /*
 
459
         * Input DMA flip mode (and rotation).
 
460
         * Do not allow simultaneous rotation and flipping.
 
461
         */
 
462
        if (!ctx->rotation && ctx->out_path == FIMC_LCDFIFO)
 
463
                cfg |= fimc_hw_get_in_flip(ctx->flip);
 
464
 
 
465
        writel(cfg, dev->regs + S5P_MSCTRL);
 
466
 
 
467
        /* Input/output DMA linear/tiled mode. */
 
468
        cfg = readl(dev->regs + S5P_CIDMAPARAM);
 
469
        cfg &= ~S5P_CIDMAPARAM_TILE_MASK;
 
470
 
 
471
        if (tiled_fmt(ctx->s_frame.fmt))
 
472
                cfg |= S5P_CIDMAPARAM_R_64X32;
 
473
 
 
474
        if (tiled_fmt(ctx->d_frame.fmt))
 
475
                cfg |= S5P_CIDMAPARAM_W_64X32;
 
476
 
 
477
        writel(cfg, dev->regs + S5P_CIDMAPARAM);
 
478
}
 
479
 
 
480
 
 
481
void fimc_hw_set_input_path(struct fimc_ctx *ctx)
 
482
{
 
483
        struct fimc_dev *dev = ctx->fimc_dev;
 
484
 
 
485
        u32 cfg = readl(dev->regs + S5P_MSCTRL);
 
486
        cfg &= ~S5P_MSCTRL_INPUT_MASK;
 
487
 
 
488
        if (ctx->in_path == FIMC_DMA)
 
489
                cfg |= S5P_MSCTRL_INPUT_MEMORY;
 
490
        else
 
491
                cfg |= S5P_MSCTRL_INPUT_EXTCAM;
 
492
 
 
493
        writel(cfg, dev->regs + S5P_MSCTRL);
 
494
}
 
495
 
 
496
void fimc_hw_set_output_path(struct fimc_ctx *ctx)
 
497
{
 
498
        struct fimc_dev *dev = ctx->fimc_dev;
 
499
 
 
500
        u32 cfg = readl(dev->regs + S5P_CISCCTRL);
 
501
        cfg &= ~S5P_CISCCTRL_LCDPATHEN_FIFO;
 
502
        if (ctx->out_path == FIMC_LCDFIFO)
 
503
                cfg |= S5P_CISCCTRL_LCDPATHEN_FIFO;
 
504
        writel(cfg, dev->regs + S5P_CISCCTRL);
 
505
}
 
506
 
 
507
void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
 
508
{
 
509
        u32 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
 
510
        cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS;
 
511
        writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
 
512
 
 
513
        writel(paddr->y, dev->regs + S5P_CIIYSA(0));
 
514
        writel(paddr->cb, dev->regs + S5P_CIICBSA(0));
 
515
        writel(paddr->cr, dev->regs + S5P_CIICRSA(0));
 
516
 
 
517
        cfg &= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS;
 
518
        writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
 
519
}
 
520
 
 
521
void fimc_hw_set_output_addr(struct fimc_dev *dev,
 
522
                             struct fimc_addr *paddr, int index)
 
523
{
 
524
        int i = (index == -1) ? 0 : index;
 
525
        do {
 
526
                writel(paddr->y, dev->regs + S5P_CIOYSA(i));
 
527
                writel(paddr->cb, dev->regs + S5P_CIOCBSA(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 */
 
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;
 
668
}