1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * isp.h |
4 | * |
5 | * TI OMAP3 ISP - Core |
6 | * |
7 | * Copyright (C) 2009-2010 Nokia Corporation |
8 | * Copyright (C) 2009 Texas Instruments, Inc. |
9 | * |
10 | * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
11 | * Sakari Ailus <sakari.ailus@iki.fi> |
12 | */ |
13 | |
14 | #ifndef OMAP3_ISP_CORE_H |
15 | #define OMAP3_ISP_CORE_H |
16 | |
17 | #include <media/media-entity.h> |
18 | #include <media/v4l2-async.h> |
19 | #include <media/v4l2-device.h> |
20 | #include <linux/clk-provider.h> |
21 | #include <linux/device.h> |
22 | #include <linux/io.h> |
23 | #include <linux/platform_device.h> |
24 | #include <linux/wait.h> |
25 | |
26 | #include "omap3isp.h" |
27 | #include "ispstat.h" |
28 | #include "ispccdc.h" |
29 | #include "ispreg.h" |
30 | #include "ispresizer.h" |
31 | #include "isppreview.h" |
32 | #include "ispcsiphy.h" |
33 | #include "ispcsi2.h" |
34 | #include "ispccp2.h" |
35 | |
36 | #define ISP_TOK_TERM 0xFFFFFFFF /* |
37 | * terminating token for ISP |
38 | * modules reg list |
39 | */ |
40 | #define to_isp_device(ptr_module) \ |
41 | container_of(ptr_module, struct isp_device, isp_##ptr_module) |
42 | #define to_device(ptr_module) \ |
43 | (to_isp_device(ptr_module)->dev) |
44 | |
45 | enum isp_mem_resources { |
46 | OMAP3_ISP_IOMEM_MAIN, |
47 | OMAP3_ISP_IOMEM_CCP2, |
48 | OMAP3_ISP_IOMEM_CCDC, |
49 | OMAP3_ISP_IOMEM_HIST, |
50 | OMAP3_ISP_IOMEM_H3A, |
51 | OMAP3_ISP_IOMEM_PREV, |
52 | OMAP3_ISP_IOMEM_RESZ, |
53 | OMAP3_ISP_IOMEM_SBL, |
54 | OMAP3_ISP_IOMEM_CSI2A_REGS1, |
55 | OMAP3_ISP_IOMEM_CSIPHY2, |
56 | OMAP3_ISP_IOMEM_CSI2A_REGS2, |
57 | OMAP3_ISP_IOMEM_CSI2C_REGS1, |
58 | OMAP3_ISP_IOMEM_CSIPHY1, |
59 | OMAP3_ISP_IOMEM_CSI2C_REGS2, |
60 | OMAP3_ISP_IOMEM_LAST |
61 | }; |
62 | |
63 | enum isp_sbl_resource { |
64 | OMAP3_ISP_SBL_CSI1_READ = 0x1, |
65 | OMAP3_ISP_SBL_CSI1_WRITE = 0x2, |
66 | OMAP3_ISP_SBL_CSI2A_WRITE = 0x4, |
67 | OMAP3_ISP_SBL_CSI2C_WRITE = 0x8, |
68 | OMAP3_ISP_SBL_CCDC_LSC_READ = 0x10, |
69 | OMAP3_ISP_SBL_CCDC_WRITE = 0x20, |
70 | OMAP3_ISP_SBL_PREVIEW_READ = 0x40, |
71 | OMAP3_ISP_SBL_PREVIEW_WRITE = 0x80, |
72 | OMAP3_ISP_SBL_RESIZER_READ = 0x100, |
73 | OMAP3_ISP_SBL_RESIZER_WRITE = 0x200, |
74 | }; |
75 | |
76 | enum isp_subclk_resource { |
77 | OMAP3_ISP_SUBCLK_CCDC = (1 << 0), |
78 | OMAP3_ISP_SUBCLK_AEWB = (1 << 1), |
79 | OMAP3_ISP_SUBCLK_AF = (1 << 2), |
80 | OMAP3_ISP_SUBCLK_HIST = (1 << 3), |
81 | OMAP3_ISP_SUBCLK_PREVIEW = (1 << 4), |
82 | OMAP3_ISP_SUBCLK_RESIZER = (1 << 5), |
83 | }; |
84 | |
85 | /* ISP: OMAP 34xx ES 1.0 */ |
86 | #define ISP_REVISION_1_0 0x10 |
87 | /* ISP2: OMAP 34xx ES 2.0, 2.1 and 3.0 */ |
88 | #define ISP_REVISION_2_0 0x20 |
89 | /* ISP2P: OMAP 36xx */ |
90 | #define ISP_REVISION_15_0 0xF0 |
91 | |
92 | #define ISP_PHY_TYPE_3430 0 |
93 | #define ISP_PHY_TYPE_3630 1 |
94 | |
95 | struct regmap; |
96 | |
97 | /* |
98 | * struct isp_res_mapping - Map ISP io resources to ISP revision. |
99 | * @isp_rev: ISP_REVISION_x_x |
100 | * @offset: register offsets of various ISP sub-blocks |
101 | * @phy_type: ISP_PHY_TYPE_{3430,3630} |
102 | */ |
103 | struct isp_res_mapping { |
104 | u32 isp_rev; |
105 | u32 offset[OMAP3_ISP_IOMEM_LAST]; |
106 | u32 phy_type; |
107 | }; |
108 | |
109 | /* |
110 | * struct isp_reg - Structure for ISP register values. |
111 | * @reg: 32-bit Register address. |
112 | * @val: 32-bit Register value. |
113 | */ |
114 | struct isp_reg { |
115 | enum isp_mem_resources mmio_range; |
116 | u32 reg; |
117 | u32 val; |
118 | }; |
119 | |
120 | enum isp_xclk_id { |
121 | ISP_XCLK_A, |
122 | ISP_XCLK_B, |
123 | }; |
124 | |
125 | struct isp_xclk { |
126 | struct isp_device *isp; |
127 | struct clk_hw hw; |
128 | struct clk *clk; |
129 | enum isp_xclk_id id; |
130 | |
131 | spinlock_t lock; /* Protects enabled and divider */ |
132 | bool enabled; |
133 | unsigned int divider; |
134 | }; |
135 | |
136 | /* |
137 | * struct isp_device - ISP device structure. |
138 | * @dev: Device pointer specific to the OMAP3 ISP. |
139 | * @revision: Stores current ISP module revision. |
140 | * @irq_num: Currently used IRQ number. |
141 | * @mmio_base: Array with kernel base addresses for ioremapped ISP register |
142 | * regions. |
143 | * @mmio_hist_base_phys: Physical L4 bus address for ISP hist block register |
144 | * region. |
145 | * @syscon: Regmap for the syscon register space |
146 | * @syscon_offset: Offset of the CSIPHY control register in syscon |
147 | * @phy_type: ISP_PHY_TYPE_{3430,3630} |
148 | * @mapping: IOMMU mapping |
149 | * @stat_lock: Spinlock for handling statistics |
150 | * @isp_mutex: Mutex for serializing requests to ISP. |
151 | * @stop_failure: Indicates that an entity failed to stop. |
152 | * @crashed: Crashed ent_enum |
153 | * @has_context: Context has been saved at least once and can be restored. |
154 | * @ref_count: Reference count for handling multiple ISP requests. |
155 | * @cam_ick: Pointer to camera interface clock structure. |
156 | * @cam_mclk: Pointer to camera functional clock structure. |
157 | * @csi2_fck: Pointer to camera CSI2 complexIO clock structure. |
158 | * @l3_ick: Pointer to OMAP3 L3 bus interface clock. |
159 | * @xclks: External clocks provided by the ISP |
160 | * @irq: Currently attached ISP ISR callbacks information structure. |
161 | * @isp_af: Pointer to current settings for ISP AutoFocus SCM. |
162 | * @isp_hist: Pointer to current settings for ISP Histogram SCM. |
163 | * @isp_h3a: Pointer to current settings for ISP Auto Exposure and |
164 | * White Balance SCM. |
165 | * @isp_res: Pointer to current settings for ISP Resizer. |
166 | * @isp_prev: Pointer to current settings for ISP Preview. |
167 | * @isp_ccdc: Pointer to current settings for ISP CCDC. |
168 | * @platform_cb: ISP driver callback function pointers for platform code |
169 | * |
170 | * This structure is used to store the OMAP ISP Information. |
171 | */ |
172 | struct isp_device { |
173 | struct v4l2_device v4l2_dev; |
174 | struct v4l2_async_notifier notifier; |
175 | struct media_device media_dev; |
176 | struct device *dev; |
177 | u32 revision; |
178 | |
179 | /* platform HW resources */ |
180 | unsigned int irq_num; |
181 | |
182 | void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST]; |
183 | unsigned long mmio_hist_base_phys; |
184 | struct regmap *syscon; |
185 | u32 syscon_offset; |
186 | u32 phy_type; |
187 | |
188 | struct dma_iommu_mapping *mapping; |
189 | |
190 | /* ISP Obj */ |
191 | spinlock_t stat_lock; /* common lock for statistic drivers */ |
192 | struct mutex isp_mutex; /* For handling ref_count field */ |
193 | bool stop_failure; |
194 | struct media_entity_enum crashed; |
195 | int has_context; |
196 | int ref_count; |
197 | unsigned int autoidle; |
198 | #define ISP_CLK_CAM_ICK 0 |
199 | #define ISP_CLK_CAM_MCLK 1 |
200 | #define ISP_CLK_CSI2_FCK 2 |
201 | #define ISP_CLK_L3_ICK 3 |
202 | struct clk *clock[4]; |
203 | struct isp_xclk xclks[2]; |
204 | |
205 | /* ISP modules */ |
206 | struct ispstat isp_af; |
207 | struct ispstat isp_aewb; |
208 | struct ispstat isp_hist; |
209 | struct isp_res_device isp_res; |
210 | struct isp_prev_device isp_prev; |
211 | struct isp_ccdc_device isp_ccdc; |
212 | struct isp_csi2_device isp_csi2a; |
213 | struct isp_csi2_device isp_csi2c; |
214 | struct isp_ccp2_device isp_ccp2; |
215 | struct isp_csiphy isp_csiphy1; |
216 | struct isp_csiphy isp_csiphy2; |
217 | |
218 | unsigned int sbl_resources; |
219 | unsigned int subclk_resources; |
220 | }; |
221 | |
222 | struct isp_async_subdev { |
223 | struct v4l2_async_connection asd; |
224 | struct isp_bus_cfg bus; |
225 | }; |
226 | |
227 | static inline struct isp_bus_cfg * |
228 | v4l2_subdev_to_bus_cfg(struct v4l2_subdev *sd) |
229 | { |
230 | struct v4l2_async_connection *asc; |
231 | |
232 | asc = v4l2_async_connection_unique(sd); |
233 | if (!asc) |
234 | return NULL; |
235 | |
236 | return &container_of(asc, struct isp_async_subdev, asd)->bus; |
237 | } |
238 | |
239 | #define v4l2_dev_to_isp_device(dev) \ |
240 | container_of(dev, struct isp_device, v4l2_dev) |
241 | |
242 | void omap3isp_hist_dma_done(struct isp_device *isp); |
243 | |
244 | void omap3isp_flush(struct isp_device *isp); |
245 | |
246 | int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait, |
247 | atomic_t *stopping); |
248 | |
249 | int omap3isp_module_sync_is_stopping(wait_queue_head_t *wait, |
250 | atomic_t *stopping); |
251 | |
252 | int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe, |
253 | enum isp_pipeline_stream_state state); |
254 | void omap3isp_pipeline_cancel_stream(struct isp_pipeline *pipe); |
255 | void omap3isp_configure_bridge(struct isp_device *isp, |
256 | enum ccdc_input_entity input, |
257 | const struct isp_parallel_cfg *buscfg, |
258 | unsigned int shift, unsigned int bridge); |
259 | |
260 | struct isp_device *omap3isp_get(struct isp_device *isp); |
261 | void omap3isp_put(struct isp_device *isp); |
262 | |
263 | void omap3isp_print_status(struct isp_device *isp); |
264 | |
265 | void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res); |
266 | void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res); |
267 | |
268 | void omap3isp_subclk_enable(struct isp_device *isp, |
269 | enum isp_subclk_resource res); |
270 | void omap3isp_subclk_disable(struct isp_device *isp, |
271 | enum isp_subclk_resource res); |
272 | |
273 | int omap3isp_register_entities(struct platform_device *pdev, |
274 | struct v4l2_device *v4l2_dev); |
275 | void omap3isp_unregister_entities(struct platform_device *pdev); |
276 | |
277 | /* |
278 | * isp_reg_readl - Read value of an OMAP3 ISP register |
279 | * @isp: Device pointer specific to the OMAP3 ISP. |
280 | * @isp_mmio_range: Range to which the register offset refers to. |
281 | * @reg_offset: Register offset to read from. |
282 | * |
283 | * Returns an unsigned 32 bit value with the required register contents. |
284 | */ |
285 | static inline |
286 | u32 isp_reg_readl(struct isp_device *isp, enum isp_mem_resources isp_mmio_range, |
287 | u32 reg_offset) |
288 | { |
289 | return __raw_readl(addr: isp->mmio_base[isp_mmio_range] + reg_offset); |
290 | } |
291 | |
292 | /* |
293 | * isp_reg_writel - Write value to an OMAP3 ISP register |
294 | * @isp: Device pointer specific to the OMAP3 ISP. |
295 | * @reg_value: 32 bit value to write to the register. |
296 | * @isp_mmio_range: Range to which the register offset refers to. |
297 | * @reg_offset: Register offset to write into. |
298 | */ |
299 | static inline |
300 | void isp_reg_writel(struct isp_device *isp, u32 reg_value, |
301 | enum isp_mem_resources isp_mmio_range, u32 reg_offset) |
302 | { |
303 | __raw_writel(val: reg_value, addr: isp->mmio_base[isp_mmio_range] + reg_offset); |
304 | } |
305 | |
306 | /* |
307 | * isp_reg_clr - Clear individual bits in an OMAP3 ISP register |
308 | * @isp: Device pointer specific to the OMAP3 ISP. |
309 | * @mmio_range: Range to which the register offset refers to. |
310 | * @reg: Register offset to work on. |
311 | * @clr_bits: 32 bit value which would be cleared in the register. |
312 | */ |
313 | static inline |
314 | void isp_reg_clr(struct isp_device *isp, enum isp_mem_resources mmio_range, |
315 | u32 reg, u32 clr_bits) |
316 | { |
317 | u32 v = isp_reg_readl(isp, isp_mmio_range: mmio_range, reg_offset: reg); |
318 | |
319 | isp_reg_writel(isp, reg_value: v & ~clr_bits, isp_mmio_range: mmio_range, reg_offset: reg); |
320 | } |
321 | |
322 | /* |
323 | * isp_reg_set - Set individual bits in an OMAP3 ISP register |
324 | * @isp: Device pointer specific to the OMAP3 ISP. |
325 | * @mmio_range: Range to which the register offset refers to. |
326 | * @reg: Register offset to work on. |
327 | * @set_bits: 32 bit value which would be set in the register. |
328 | */ |
329 | static inline |
330 | void isp_reg_set(struct isp_device *isp, enum isp_mem_resources mmio_range, |
331 | u32 reg, u32 set_bits) |
332 | { |
333 | u32 v = isp_reg_readl(isp, isp_mmio_range: mmio_range, reg_offset: reg); |
334 | |
335 | isp_reg_writel(isp, reg_value: v | set_bits, isp_mmio_range: mmio_range, reg_offset: reg); |
336 | } |
337 | |
338 | /* |
339 | * isp_reg_clr_set - Clear and set invidial bits in an OMAP3 ISP register |
340 | * @isp: Device pointer specific to the OMAP3 ISP. |
341 | * @mmio_range: Range to which the register offset refers to. |
342 | * @reg: Register offset to work on. |
343 | * @clr_bits: 32 bit value which would be cleared in the register. |
344 | * @set_bits: 32 bit value which would be set in the register. |
345 | * |
346 | * The clear operation is done first, and then the set operation. |
347 | */ |
348 | static inline |
349 | void isp_reg_clr_set(struct isp_device *isp, enum isp_mem_resources mmio_range, |
350 | u32 reg, u32 clr_bits, u32 set_bits) |
351 | { |
352 | u32 v = isp_reg_readl(isp, isp_mmio_range: mmio_range, reg_offset: reg); |
353 | |
354 | isp_reg_writel(isp, reg_value: (v & ~clr_bits) | set_bits, isp_mmio_range: mmio_range, reg_offset: reg); |
355 | } |
356 | |
357 | static inline enum v4l2_buf_type |
358 | isp_pad_buffer_type(const struct v4l2_subdev *subdev, int pad) |
359 | { |
360 | if (pad >= subdev->entity.num_pads) |
361 | return 0; |
362 | |
363 | if (subdev->entity.pads[pad].flags & MEDIA_PAD_FL_SINK) |
364 | return V4L2_BUF_TYPE_VIDEO_OUTPUT; |
365 | else |
366 | return V4L2_BUF_TYPE_VIDEO_CAPTURE; |
367 | } |
368 | |
369 | #endif /* OMAP3_ISP_CORE_H */ |
370 | |