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