Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
media
platform
s5p-fimc
fimc-lite-reg.c
Go to the documentation of this file.
1
/*
2
* Register interface file for EXYNOS FIMC-LITE (camera interface) driver
3
*
4
* Copyright (C) 2012 Samsung Electronics Co., Ltd.
5
* Sylwester Nawrocki <
[email protected]
>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License version 2 as
9
* published by the Free Software Foundation.
10
*/
11
12
#include <
linux/io.h
>
13
#include <
linux/delay.h
>
14
#include <
media/s5p_fimc.h
>
15
16
#include "
fimc-lite-reg.h
"
17
#include "
fimc-lite.h
"
18
#include "
fimc-core.h
"
19
20
#define FLITE_RESET_TIMEOUT 50
/* in ms */
21
22
void
flite_hw_reset
(
struct
fimc_lite
*
dev
)
23
{
24
unsigned
long
end
=
jiffies
+
msecs_to_jiffies
(
FLITE_RESET_TIMEOUT
);
25
u32
cfg
;
26
27
cfg =
readl
(dev->
regs
+
FLITE_REG_CIGCTRL
);
28
cfg |=
FLITE_REG_CIGCTRL_SWRST_REQ
;
29
writel
(cfg, dev->
regs
+
FLITE_REG_CIGCTRL
);
30
31
while
(
time_is_after_jiffies
(end)) {
32
cfg =
readl
(dev->
regs
+
FLITE_REG_CIGCTRL
);
33
if
(cfg &
FLITE_REG_CIGCTRL_SWRST_RDY
)
34
break
;
35
usleep_range
(1000, 5000);
36
}
37
38
cfg |=
FLITE_REG_CIGCTRL_SWRST
;
39
writel
(cfg, dev->
regs
+
FLITE_REG_CIGCTRL
);
40
}
41
42
void
flite_hw_clear_pending_irq
(
struct
fimc_lite
*
dev
)
43
{
44
u32
cfg
=
readl
(dev->
regs
+
FLITE_REG_CISTATUS
);
45
cfg &= ~
FLITE_REG_CISTATUS_IRQ_CAM
;
46
writel
(cfg, dev->
regs
+
FLITE_REG_CISTATUS
);
47
}
48
49
u32
flite_hw_get_interrupt_source
(
struct
fimc_lite
*
dev
)
50
{
51
u32
intsrc =
readl
(dev->
regs
+
FLITE_REG_CISTATUS
);
52
return
intsrc &
FLITE_REG_CISTATUS_IRQ_MASK
;
53
}
54
55
void
flite_hw_clear_last_capture_end
(
struct
fimc_lite
*
dev
)
56
{
57
58
u32
cfg
=
readl
(dev->
regs
+
FLITE_REG_CISTATUS2
);
59
cfg &= ~
FLITE_REG_CISTATUS2_LASTCAPEND
;
60
writel
(cfg, dev->
regs
+
FLITE_REG_CISTATUS2
);
61
}
62
63
void
flite_hw_set_interrupt_mask
(
struct
fimc_lite
*
dev
)
64
{
65
u32
cfg
, intsrc;
66
67
/* Select interrupts to be enabled for each output mode */
68
if
(dev->
out_path
==
FIMC_IO_DMA
) {
69
intsrc =
FLITE_REG_CIGCTRL_IRQ_OVFEN
|
70
FLITE_REG_CIGCTRL_IRQ_LASTEN
|
71
FLITE_REG_CIGCTRL_IRQ_STARTEN
;
72
}
else
{
73
/* An output to the FIMC-IS */
74
intsrc =
FLITE_REG_CIGCTRL_IRQ_OVFEN
|
75
FLITE_REG_CIGCTRL_IRQ_LASTEN
;
76
}
77
78
cfg =
readl
(dev->
regs
+
FLITE_REG_CIGCTRL
);
79
cfg |=
FLITE_REG_CIGCTRL_IRQ_DISABLE_MASK
;
80
cfg &= ~intsrc;
81
writel
(cfg, dev->
regs
+
FLITE_REG_CIGCTRL
);
82
}
83
84
void
flite_hw_capture_start
(
struct
fimc_lite
*
dev
)
85
{
86
u32
cfg
=
readl
(dev->
regs
+
FLITE_REG_CIIMGCPT
);
87
cfg |=
FLITE_REG_CIIMGCPT_IMGCPTEN
;
88
writel
(cfg, dev->
regs
+
FLITE_REG_CIIMGCPT
);
89
}
90
91
void
flite_hw_capture_stop
(
struct
fimc_lite
*
dev
)
92
{
93
u32
cfg
=
readl
(dev->
regs
+
FLITE_REG_CIIMGCPT
);
94
cfg &= ~
FLITE_REG_CIIMGCPT_IMGCPTEN
;
95
writel
(cfg, dev->
regs
+
FLITE_REG_CIIMGCPT
);
96
}
97
98
/*
99
* Test pattern (color bars) enable/disable. External sensor
100
* pixel clock must be active for the test pattern to work.
101
*/
102
void
flite_hw_set_test_pattern
(
struct
fimc_lite
*
dev
,
bool
on)
103
{
104
u32
cfg
=
readl
(dev->
regs
+
FLITE_REG_CIGCTRL
);
105
if
(on)
106
cfg |=
FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR
;
107
else
108
cfg &= ~
FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR
;
109
writel
(cfg, dev->
regs
+
FLITE_REG_CIGCTRL
);
110
}
111
112
static
const
u32
src_pixfmt_map[8][3] = {
113
{
V4L2_MBUS_FMT_YUYV8_2X8
,
FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR
,
114
FLITE_REG_CIGCTRL_YUV422_1P
},
115
{
V4L2_MBUS_FMT_YVYU8_2X8
,
FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB
,
116
FLITE_REG_CIGCTRL_YUV422_1P
},
117
{
V4L2_MBUS_FMT_UYVY8_2X8
,
FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY
,
118
FLITE_REG_CIGCTRL_YUV422_1P
},
119
{
V4L2_MBUS_FMT_VYUY8_2X8
,
FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY
,
120
FLITE_REG_CIGCTRL_YUV422_1P
},
121
{
V4L2_MBUS_FMT_SGRBG8_1X8
, 0,
FLITE_REG_CIGCTRL_RAW8
},
122
{
V4L2_MBUS_FMT_SGRBG10_1X10
, 0,
FLITE_REG_CIGCTRL_RAW10
},
123
{
V4L2_MBUS_FMT_SGRBG12_1X12
, 0,
FLITE_REG_CIGCTRL_RAW12
},
124
{
V4L2_MBUS_FMT_JPEG_1X8
, 0,
FLITE_REG_CIGCTRL_USER
(1) },
125
};
126
127
/* Set camera input pixel format and resolution */
128
void
flite_hw_set_source_format
(
struct
fimc_lite
*
dev
,
struct
flite_frame
*
f
)
129
{
130
enum
v4l2_mbus_pixelcode
pixelcode = dev->
fmt
->mbus_code;
131
unsigned
int
i
=
ARRAY_SIZE
(src_pixfmt_map);
132
u32
cfg
;
133
134
while
(i-- >= 0) {
135
if
(src_pixfmt_map[i][0] == pixelcode)
136
break
;
137
}
138
139
if
(i == 0 && src_pixfmt_map[i][0] != pixelcode) {
140
v4l2_err
(&dev->
vfd
,
141
"Unsupported pixel code, falling back to %#08x\n"
,
142
src_pixfmt_map[i][0]);
143
}
144
145
cfg =
readl
(dev->
regs
+
FLITE_REG_CIGCTRL
);
146
cfg &= ~
FLITE_REG_CIGCTRL_FMT_MASK
;
147
cfg |= src_pixfmt_map[
i
][2];
148
writel
(cfg, dev->
regs
+
FLITE_REG_CIGCTRL
);
149
150
cfg =
readl
(dev->
regs
+
FLITE_REG_CISRCSIZE
);
151
cfg &= ~(
FLITE_REG_CISRCSIZE_ORDER422_MASK
|
152
FLITE_REG_CISRCSIZE_SIZE_CAM_MASK
);
153
cfg |= (f->
f_width
<< 16) | f->
f_height
;
154
cfg |= src_pixfmt_map[i][1];
155
writel
(cfg, dev->
regs
+
FLITE_REG_CISRCSIZE
);
156
}
157
158
/* Set the camera host input window offsets (cropping) */
159
void
flite_hw_set_window_offset
(
struct
fimc_lite
*
dev
,
struct
flite_frame
*
f
)
160
{
161
u32
hoff2, voff2;
162
u32
cfg
;
163
164
cfg =
readl
(dev->
regs
+
FLITE_REG_CIWDOFST
);
165
cfg &= ~
FLITE_REG_CIWDOFST_OFST_MASK
;
166
cfg |= (f->
rect
.left << 16) | f->
rect
.top;
167
cfg |=
FLITE_REG_CIWDOFST_WINOFSEN
;
168
writel
(cfg, dev->
regs
+
FLITE_REG_CIWDOFST
);
169
170
hoff2 = f->
f_width
- f->
rect
.width - f->
rect
.left;
171
voff2 = f->
f_height
- f->
rect
.height - f->
rect
.top;
172
173
cfg = (hoff2 << 16) | voff2;
174
writel
(cfg, dev->
regs
+
FLITE_REG_CIWDOFST2
);
175
}
176
177
/* Select camera port (A, B) */
178
static
void
flite_hw_set_camera_port(
struct
fimc_lite
*
dev
,
int
id
)
179
{
180
u32
cfg
=
readl
(dev->
regs
+
FLITE_REG_CIGENERAL
);
181
if
(
id
== 0)
182
cfg &= ~
FLITE_REG_CIGENERAL_CAM_B
;
183
else
184
cfg |=
FLITE_REG_CIGENERAL_CAM_B
;
185
writel
(cfg, dev->
regs
+
FLITE_REG_CIGENERAL
);
186
}
187
188
/* Select serial or parallel bus, camera port (A,B) and set signals polarity */
189
void
flite_hw_set_camera_bus
(
struct
fimc_lite
*dev,
190
struct
s5p_fimc_isp_info
*s_info)
191
{
192
u32
cfg =
readl
(dev->
regs
+
FLITE_REG_CIGCTRL
);
193
unsigned
int
flags
= s_info->
flags
;
194
195
if
(s_info->
bus_type
!=
FIMC_MIPI_CSI2
) {
196
cfg &= ~(
FLITE_REG_CIGCTRL_SELCAM_MIPI
|
197
FLITE_REG_CIGCTRL_INVPOLPCLK
|
198
FLITE_REG_CIGCTRL_INVPOLVSYNC
|
199
FLITE_REG_CIGCTRL_INVPOLHREF
);
200
201
if
(flags &
V4L2_MBUS_PCLK_SAMPLE_FALLING
)
202
cfg |=
FLITE_REG_CIGCTRL_INVPOLPCLK
;
203
204
if
(flags &
V4L2_MBUS_VSYNC_ACTIVE_LOW
)
205
cfg |=
FLITE_REG_CIGCTRL_INVPOLVSYNC
;
206
207
if
(flags &
V4L2_MBUS_HSYNC_ACTIVE_LOW
)
208
cfg |=
FLITE_REG_CIGCTRL_INVPOLHREF
;
209
}
else
{
210
cfg |=
FLITE_REG_CIGCTRL_SELCAM_MIPI
;
211
}
212
213
writel
(cfg, dev->
regs
+
FLITE_REG_CIGCTRL
);
214
215
flite_hw_set_camera_port(dev, s_info->
mux_id
);
216
}
217
218
static
void
flite_hw_set_out_order(
struct
fimc_lite
*dev,
struct
flite_frame
*
f
)
219
{
220
static
const
u32
pixcode[4][2] = {
221
{
V4L2_MBUS_FMT_YUYV8_2X8
,
FLITE_REG_CIODMAFMT_YCBYCR
},
222
{
V4L2_MBUS_FMT_YVYU8_2X8
,
FLITE_REG_CIODMAFMT_YCRYCB
},
223
{
V4L2_MBUS_FMT_UYVY8_2X8
,
FLITE_REG_CIODMAFMT_CBYCRY
},
224
{
V4L2_MBUS_FMT_VYUY8_2X8
,
FLITE_REG_CIODMAFMT_CRYCBY
},
225
};
226
u32
cfg =
readl
(dev->
regs
+
FLITE_REG_CIODMAFMT
);
227
unsigned
int
i
=
ARRAY_SIZE
(pixcode);
228
229
while
(i-- >= 0)
230
if
(pixcode[i][0] == dev->
fmt
->mbus_code)
231
break
;
232
cfg &= ~
FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK
;
233
writel
(cfg | pixcode[i][1], dev->
regs
+
FLITE_REG_CIODMAFMT
);
234
}
235
236
void
flite_hw_set_dma_window
(
struct
fimc_lite
*dev,
struct
flite_frame
*f)
237
{
238
u32
cfg
;
239
240
/* Maximum output pixel size */
241
cfg =
readl
(dev->
regs
+
FLITE_REG_CIOCAN
);
242
cfg &= ~
FLITE_REG_CIOCAN_MASK
;
243
cfg = (f->
f_height
<< 16) | f->
f_width
;
244
writel
(cfg, dev->
regs
+
FLITE_REG_CIOCAN
);
245
246
/* DMA offsets */
247
cfg =
readl
(dev->
regs
+
FLITE_REG_CIOOFF
);
248
cfg &= ~
FLITE_REG_CIOOFF_MASK
;
249
cfg |= (f->
rect
.top << 16) | f->
rect
.left;
250
writel
(cfg, dev->
regs
+
FLITE_REG_CIOOFF
);
251
}
252
253
/* Enable/disable output DMA, set output pixel size and offsets (composition) */
254
void
flite_hw_set_output_dma
(
struct
fimc_lite
*dev,
struct
flite_frame
*f,
255
bool
enable
)
256
{
257
u32
cfg =
readl
(dev->
regs
+
FLITE_REG_CIGCTRL
);
258
259
if
(!enable) {
260
cfg |=
FLITE_REG_CIGCTRL_ODMA_DISABLE
;
261
writel
(cfg, dev->
regs
+
FLITE_REG_CIGCTRL
);
262
return
;
263
}
264
265
cfg &= ~
FLITE_REG_CIGCTRL_ODMA_DISABLE
;
266
writel
(cfg, dev->
regs
+
FLITE_REG_CIGCTRL
);
267
268
flite_hw_set_out_order(dev, f);
269
flite_hw_set_dma_window
(dev, f);
270
}
271
272
void
flite_hw_dump_regs
(
struct
fimc_lite
*dev,
const
char
*
label
)
273
{
274
struct
{
275
u32
offset
;
276
const
char
*
const
name
;
277
}
registers
[] = {
278
{ 0x00,
"CISRCSIZE"
},
279
{ 0x04,
"CIGCTRL"
},
280
{ 0x08,
"CIIMGCPT"
},
281
{ 0x0c,
"CICPTSEQ"
},
282
{ 0x10,
"CIWDOFST"
},
283
{ 0x14,
"CIWDOFST2"
},
284
{ 0x18,
"CIODMAFMT"
},
285
{ 0x20,
"CIOCAN"
},
286
{ 0x24,
"CIOOFF"
},
287
{ 0x30,
"CIOSA"
},
288
{ 0x40,
"CISTATUS"
},
289
{ 0x44,
"CISTATUS2"
},
290
{ 0xf0,
"CITHOLD"
},
291
{ 0xfc,
"CIGENERAL"
},
292
};
293
u32
i
;
294
295
pr_info
(
"--- %s ---\n"
, label);
296
for
(i = 0; i <
ARRAY_SIZE
(
registers
); i++) {
297
u32
cfg =
readl
(dev->
regs
+
registers
[i].offset);
298
pr_info
(
"%s: %s:\t0x%08x\n"
, __func__,
registers
[i].
name
, cfg);
299
}
300
}
Generated on Thu Jan 10 2013 13:49:36 for Linux Kernel by
1.8.2