xref: /linux/drivers/media/platform/microchip/microchip-sama5d2-isc.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Microchip Image Sensor Controller (ISC) driver
4  *
5  * Copyright (C) 2016-2019 Microchip Technology, Inc.
6  *
7  * Author: Songjun Wu
8  * Author: Eugen Hristev <eugen.hristev@microchip.com>
9  *
10  *
11  * Sensor-->PFE-->WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB-->RLP-->DMA
12  *
13  * ISC video pipeline integrates the following submodules:
14  * PFE: Parallel Front End to sample the camera sensor input stream
15  *  WB: Programmable white balance in the Bayer domain
16  * CFA: Color filter array interpolation module
17  *  CC: Programmable color correction
18  * GAM: Gamma correction
19  * CSC: Programmable color space conversion
20  * CBC: Contrast and Brightness control
21  * SUB: This module performs YCbCr444 to YCbCr420 chrominance subsampling
22  * RLP: This module performs rounding, range limiting
23  *      and packing of the incoming data
24  */
25 
26 #include <linux/clk.h>
27 #include <linux/clkdev.h>
28 #include <linux/clk-provider.h>
29 #include <linux/delay.h>
30 #include <linux/interrupt.h>
31 #include <linux/math64.h>
32 #include <linux/module.h>
33 #include <linux/of.h>
34 #include <linux/of_graph.h>
35 #include <linux/platform_device.h>
36 #include <linux/pm_runtime.h>
37 #include <linux/regmap.h>
38 #include <linux/videodev2.h>
39 
40 #include <media/v4l2-ctrls.h>
41 #include <media/v4l2-device.h>
42 #include <media/v4l2-event.h>
43 #include <media/v4l2-image-sizes.h>
44 #include <media/v4l2-ioctl.h>
45 #include <media/v4l2-fwnode.h>
46 #include <media/v4l2-subdev.h>
47 #include <media/videobuf2-dma-contig.h>
48 
49 #include "microchip-isc-regs.h"
50 #include "microchip-isc.h"
51 
52 #define ISC_SAMA5D2_MAX_SUPPORT_WIDTH   2592
53 #define ISC_SAMA5D2_MAX_SUPPORT_HEIGHT  1944
54 
55 #define ISC_SAMA5D2_PIPELINE \
56 	(WB_ENABLE | CFA_ENABLE | CC_ENABLE | GAM_ENABLES | CSC_ENABLE | \
57 	CBC_ENABLE | SUB422_ENABLE | SUB420_ENABLE)
58 
59 /* This is a list of the formats that the ISC can *output* */
60 static const struct isc_format sama5d2_controller_formats[] = {
61 	{
62 		.fourcc		= V4L2_PIX_FMT_ARGB444,
63 	}, {
64 		.fourcc		= V4L2_PIX_FMT_ARGB555,
65 	}, {
66 		.fourcc		= V4L2_PIX_FMT_RGB565,
67 	}, {
68 		.fourcc		= V4L2_PIX_FMT_ABGR32,
69 	}, {
70 		.fourcc		= V4L2_PIX_FMT_XBGR32,
71 	}, {
72 		.fourcc		= V4L2_PIX_FMT_YUV420,
73 	}, {
74 		.fourcc		= V4L2_PIX_FMT_YUYV,
75 	}, {
76 		.fourcc		= V4L2_PIX_FMT_YUV422P,
77 	}, {
78 		.fourcc		= V4L2_PIX_FMT_GREY,
79 	}, {
80 		.fourcc		= V4L2_PIX_FMT_Y10,
81 	}, {
82 		.fourcc		= V4L2_PIX_FMT_SBGGR8,
83 		.raw		= true,
84 	}, {
85 		.fourcc		= V4L2_PIX_FMT_SGBRG8,
86 		.raw		= true,
87 	}, {
88 		.fourcc		= V4L2_PIX_FMT_SGRBG8,
89 		.raw		= true,
90 	}, {
91 		.fourcc		= V4L2_PIX_FMT_SRGGB8,
92 		.raw		= true,
93 	}, {
94 		.fourcc		= V4L2_PIX_FMT_SBGGR10,
95 		.raw		= true,
96 	}, {
97 		.fourcc		= V4L2_PIX_FMT_SGBRG10,
98 		.raw		= true,
99 	}, {
100 		.fourcc		= V4L2_PIX_FMT_SGRBG10,
101 		.raw		= true,
102 	}, {
103 		.fourcc		= V4L2_PIX_FMT_SRGGB10,
104 		.raw		= true,
105 	}, {
106 		.fourcc		= V4L2_PIX_FMT_SBGGR12,
107 		.raw		= true,
108 	}, {
109 		.fourcc		= V4L2_PIX_FMT_SGBRG12,
110 		.raw		= true,
111 	}, {
112 		.fourcc		= V4L2_PIX_FMT_SGRBG12,
113 		.raw		= true,
114 	}, {
115 		.fourcc		= V4L2_PIX_FMT_SRGGB12,
116 		.raw		= true,
117 	},
118 };
119 
120 /* This is a list of formats that the ISC can receive as *input* */
121 static struct isc_format sama5d2_formats_list[] = {
122 	{
123 		.fourcc		= V4L2_PIX_FMT_SBGGR8,
124 		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
125 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
126 		.cfa_baycfg	= ISC_BAY_CFG_BGBG,
127 	},
128 	{
129 		.fourcc		= V4L2_PIX_FMT_SGBRG8,
130 		.mbus_code	= MEDIA_BUS_FMT_SGBRG8_1X8,
131 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
132 		.cfa_baycfg	= ISC_BAY_CFG_GBGB,
133 	},
134 	{
135 		.fourcc		= V4L2_PIX_FMT_SGRBG8,
136 		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
137 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
138 		.cfa_baycfg	= ISC_BAY_CFG_GRGR,
139 	},
140 	{
141 		.fourcc		= V4L2_PIX_FMT_SRGGB8,
142 		.mbus_code	= MEDIA_BUS_FMT_SRGGB8_1X8,
143 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
144 		.cfa_baycfg	= ISC_BAY_CFG_RGRG,
145 	},
146 	{
147 		.fourcc		= V4L2_PIX_FMT_SBGGR10,
148 		.mbus_code	= MEDIA_BUS_FMT_SBGGR10_1X10,
149 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
150 		.cfa_baycfg	= ISC_BAY_CFG_RGRG,
151 	},
152 	{
153 		.fourcc		= V4L2_PIX_FMT_SGBRG10,
154 		.mbus_code	= MEDIA_BUS_FMT_SGBRG10_1X10,
155 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
156 		.cfa_baycfg	= ISC_BAY_CFG_GBGB,
157 	},
158 	{
159 		.fourcc		= V4L2_PIX_FMT_SGRBG10,
160 		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
161 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
162 		.cfa_baycfg	= ISC_BAY_CFG_GRGR,
163 	},
164 	{
165 		.fourcc		= V4L2_PIX_FMT_SRGGB10,
166 		.mbus_code	= MEDIA_BUS_FMT_SRGGB10_1X10,
167 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
168 		.cfa_baycfg	= ISC_BAY_CFG_RGRG,
169 	},
170 	{
171 		.fourcc		= V4L2_PIX_FMT_SBGGR12,
172 		.mbus_code	= MEDIA_BUS_FMT_SBGGR12_1X12,
173 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TWELVE,
174 		.cfa_baycfg	= ISC_BAY_CFG_BGBG,
175 	},
176 	{
177 		.fourcc		= V4L2_PIX_FMT_SGBRG12,
178 		.mbus_code	= MEDIA_BUS_FMT_SGBRG12_1X12,
179 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TWELVE,
180 		.cfa_baycfg	= ISC_BAY_CFG_GBGB,
181 	},
182 	{
183 		.fourcc		= V4L2_PIX_FMT_SGRBG12,
184 		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
185 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TWELVE,
186 		.cfa_baycfg	= ISC_BAY_CFG_GRGR,
187 	},
188 	{
189 		.fourcc		= V4L2_PIX_FMT_SRGGB12,
190 		.mbus_code	= MEDIA_BUS_FMT_SRGGB12_1X12,
191 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TWELVE,
192 		.cfa_baycfg	= ISC_BAY_CFG_RGRG,
193 	},
194 	{
195 		.fourcc		= V4L2_PIX_FMT_GREY,
196 		.mbus_code	= MEDIA_BUS_FMT_Y8_1X8,
197 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
198 	},
199 	{
200 		.fourcc		= V4L2_PIX_FMT_YUYV,
201 		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
202 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
203 	},
204 	{
205 		.fourcc		= V4L2_PIX_FMT_RGB565,
206 		.mbus_code	= MEDIA_BUS_FMT_RGB565_2X8_LE,
207 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
208 	},
209 	{
210 		.fourcc		= V4L2_PIX_FMT_Y10,
211 		.mbus_code	= MEDIA_BUS_FMT_Y10_1X10,
212 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
213 	},
214 
215 };
216 
isc_sama5d2_config_csc(struct isc_device * isc)217 static void isc_sama5d2_config_csc(struct isc_device *isc)
218 {
219 	struct regmap *regmap = isc->regmap;
220 
221 	/* Convert RGB to YUV */
222 	regmap_write(regmap, ISC_CSC_YR_YG + isc->offsets.csc,
223 		     0x42 | (0x81 << 16));
224 	regmap_write(regmap, ISC_CSC_YB_OY + isc->offsets.csc,
225 		     0x19 | (0x10 << 16));
226 	regmap_write(regmap, ISC_CSC_CBR_CBG + isc->offsets.csc,
227 		     0xFDA | (0xFB6 << 16));
228 	regmap_write(regmap, ISC_CSC_CBB_OCB + isc->offsets.csc,
229 		     0x70 | (0x80 << 16));
230 	regmap_write(regmap, ISC_CSC_CRR_CRG + isc->offsets.csc,
231 		     0x70 | (0xFA2 << 16));
232 	regmap_write(regmap, ISC_CSC_CRB_OCR + isc->offsets.csc,
233 		     0xFEE | (0x80 << 16));
234 }
235 
isc_sama5d2_config_cbc(struct isc_device * isc)236 static void isc_sama5d2_config_cbc(struct isc_device *isc)
237 {
238 	struct regmap *regmap = isc->regmap;
239 
240 	regmap_write(regmap, ISC_CBC_BRIGHT + isc->offsets.cbc,
241 		     isc->ctrls.brightness);
242 	regmap_write(regmap, ISC_CBC_CONTRAST + isc->offsets.cbc,
243 		     isc->ctrls.contrast);
244 }
245 
isc_sama5d2_config_cc(struct isc_device * isc)246 static void isc_sama5d2_config_cc(struct isc_device *isc)
247 {
248 	struct regmap *regmap = isc->regmap;
249 
250 	/* Configure each register at the neutral fixed point 1.0 or 0.0 */
251 	regmap_write(regmap, ISC_CC_RR_RG, (1 << 8));
252 	regmap_write(regmap, ISC_CC_RB_OR, 0);
253 	regmap_write(regmap, ISC_CC_GR_GG, (1 << 8) << 16);
254 	regmap_write(regmap, ISC_CC_GB_OG, 0);
255 	regmap_write(regmap, ISC_CC_BR_BG, 0);
256 	regmap_write(regmap, ISC_CC_BB_OB, (1 << 8));
257 }
258 
isc_sama5d2_config_ctrls(struct isc_device * isc,const struct v4l2_ctrl_ops * ops)259 static void isc_sama5d2_config_ctrls(struct isc_device *isc,
260 				     const struct v4l2_ctrl_ops *ops)
261 {
262 	struct isc_ctrls *ctrls = &isc->ctrls;
263 	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
264 
265 	ctrls->contrast = 256;
266 
267 	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 256);
268 }
269 
isc_sama5d2_config_dpc(struct isc_device * isc)270 static void isc_sama5d2_config_dpc(struct isc_device *isc)
271 {
272 	/* This module is not present on sama5d2 pipeline */
273 }
274 
isc_sama5d2_config_gam(struct isc_device * isc)275 static void isc_sama5d2_config_gam(struct isc_device *isc)
276 {
277 	/* No specific gamma configuration */
278 }
279 
isc_sama5d2_config_rlp(struct isc_device * isc)280 static void isc_sama5d2_config_rlp(struct isc_device *isc)
281 {
282 	struct regmap *regmap = isc->regmap;
283 	u32 rlp_mode = isc->config.rlp_cfg_mode;
284 
285 	/*
286 	 * In sama5d2, the YUV planar modes and the YUYV modes are treated
287 	 * in the same way in RLP register.
288 	 * Normally, YYCC mode should be Luma(n) - Color B(n) - Color R (n)
289 	 * and YCYC should be Luma(n + 1) - Color B (n) - Luma (n) - Color R (n)
290 	 * but in sama5d2, the YCYC mode does not exist, and YYCC must be
291 	 * selected for both planar and interleaved modes, as in fact
292 	 * both modes are supported.
293 	 *
294 	 * Thus, if the YCYC mode is selected, replace it with the
295 	 * sama5d2-compliant mode which is YYCC .
296 	 */
297 	if ((rlp_mode & ISC_RLP_CFG_MODE_MASK) == ISC_RLP_CFG_MODE_YCYC) {
298 		rlp_mode &= ~ISC_RLP_CFG_MODE_MASK;
299 		rlp_mode |= ISC_RLP_CFG_MODE_YYCC;
300 	}
301 
302 	regmap_update_bits(regmap, ISC_RLP_CFG + isc->offsets.rlp,
303 			   ISC_RLP_CFG_MODE_MASK, rlp_mode);
304 }
305 
isc_sama5d2_adapt_pipeline(struct isc_device * isc)306 static void isc_sama5d2_adapt_pipeline(struct isc_device *isc)
307 {
308 	isc->try_config.bits_pipeline &= ISC_SAMA5D2_PIPELINE;
309 }
310 
311 /* Gamma table with gamma 1/2.2 */
312 static const u32 isc_sama5d2_gamma_table[][GAMMA_ENTRIES] = {
313 	/* 0 --> gamma 1/1.8 */
314 	{      0x65,  0x66002F,  0x950025,  0xBB0020,  0xDB001D,  0xF8001A,
315 	  0x1130018, 0x12B0017, 0x1420016, 0x1580014, 0x16D0013, 0x1810012,
316 	  0x1940012, 0x1A60012, 0x1B80011, 0x1C90010, 0x1DA0010, 0x1EA000F,
317 	  0x1FA000F, 0x209000F, 0x218000F, 0x227000E, 0x235000E, 0x243000E,
318 	  0x251000E, 0x25F000D, 0x26C000D, 0x279000D, 0x286000D, 0x293000C,
319 	  0x2A0000C, 0x2AC000C, 0x2B8000C, 0x2C4000C, 0x2D0000B, 0x2DC000B,
320 	  0x2E7000B, 0x2F3000B, 0x2FE000B, 0x309000B, 0x314000B, 0x31F000A,
321 	  0x32A000A, 0x334000B, 0x33F000A, 0x349000A, 0x354000A, 0x35E000A,
322 	  0x368000A, 0x372000A, 0x37C000A, 0x386000A, 0x3900009, 0x399000A,
323 	  0x3A30009, 0x3AD0009, 0x3B60009, 0x3BF000A, 0x3C90009, 0x3D20009,
324 	  0x3DB0009, 0x3E40009, 0x3ED0009, 0x3F60009 },
325 
326 	/* 1 --> gamma 1/2 */
327 	{      0x7F,  0x800034,  0xB50028,  0xDE0021, 0x100001E, 0x11E001B,
328 	  0x1390019, 0x1520017, 0x16A0015, 0x1800014, 0x1940014, 0x1A80013,
329 	  0x1BB0012, 0x1CD0011, 0x1DF0010, 0x1EF0010, 0x200000F, 0x20F000F,
330 	  0x21F000E, 0x22D000F, 0x23C000E, 0x24A000E, 0x258000D, 0x265000D,
331 	  0x273000C, 0x27F000D, 0x28C000C, 0x299000C, 0x2A5000C, 0x2B1000B,
332 	  0x2BC000C, 0x2C8000B, 0x2D3000C, 0x2DF000B, 0x2EA000A, 0x2F5000A,
333 	  0x2FF000B, 0x30A000A, 0x314000B, 0x31F000A, 0x329000A, 0x333000A,
334 	  0x33D0009, 0x3470009, 0x350000A, 0x35A0009, 0x363000A, 0x36D0009,
335 	  0x3760009, 0x37F0009, 0x3880009, 0x3910009, 0x39A0009, 0x3A30009,
336 	  0x3AC0008, 0x3B40009, 0x3BD0008, 0x3C60008, 0x3CE0008, 0x3D60009,
337 	  0x3DF0008, 0x3E70008, 0x3EF0008, 0x3F70008 },
338 
339 	/* 2 --> gamma 1/2.2 */
340 	{      0x99,  0x9B0038,  0xD4002A,  0xFF0023, 0x122001F, 0x141001B,
341 	  0x15D0019, 0x1760017, 0x18E0015, 0x1A30015, 0x1B80013, 0x1CC0012,
342 	  0x1DE0011, 0x1F00010, 0x2010010, 0x2110010, 0x221000F, 0x230000F,
343 	  0x23F000E, 0x24D000E, 0x25B000D, 0x269000C, 0x276000C, 0x283000C,
344 	  0x28F000C, 0x29B000C, 0x2A7000C, 0x2B3000B, 0x2BF000B, 0x2CA000B,
345 	  0x2D5000B, 0x2E0000A, 0x2EB000A, 0x2F5000A, 0x2FF000A, 0x30A000A,
346 	  0x3140009, 0x31E0009, 0x327000A, 0x3310009, 0x33A0009, 0x3440009,
347 	  0x34D0009, 0x3560009, 0x35F0009, 0x3680008, 0x3710008, 0x3790009,
348 	  0x3820008, 0x38A0008, 0x3930008, 0x39B0008, 0x3A30008, 0x3AB0008,
349 	  0x3B30008, 0x3BB0008, 0x3C30008, 0x3CB0007, 0x3D20008, 0x3DA0007,
350 	  0x3E20007, 0x3E90007, 0x3F00008, 0x3F80007 },
351 };
352 
isc_parse_dt(struct device * dev,struct isc_device * isc)353 static int isc_parse_dt(struct device *dev, struct isc_device *isc)
354 {
355 	struct device_node *np = dev->of_node;
356 	struct device_node *epn;
357 	struct isc_subdev_entity *subdev_entity;
358 	unsigned int flags;
359 
360 	INIT_LIST_HEAD(&isc->subdev_entities);
361 
362 	for_each_endpoint_of_node(np, epn) {
363 		struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 };
364 		int ret;
365 
366 		ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn),
367 						 &v4l2_epn);
368 		if (ret) {
369 			of_node_put(epn);
370 			dev_err(dev, "Could not parse the endpoint\n");
371 			return -EINVAL;
372 		}
373 
374 		subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity),
375 					     GFP_KERNEL);
376 		if (!subdev_entity) {
377 			of_node_put(epn);
378 			return -ENOMEM;
379 		}
380 		subdev_entity->epn = epn;
381 
382 		flags = v4l2_epn.bus.parallel.flags;
383 
384 		if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
385 			subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_LOW;
386 
387 		if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
388 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_LOW;
389 
390 		if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
391 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
392 
393 		if (v4l2_epn.bus_type == V4L2_MBUS_BT656)
394 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_CCIR_CRC |
395 					ISC_PFE_CFG0_CCIR656;
396 
397 		list_add_tail(&subdev_entity->list, &isc->subdev_entities);
398 	}
399 
400 	return 0;
401 }
402 
microchip_isc_probe(struct platform_device * pdev)403 static int microchip_isc_probe(struct platform_device *pdev)
404 {
405 	struct device *dev = &pdev->dev;
406 	struct isc_device *isc;
407 	void __iomem *io_base;
408 	struct isc_subdev_entity *subdev_entity;
409 	int irq;
410 	int ret;
411 	u32 ver;
412 
413 	isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL);
414 	if (!isc)
415 		return -ENOMEM;
416 
417 	platform_set_drvdata(pdev, isc);
418 	isc->dev = dev;
419 
420 	io_base = devm_platform_ioremap_resource(pdev, 0);
421 	if (IS_ERR(io_base))
422 		return PTR_ERR(io_base);
423 
424 	isc->regmap = devm_regmap_init_mmio(dev, io_base, &microchip_isc_regmap_config);
425 	if (IS_ERR(isc->regmap)) {
426 		ret = PTR_ERR(isc->regmap);
427 		dev_err(dev, "failed to init register map: %d\n", ret);
428 		return ret;
429 	}
430 
431 	irq = platform_get_irq(pdev, 0);
432 	if (irq < 0)
433 		return irq;
434 
435 	ret = devm_request_irq(dev, irq, microchip_isc_interrupt, 0,
436 			       "microchip-sama5d2-isc", isc);
437 	if (ret < 0) {
438 		dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
439 			irq, ret);
440 		return ret;
441 	}
442 
443 	isc->gamma_table = isc_sama5d2_gamma_table;
444 	isc->gamma_max = 2;
445 
446 	isc->max_width = ISC_SAMA5D2_MAX_SUPPORT_WIDTH;
447 	isc->max_height = ISC_SAMA5D2_MAX_SUPPORT_HEIGHT;
448 
449 	isc->config_dpc = isc_sama5d2_config_dpc;
450 	isc->config_csc = isc_sama5d2_config_csc;
451 	isc->config_cbc = isc_sama5d2_config_cbc;
452 	isc->config_cc = isc_sama5d2_config_cc;
453 	isc->config_gam = isc_sama5d2_config_gam;
454 	isc->config_rlp = isc_sama5d2_config_rlp;
455 	isc->config_ctrls = isc_sama5d2_config_ctrls;
456 
457 	isc->adapt_pipeline = isc_sama5d2_adapt_pipeline;
458 
459 	isc->offsets.csc = ISC_SAMA5D2_CSC_OFFSET;
460 	isc->offsets.cbc = ISC_SAMA5D2_CBC_OFFSET;
461 	isc->offsets.sub422 = ISC_SAMA5D2_SUB422_OFFSET;
462 	isc->offsets.sub420 = ISC_SAMA5D2_SUB420_OFFSET;
463 	isc->offsets.rlp = ISC_SAMA5D2_RLP_OFFSET;
464 	isc->offsets.his = ISC_SAMA5D2_HIS_OFFSET;
465 	isc->offsets.dma = ISC_SAMA5D2_DMA_OFFSET;
466 	isc->offsets.version = ISC_SAMA5D2_VERSION_OFFSET;
467 	isc->offsets.his_entry = ISC_SAMA5D2_HIS_ENTRY_OFFSET;
468 
469 	isc->controller_formats = sama5d2_controller_formats;
470 	isc->controller_formats_size = ARRAY_SIZE(sama5d2_controller_formats);
471 	isc->formats_list = sama5d2_formats_list;
472 	isc->formats_list_size = ARRAY_SIZE(sama5d2_formats_list);
473 
474 	/* sama5d2-isc - 8 bits per beat */
475 	isc->dcfg = ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8;
476 
477 	/* sama5d2-isc : ISPCK is required and mandatory */
478 	isc->ispck_required = true;
479 
480 	ret = microchip_isc_pipeline_init(isc);
481 	if (ret)
482 		return ret;
483 
484 	isc->hclock = devm_clk_get(dev, "hclock");
485 	if (IS_ERR(isc->hclock)) {
486 		ret = PTR_ERR(isc->hclock);
487 		dev_err(dev, "failed to get hclock: %d\n", ret);
488 		return ret;
489 	}
490 
491 	ret = clk_prepare_enable(isc->hclock);
492 	if (ret) {
493 		dev_err(dev, "failed to enable hclock: %d\n", ret);
494 		return ret;
495 	}
496 
497 	ret = microchip_isc_clk_init(isc);
498 	if (ret) {
499 		dev_err(dev, "failed to init isc clock: %d\n", ret);
500 		goto unprepare_hclk;
501 	}
502 	ret = v4l2_device_register(dev, &isc->v4l2_dev);
503 	if (ret) {
504 		dev_err(dev, "unable to register v4l2 device.\n");
505 		goto unprepare_clk;
506 	}
507 
508 	ret = isc_parse_dt(dev, isc);
509 	if (ret) {
510 		dev_err(dev, "fail to parse device tree\n");
511 		goto unregister_v4l2_device;
512 	}
513 
514 	if (list_empty(&isc->subdev_entities)) {
515 		dev_err(dev, "no subdev found\n");
516 		ret = -ENODEV;
517 		goto unregister_v4l2_device;
518 	}
519 
520 	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
521 		struct v4l2_async_connection *asd;
522 		struct fwnode_handle *fwnode =
523 			of_fwnode_handle(subdev_entity->epn);
524 
525 		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
526 
527 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
528 						      fwnode,
529 						      struct v4l2_async_connection);
530 
531 		of_node_put(subdev_entity->epn);
532 		subdev_entity->epn = NULL;
533 
534 		if (IS_ERR(asd)) {
535 			ret = PTR_ERR(asd);
536 			goto cleanup_subdev;
537 		}
538 
539 		subdev_entity->notifier.ops = &microchip_isc_async_ops;
540 
541 		ret = v4l2_async_nf_register(&subdev_entity->notifier);
542 		if (ret) {
543 			dev_err(dev, "fail to register async notifier\n");
544 			goto cleanup_subdev;
545 		}
546 
547 		if (video_is_registered(&isc->video_dev))
548 			break;
549 	}
550 
551 	regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver);
552 
553 	ret = isc_mc_init(isc, ver);
554 	if (ret < 0)
555 		goto isc_probe_mc_init_err;
556 
557 	pm_runtime_set_active(dev);
558 	pm_runtime_enable(dev);
559 	pm_request_idle(dev);
560 
561 	isc->ispck = isc->isc_clks[ISC_ISPCK].clk;
562 
563 	ret = clk_prepare_enable(isc->ispck);
564 	if (ret) {
565 		dev_err(dev, "failed to enable ispck: %d\n", ret);
566 		goto disable_pm;
567 	}
568 
569 	/* ispck should be greater or equal to hclock */
570 	ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
571 	if (ret) {
572 		dev_err(dev, "failed to set ispck rate: %d\n", ret);
573 		goto unprepare_clk;
574 	}
575 
576 	dev_info(dev, "Microchip ISC version %x\n", ver);
577 
578 	return 0;
579 
580 unprepare_clk:
581 	clk_disable_unprepare(isc->ispck);
582 
583 disable_pm:
584 	pm_runtime_disable(dev);
585 
586 isc_probe_mc_init_err:
587 	isc_mc_cleanup(isc);
588 
589 cleanup_subdev:
590 	microchip_isc_subdev_cleanup(isc);
591 
592 unregister_v4l2_device:
593 	v4l2_device_unregister(&isc->v4l2_dev);
594 
595 unprepare_hclk:
596 	clk_disable_unprepare(isc->hclock);
597 
598 	microchip_isc_clk_cleanup(isc);
599 
600 	return ret;
601 }
602 
microchip_isc_remove(struct platform_device * pdev)603 static void microchip_isc_remove(struct platform_device *pdev)
604 {
605 	struct isc_device *isc = platform_get_drvdata(pdev);
606 
607 	pm_runtime_disable(&pdev->dev);
608 
609 	isc_mc_cleanup(isc);
610 
611 	microchip_isc_subdev_cleanup(isc);
612 
613 	v4l2_device_unregister(&isc->v4l2_dev);
614 
615 	clk_disable_unprepare(isc->ispck);
616 	clk_disable_unprepare(isc->hclock);
617 
618 	microchip_isc_clk_cleanup(isc);
619 }
620 
isc_runtime_suspend(struct device * dev)621 static int __maybe_unused isc_runtime_suspend(struct device *dev)
622 {
623 	struct isc_device *isc = dev_get_drvdata(dev);
624 
625 	clk_disable_unprepare(isc->ispck);
626 	clk_disable_unprepare(isc->hclock);
627 
628 	return 0;
629 }
630 
isc_runtime_resume(struct device * dev)631 static int __maybe_unused isc_runtime_resume(struct device *dev)
632 {
633 	struct isc_device *isc = dev_get_drvdata(dev);
634 	int ret;
635 
636 	ret = clk_prepare_enable(isc->hclock);
637 	if (ret)
638 		return ret;
639 
640 	ret = clk_prepare_enable(isc->ispck);
641 	if (ret)
642 		clk_disable_unprepare(isc->hclock);
643 
644 	return ret;
645 }
646 
647 static const struct dev_pm_ops microchip_isc_dev_pm_ops = {
648 	SET_RUNTIME_PM_OPS(isc_runtime_suspend, isc_runtime_resume, NULL)
649 };
650 
651 #if IS_ENABLED(CONFIG_OF)
652 static const struct of_device_id microchip_isc_of_match[] = {
653 	{ .compatible = "atmel,sama5d2-isc" },
654 	{ }
655 };
656 MODULE_DEVICE_TABLE(of, microchip_isc_of_match);
657 #endif
658 
659 static struct platform_driver microchip_isc_driver = {
660 	.probe	= microchip_isc_probe,
661 	.remove_new = microchip_isc_remove,
662 	.driver	= {
663 		.name		= "microchip-sama5d2-isc",
664 		.pm		= &microchip_isc_dev_pm_ops,
665 		.of_match_table = of_match_ptr(microchip_isc_of_match),
666 	},
667 };
668 
669 module_platform_driver(microchip_isc_driver);
670 
671 MODULE_AUTHOR("Songjun Wu");
672 MODULE_DESCRIPTION("The V4L2 driver for Microchip-ISC");
673 MODULE_LICENSE("GPL v2");
674