Commit | Line | Data |
---|---|---|
9a761e43 SN |
1 | /* |
2 | * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver | |
3 | * | |
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | |
5 | * | |
6 | * Authors: Younghwan Joo <yhwan.joo@samsung.com> | |
7 | * Sylwester Nawrocki <s.nawrocki@samsung.com> | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License version 2 as | |
11 | * published by the Free Software Foundation. | |
12 | */ | |
13 | #ifndef FIMC_IS_H_ | |
14 | #define FIMC_IS_H_ | |
15 | ||
16 | #include <asm/barrier.h> | |
17 | #include <linux/clk.h> | |
18 | #include <linux/device.h> | |
19 | #include <linux/kernel.h> | |
20 | #include <linux/pinctrl/consumer.h> | |
21 | #include <linux/platform_device.h> | |
22 | #include <linux/sizes.h> | |
23 | #include <linux/spinlock.h> | |
24 | #include <linux/types.h> | |
c139990e | 25 | #include <media/videobuf2-v4l2.h> |
9a761e43 SN |
26 | #include <media/v4l2-ctrls.h> |
27 | ||
28 | #include "fimc-isp.h" | |
29 | #include "fimc-is-command.h" | |
30 | #include "fimc-is-sensor.h" | |
31 | #include "fimc-is-param.h" | |
32 | #include "fimc-is-regs.h" | |
33 | ||
34 | #define FIMC_IS_DRV_NAME "exynos4-fimc-is" | |
35 | ||
72f2a768 SN |
36 | #define FIMC_IS_FW_FILENAME "exynos4_fimc_is_fw.bin" |
37 | #define FIMC_IS_SETFILE_6A3 "exynos4_s5k6a3_setfile.bin" | |
9a761e43 SN |
38 | |
39 | #define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */ | |
40 | #define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */ | |
41 | ||
d265d9ac | 42 | #define FIMC_IS_SENSORS_NUM 2 |
9a761e43 SN |
43 | |
44 | /* Memory definitions */ | |
45 | #define FIMC_IS_CPU_MEM_SIZE (0xa00000) | |
46 | #define FIMC_IS_CPU_BASE_MASK ((1 << 26) - 1) | |
47 | #define FIMC_IS_REGION_SIZE 0x5000 | |
48 | ||
49 | #define FIMC_IS_DEBUG_REGION_OFFSET 0x0084b000 | |
50 | #define FIMC_IS_SHARED_REGION_OFFSET 0x008c0000 | |
51 | #define FIMC_IS_FW_INFO_LEN 31 | |
52 | #define FIMC_IS_FW_VER_LEN 7 | |
53 | #define FIMC_IS_FW_DESC_LEN (FIMC_IS_FW_INFO_LEN + \ | |
54 | FIMC_IS_FW_VER_LEN) | |
55 | #define FIMC_IS_SETFILE_INFO_LEN 39 | |
56 | ||
57 | #define FIMC_IS_EXTRA_MEM_SIZE (FIMC_IS_EXTRA_FW_SIZE + \ | |
58 | FIMC_IS_EXTRA_SETFILE_SIZE + 0x1000) | |
59 | #define FIMC_IS_EXTRA_FW_SIZE 0x180000 | |
60 | #define FIMC_IS_EXTRA_SETFILE_SIZE 0x4b000 | |
61 | ||
62 | /* TODO: revisit */ | |
63 | #define FIMC_IS_FW_ADDR_MASK ((1 << 26) - 1) | |
64 | #define FIMC_IS_FW_SIZE_MAX (SZ_4M) | |
65 | #define FIMC_IS_FW_SIZE_MIN (SZ_32K) | |
66 | ||
67 | #define ATCLK_MCUISP_FREQUENCY 100000000UL | |
68 | #define ACLK_AXI_FREQUENCY 100000000UL | |
69 | ||
70 | enum { | |
71 | ISS_CLK_PPMUISPX, | |
72 | ISS_CLK_PPMUISPMX, | |
73 | ISS_CLK_LITE0, | |
74 | ISS_CLK_LITE1, | |
75 | ISS_CLK_MPLL, | |
9a761e43 SN |
76 | ISS_CLK_ISP, |
77 | ISS_CLK_DRC, | |
78 | ISS_CLK_FD, | |
79 | ISS_CLK_MCUISP, | |
80 | ISS_CLK_UART, | |
81 | ISS_GATE_CLKS_MAX, | |
82 | ISS_CLK_ISP_DIV0 = ISS_GATE_CLKS_MAX, | |
83 | ISS_CLK_ISP_DIV1, | |
84 | ISS_CLK_MCUISP_DIV0, | |
85 | ISS_CLK_MCUISP_DIV1, | |
86 | ISS_CLK_ACLK200, | |
87 | ISS_CLK_ACLK200_DIV, | |
88 | ISS_CLK_ACLK400MCUISP, | |
89 | ISS_CLK_ACLK400MCUISP_DIV, | |
90 | ISS_CLKS_MAX | |
91 | }; | |
92 | ||
93 | /* The driver's internal state flags */ | |
94 | enum { | |
95 | IS_ST_IDLE, | |
96 | IS_ST_PWR_ON, | |
97 | IS_ST_A5_PWR_ON, | |
98 | IS_ST_FW_LOADED, | |
99 | IS_ST_OPEN_SENSOR, | |
100 | IS_ST_SETFILE_LOADED, | |
101 | IS_ST_INIT_DONE, | |
102 | IS_ST_STREAM_ON, | |
103 | IS_ST_STREAM_OFF, | |
104 | IS_ST_CHANGE_MODE, | |
105 | IS_ST_BLOCK_CMD_CLEARED, | |
106 | IS_ST_SET_ZOOM, | |
107 | IS_ST_PWR_SUBIP_ON, | |
108 | IS_ST_END, | |
109 | }; | |
110 | ||
111 | enum af_state { | |
112 | FIMC_IS_AF_IDLE = 0, | |
113 | FIMC_IS_AF_SETCONFIG = 1, | |
114 | FIMC_IS_AF_RUNNING = 2, | |
115 | FIMC_IS_AF_LOCK = 3, | |
116 | FIMC_IS_AF_ABORT = 4, | |
117 | FIMC_IS_AF_FAILED = 5, | |
118 | }; | |
119 | ||
120 | enum af_lock_state { | |
121 | FIMC_IS_AF_UNLOCKED = 0, | |
122 | FIMC_IS_AF_LOCKED = 2 | |
123 | }; | |
124 | ||
125 | enum ae_lock_state { | |
126 | FIMC_IS_AE_UNLOCKED = 0, | |
127 | FIMC_IS_AE_LOCKED = 1 | |
128 | }; | |
129 | ||
130 | enum awb_lock_state { | |
131 | FIMC_IS_AWB_UNLOCKED = 0, | |
132 | FIMC_IS_AWB_LOCKED = 1 | |
133 | }; | |
134 | ||
135 | enum { | |
136 | IS_METERING_CONFIG_CMD, | |
137 | IS_METERING_CONFIG_WIN_POS_X, | |
138 | IS_METERING_CONFIG_WIN_POS_Y, | |
139 | IS_METERING_CONFIG_WIN_WIDTH, | |
140 | IS_METERING_CONFIG_WIN_HEIGHT, | |
141 | IS_METERING_CONFIG_MAX | |
142 | }; | |
143 | ||
144 | struct is_setfile { | |
145 | const struct firmware *info; | |
146 | int state; | |
147 | u32 sub_index; | |
148 | u32 base; | |
149 | size_t size; | |
150 | }; | |
151 | ||
152 | struct is_fd_result_header { | |
153 | u32 offset; | |
154 | u32 count; | |
155 | u32 index; | |
156 | u32 curr_index; | |
157 | u32 width; | |
158 | u32 height; | |
159 | }; | |
160 | ||
161 | struct is_af_info { | |
162 | u16 mode; | |
163 | u32 af_state; | |
164 | u32 af_lock_state; | |
165 | u32 ae_lock_state; | |
166 | u32 awb_lock_state; | |
167 | u16 pos_x; | |
168 | u16 pos_y; | |
169 | u16 prev_pos_x; | |
170 | u16 prev_pos_y; | |
171 | u16 use_af; | |
172 | }; | |
173 | ||
174 | struct fimc_is_firmware { | |
175 | const struct firmware *f_w; | |
176 | ||
177 | dma_addr_t paddr; | |
178 | void *vaddr; | |
179 | unsigned int size; | |
180 | ||
181 | char info[FIMC_IS_FW_INFO_LEN + 1]; | |
182 | char version[FIMC_IS_FW_VER_LEN + 1]; | |
183 | char setfile_info[FIMC_IS_SETFILE_INFO_LEN + 1]; | |
184 | u8 state; | |
185 | }; | |
186 | ||
187 | struct fimc_is_memory { | |
188 | /* physical base address */ | |
189 | dma_addr_t paddr; | |
190 | /* virtual base address */ | |
191 | void *vaddr; | |
192 | /* total length */ | |
193 | unsigned int size; | |
194 | }; | |
195 | ||
196 | #define FIMC_IS_I2H_MAX_ARGS 12 | |
197 | ||
198 | struct i2h_cmd { | |
199 | u32 cmd; | |
200 | u32 sensor_id; | |
201 | u16 num_args; | |
202 | u32 args[FIMC_IS_I2H_MAX_ARGS]; | |
203 | }; | |
204 | ||
205 | struct h2i_cmd { | |
206 | u16 cmd_type; | |
207 | u32 entry_id; | |
208 | }; | |
209 | ||
210 | #define FIMC_IS_DEBUG_MSG 0x3f | |
211 | #define FIMC_IS_DEBUG_LEVEL 3 | |
212 | ||
213 | struct fimc_is_setfile { | |
214 | const struct firmware *info; | |
215 | unsigned int state; | |
216 | unsigned int size; | |
217 | u32 sub_index; | |
218 | u32 base; | |
219 | }; | |
220 | ||
3530ef0a | 221 | struct chain_config { |
9a761e43 SN |
222 | struct global_param global; |
223 | struct sensor_param sensor; | |
224 | struct isp_param isp; | |
225 | struct drc_param drc; | |
226 | struct fd_param fd; | |
227 | ||
0e761b21 | 228 | unsigned long p_region_index[2]; |
9a761e43 SN |
229 | }; |
230 | ||
231 | /** | |
232 | * struct fimc_is - fimc-is data structure | |
233 | * @pdev: pointer to FIMC-IS platform device | |
234 | * @pctrl: pointer to pinctrl structure for this device | |
235 | * @v4l2_dev: pointer to top the level v4l2_device | |
236 | * @alloc_ctx: videobuf2 memory allocator context | |
237 | * @lock: mutex serializing video device and the subdev operations | |
238 | * @slock: spinlock protecting this data structure and the hw registers | |
239 | * @clocks: FIMC-LITE gate clock | |
240 | * @regs: MCUCTL mmapped registers region | |
241 | * @pmu_regs: PMU ISP mmapped registers region | |
242 | * @irq_queue: interrupt handling waitqueue | |
243 | * @lpm: low power mode flag | |
244 | * @state: internal driver's state flags | |
245 | */ | |
246 | struct fimc_is { | |
247 | struct platform_device *pdev; | |
248 | struct pinctrl *pctrl; | |
249 | struct v4l2_device *v4l2_dev; | |
250 | ||
251 | struct fimc_is_firmware fw; | |
252 | struct fimc_is_memory memory; | |
253 | struct firmware *f_w; | |
254 | ||
255 | struct fimc_isp isp; | |
d265d9ac | 256 | struct fimc_is_sensor sensor[FIMC_IS_SENSORS_NUM]; |
9a761e43 SN |
257 | struct fimc_is_setfile setfile; |
258 | ||
259 | struct vb2_alloc_ctx *alloc_ctx; | |
260 | struct v4l2_ctrl_handler ctrl_handler; | |
261 | ||
262 | struct mutex lock; | |
263 | spinlock_t slock; | |
264 | ||
265 | struct clk *clocks[ISS_CLKS_MAX]; | |
9a761e43 SN |
266 | void __iomem *regs; |
267 | void __iomem *pmu_regs; | |
268 | int irq; | |
269 | wait_queue_head_t irq_queue; | |
270 | u8 lpm; | |
271 | ||
272 | unsigned long state; | |
273 | unsigned int sensor_index; | |
274 | ||
275 | struct i2h_cmd i2h_cmd; | |
276 | struct h2i_cmd h2i_cmd; | |
277 | struct is_fd_result_header fd_header; | |
278 | ||
3530ef0a SN |
279 | struct chain_config config[IS_SC_MAX]; |
280 | unsigned config_index; | |
281 | ||
9a761e43 SN |
282 | struct is_region *is_p_region; |
283 | dma_addr_t is_dma_p_region; | |
284 | struct is_share_region *is_shared_region; | |
285 | struct is_af_info af; | |
9a761e43 SN |
286 | |
287 | struct dentry *debugfs_entry; | |
288 | }; | |
289 | ||
290 | static inline struct fimc_is *fimc_isp_to_is(struct fimc_isp *isp) | |
291 | { | |
292 | return container_of(isp, struct fimc_is, isp); | |
293 | } | |
294 | ||
34947b8a SN |
295 | static inline struct chain_config *__get_curr_is_config(struct fimc_is *is) |
296 | { | |
297 | return &is->config[is->config_index]; | |
298 | } | |
299 | ||
9a761e43 SN |
300 | static inline void fimc_is_mem_barrier(void) |
301 | { | |
302 | mb(); | |
303 | } | |
304 | ||
305 | static inline void fimc_is_set_param_bit(struct fimc_is *is, int num) | |
306 | { | |
3530ef0a | 307 | struct chain_config *cfg = &is->config[is->config_index]; |
9a761e43 | 308 | |
0e761b21 | 309 | set_bit(num, &cfg->p_region_index[0]); |
9a761e43 SN |
310 | } |
311 | ||
312 | static inline void fimc_is_set_param_ctrl_cmd(struct fimc_is *is, int cmd) | |
313 | { | |
314 | is->is_p_region->parameter.isp.control.cmd = cmd; | |
315 | } | |
316 | ||
317 | static inline void mcuctl_write(u32 v, struct fimc_is *is, unsigned int offset) | |
318 | { | |
319 | writel(v, is->regs + offset); | |
320 | } | |
321 | ||
322 | static inline u32 mcuctl_read(struct fimc_is *is, unsigned int offset) | |
323 | { | |
324 | return readl(is->regs + offset); | |
325 | } | |
326 | ||
327 | static inline void pmuisp_write(u32 v, struct fimc_is *is, unsigned int offset) | |
328 | { | |
329 | writel(v, is->pmu_regs + offset); | |
330 | } | |
331 | ||
332 | static inline u32 pmuisp_read(struct fimc_is *is, unsigned int offset) | |
333 | { | |
334 | return readl(is->pmu_regs + offset); | |
335 | } | |
336 | ||
337 | int fimc_is_wait_event(struct fimc_is *is, unsigned long bit, | |
338 | unsigned int state, unsigned int timeout); | |
339 | int fimc_is_cpu_set_power(struct fimc_is *is, int on); | |
340 | int fimc_is_start_firmware(struct fimc_is *is); | |
341 | int fimc_is_hw_initialize(struct fimc_is *is); | |
342 | void fimc_is_log_dump(const char *level, const void *buf, size_t len); | |
343 | ||
344 | #endif /* FIMC_IS_H_ */ |