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