1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * TI OMAP4 ISS V4L2 Driver
4  *
5  * Copyright (C) 2012 Texas Instruments.
6  *
7  * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
8  */
9 
10 #ifndef _OMAP4_ISS_H_
11 #define _OMAP4_ISS_H_
12 
13 #include <media/v4l2-device.h>
14 #include <media/v4l2-mc.h>
15 
16 #include <linux/device.h>
17 #include <linux/io.h>
18 #include <linux/platform_device.h>
19 #include <linux/wait.h>
20 
21 #include <linux/platform_data/media/omap4iss.h>
22 
23 #include "iss_regs.h"
24 #include "iss_csiphy.h"
25 #include "iss_csi2.h"
26 #include "iss_ipipeif.h"
27 #include "iss_ipipe.h"
28 #include "iss_resizer.h"
29 
30 struct regmap;
31 
32 #define to_iss_device(ptr_module)				\
33 	container_of(ptr_module, struct iss_device, ptr_module)
34 #define to_device(ptr_module)						\
35 	(to_iss_device(ptr_module)->dev)
36 
37 enum iss_mem_resources {
38 	OMAP4_ISS_MEM_TOP,
39 	OMAP4_ISS_MEM_CSI2_A_REGS1,
40 	OMAP4_ISS_MEM_CAMERARX_CORE1,
41 	OMAP4_ISS_MEM_CSI2_B_REGS1,
42 	OMAP4_ISS_MEM_CAMERARX_CORE2,
43 	OMAP4_ISS_MEM_BTE,
44 	OMAP4_ISS_MEM_ISP_SYS1,
45 	OMAP4_ISS_MEM_ISP_RESIZER,
46 	OMAP4_ISS_MEM_ISP_IPIPE,
47 	OMAP4_ISS_MEM_ISP_ISIF,
48 	OMAP4_ISS_MEM_ISP_IPIPEIF,
49 	OMAP4_ISS_MEM_LAST,
50 };
51 
52 enum iss_subclk_resource {
53 	OMAP4_ISS_SUBCLK_SIMCOP		= (1 << 0),
54 	OMAP4_ISS_SUBCLK_ISP		= (1 << 1),
55 	OMAP4_ISS_SUBCLK_CSI2_A		= (1 << 2),
56 	OMAP4_ISS_SUBCLK_CSI2_B		= (1 << 3),
57 	OMAP4_ISS_SUBCLK_CCP2		= (1 << 4),
58 };
59 
60 enum iss_isp_subclk_resource {
61 	OMAP4_ISS_ISP_SUBCLK_BL		= (1 << 0),
62 	OMAP4_ISS_ISP_SUBCLK_ISIF	= (1 << 1),
63 	OMAP4_ISS_ISP_SUBCLK_H3A	= (1 << 2),
64 	OMAP4_ISS_ISP_SUBCLK_RSZ	= (1 << 3),
65 	OMAP4_ISS_ISP_SUBCLK_IPIPE	= (1 << 4),
66 	OMAP4_ISS_ISP_SUBCLK_IPIPEIF	= (1 << 5),
67 };
68 
69 /*
70  * struct iss_reg - Structure for ISS register values.
71  * @reg: 32-bit Register address.
72  * @val: 32-bit Register value.
73  */
74 struct iss_reg {
75 	enum iss_mem_resources mmio_range;
76 	u32 reg;
77 	u32 val;
78 };
79 
80 /*
81  * struct iss_device - ISS device structure.
82  * @syscon: Regmap for the syscon register space
83  * @crashed: Crashed entities
84  */
85 struct iss_device {
86 	struct v4l2_device v4l2_dev;
87 	struct media_device media_dev;
88 	struct device *dev;
89 	u32 revision;
90 
91 	/* platform HW resources */
92 	struct iss_platform_data *pdata;
93 	unsigned int irq_num;
94 
95 	struct resource *res[OMAP4_ISS_MEM_LAST];
96 	void __iomem *regs[OMAP4_ISS_MEM_LAST];
97 	struct regmap *syscon;
98 
99 	u64 raw_dmamask;
100 
101 	struct mutex iss_mutex;	/* For handling ref_count field */
102 	struct media_entity_enum crashed;
103 	int has_context;
104 	int ref_count;
105 
106 	struct clk *iss_fck;
107 	struct clk *iss_ctrlclk;
108 
109 	/* ISS modules */
110 	struct iss_csi2_device csi2a;
111 	struct iss_csi2_device csi2b;
112 	struct iss_csiphy csiphy1;
113 	struct iss_csiphy csiphy2;
114 	struct iss_ipipeif_device ipipeif;
115 	struct iss_ipipe_device ipipe;
116 	struct iss_resizer_device resizer;
117 
118 	unsigned int subclk_resources;
119 	unsigned int isp_subclk_resources;
120 };
121 
122 int omap4iss_get_external_info(struct iss_pipeline *pipe,
123 			       struct media_link *link);
124 
125 int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
126 			      atomic_t *stopping);
127 
128 int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait,
129 				     atomic_t *stopping);
130 
131 int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe,
132 				 enum iss_pipeline_stream_state state);
133 void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe);
134 
135 void omap4iss_configure_bridge(struct iss_device *iss,
136 			       enum ipipeif_input_entity input);
137 
138 struct iss_device *omap4iss_get(struct iss_device *iss);
139 void omap4iss_put(struct iss_device *iss);
140 int omap4iss_subclk_enable(struct iss_device *iss,
141 			   enum iss_subclk_resource res);
142 int omap4iss_subclk_disable(struct iss_device *iss,
143 			    enum iss_subclk_resource res);
144 void omap4iss_isp_subclk_enable(struct iss_device *iss,
145 				enum iss_isp_subclk_resource res);
146 void omap4iss_isp_subclk_disable(struct iss_device *iss,
147 				 enum iss_isp_subclk_resource res);
148 
149 int omap4iss_register_entities(struct platform_device *pdev,
150 			       struct v4l2_device *v4l2_dev);
151 void omap4iss_unregister_entities(struct platform_device *pdev);
152 
153 /*
154  * iss_reg_read - Read the value of an OMAP4 ISS register
155  * @iss: the ISS device
156  * @res: memory resource in which the register is located
157  * @offset: register offset in the memory resource
158  *
159  * Return the register value.
160  */
161 static inline
iss_reg_read(struct iss_device * iss,enum iss_mem_resources res,u32 offset)162 u32 iss_reg_read(struct iss_device *iss, enum iss_mem_resources res,
163 		 u32 offset)
164 {
165 	return readl(iss->regs[res] + offset);
166 }
167 
168 /*
169  * iss_reg_write - Write a value to an OMAP4 ISS register
170  * @iss: the ISS device
171  * @res: memory resource in which the register is located
172  * @offset: register offset in the memory resource
173  * @value: value to be written
174  */
175 static inline
iss_reg_write(struct iss_device * iss,enum iss_mem_resources res,u32 offset,u32 value)176 void iss_reg_write(struct iss_device *iss, enum iss_mem_resources res,
177 		   u32 offset, u32 value)
178 {
179 	writel(value, iss->regs[res] + offset);
180 }
181 
182 /*
183  * iss_reg_clr - Clear bits in an OMAP4 ISS register
184  * @iss: the ISS device
185  * @res: memory resource in which the register is located
186  * @offset: register offset in the memory resource
187  * @clr: bit mask to be cleared
188  */
189 static inline
iss_reg_clr(struct iss_device * iss,enum iss_mem_resources res,u32 offset,u32 clr)190 void iss_reg_clr(struct iss_device *iss, enum iss_mem_resources res,
191 		 u32 offset, u32 clr)
192 {
193 	u32 v = iss_reg_read(iss, res, offset);
194 
195 	iss_reg_write(iss, res, offset, v & ~clr);
196 }
197 
198 /*
199  * iss_reg_set - Set bits in an OMAP4 ISS register
200  * @iss: the ISS device
201  * @res: memory resource in which the register is located
202  * @offset: register offset in the memory resource
203  * @set: bit mask to be set
204  */
205 static inline
iss_reg_set(struct iss_device * iss,enum iss_mem_resources res,u32 offset,u32 set)206 void iss_reg_set(struct iss_device *iss, enum iss_mem_resources res,
207 		 u32 offset, u32 set)
208 {
209 	u32 v = iss_reg_read(iss, res, offset);
210 
211 	iss_reg_write(iss, res, offset, v | set);
212 }
213 
214 /*
215  * iss_reg_update - Clear and set bits in an OMAP4 ISS register
216  * @iss: the ISS device
217  * @res: memory resource in which the register is located
218  * @offset: register offset in the memory resource
219  * @clr: bit mask to be cleared
220  * @set: bit mask to be set
221  *
222  * Clear the clr mask first and then set the set mask.
223  */
224 static inline
iss_reg_update(struct iss_device * iss,enum iss_mem_resources res,u32 offset,u32 clr,u32 set)225 void iss_reg_update(struct iss_device *iss, enum iss_mem_resources res,
226 		    u32 offset, u32 clr, u32 set)
227 {
228 	u32 v = iss_reg_read(iss, res, offset);
229 
230 	iss_reg_write(iss, res, offset, (v & ~clr) | set);
231 }
232 
233 #define iss_poll_condition_timeout(cond, timeout, min_ival, max_ival)	\
234 ({									\
235 	unsigned long __timeout = jiffies + usecs_to_jiffies(timeout);	\
236 	unsigned int __min_ival = (min_ival);				\
237 	unsigned int __max_ival = (max_ival);				\
238 	bool __cond;							\
239 	while (!(__cond = (cond))) {					\
240 		if (time_after(jiffies, __timeout))			\
241 			break;						\
242 		usleep_range(__min_ival, __max_ival);			\
243 	}								\
244 	!__cond;							\
245 })
246 
247 #endif /* _OMAP4_ISS_H_ */
248