1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Microchip eXtended Image Sensor Controller (XISC) driver
4  *
5  * Copyright (C) 2019-2021 Microchip Technology, Inc. and its subsidiaries
6  *
7  * Author: Eugen Hristev <eugen.hristev@microchip.com>
8  *
9  * Sensor-->PFE-->DPC-->WB-->CFA-->CC-->GAM-->VHXS-->CSC-->CBHS-->SUB-->RLP-->DMA-->HIS
10  *
11  * ISC video pipeline integrates the following submodules:
12  * PFE: Parallel Front End to sample the camera sensor input stream
13  * DPC: Defective Pixel Correction with black offset correction, green disparity
14  *      correction and defective pixel correction (3 modules total)
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  *VHXS: Vertical and Horizontal Scaler
20  * CSC: Programmable color space conversion
21  *CBHS: Contrast Brightness Hue and Saturation control
22  * SUB: This module performs YCbCr444 to YCbCr420 chrominance subsampling
23  * RLP: This module performs rounding, range limiting
24  *      and packing of the incoming data
25  * DMA: This module performs DMA master accesses to write frames to external RAM
26  * HIS: Histogram module performs statistic counters on the frames
27  */
28 
29 #include <linux/clk.h>
30 #include <linux/clkdev.h>
31 #include <linux/clk-provider.h>
32 #include <linux/delay.h>
33 #include <linux/interrupt.h>
34 #include <linux/math64.h>
35 #include <linux/module.h>
36 #include <linux/of.h>
37 #include <linux/of_graph.h>
38 #include <linux/platform_device.h>
39 #include <linux/pm_runtime.h>
40 #include <linux/regmap.h>
41 #include <linux/videodev2.h>
42 
43 #include <media/v4l2-ctrls.h>
44 #include <media/v4l2-device.h>
45 #include <media/v4l2-event.h>
46 #include <media/v4l2-image-sizes.h>
47 #include <media/v4l2-ioctl.h>
48 #include <media/v4l2-fwnode.h>
49 #include <media/v4l2-subdev.h>
50 #include <media/videobuf2-dma-contig.h>
51 
52 #include "atmel-isc-regs.h"
53 #include "atmel-isc.h"
54 
55 #define ISC_SAMA7G5_MAX_SUPPORT_WIDTH   3264
56 #define ISC_SAMA7G5_MAX_SUPPORT_HEIGHT  2464
57 
58 #define ISC_SAMA7G5_PIPELINE \
59 	(WB_ENABLE | CFA_ENABLE | CC_ENABLE | GAM_ENABLES | CSC_ENABLE | \
60 	CBC_ENABLE | SUB422_ENABLE | SUB420_ENABLE)
61 
62 /* This is a list of the formats that the ISC can *output* */
63 static const struct isc_format sama7g5_controller_formats[] = {
64 	{
65 		.fourcc		= V4L2_PIX_FMT_ARGB444,
66 	},
67 	{
68 		.fourcc		= V4L2_PIX_FMT_ARGB555,
69 	},
70 	{
71 		.fourcc		= V4L2_PIX_FMT_RGB565,
72 	},
73 	{
74 		.fourcc		= V4L2_PIX_FMT_ABGR32,
75 	},
76 	{
77 		.fourcc		= V4L2_PIX_FMT_XBGR32,
78 	},
79 	{
80 		.fourcc		= V4L2_PIX_FMT_YUV420,
81 	},
82 	{
83 		.fourcc		= V4L2_PIX_FMT_UYVY,
84 	},
85 	{
86 		.fourcc		= V4L2_PIX_FMT_VYUY,
87 	},
88 	{
89 		.fourcc		= V4L2_PIX_FMT_YUYV,
90 	},
91 	{
92 		.fourcc		= V4L2_PIX_FMT_YUV422P,
93 	},
94 	{
95 		.fourcc		= V4L2_PIX_FMT_GREY,
96 	},
97 	{
98 		.fourcc		= V4L2_PIX_FMT_Y10,
99 	},
100 	{
101 		.fourcc		= V4L2_PIX_FMT_Y16,
102 	},
103 };
104 
105 /* This is a list of formats that the ISC can receive as *input* */
106 static struct isc_format sama7g5_formats_list[] = {
107 	{
108 		.fourcc		= V4L2_PIX_FMT_SBGGR8,
109 		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
110 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
111 		.cfa_baycfg	= ISC_BAY_CFG_BGBG,
112 	},
113 	{
114 		.fourcc		= V4L2_PIX_FMT_SGBRG8,
115 		.mbus_code	= MEDIA_BUS_FMT_SGBRG8_1X8,
116 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
117 		.cfa_baycfg	= ISC_BAY_CFG_GBGB,
118 	},
119 	{
120 		.fourcc		= V4L2_PIX_FMT_SGRBG8,
121 		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
122 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
123 		.cfa_baycfg	= ISC_BAY_CFG_GRGR,
124 	},
125 	{
126 		.fourcc		= V4L2_PIX_FMT_SRGGB8,
127 		.mbus_code	= MEDIA_BUS_FMT_SRGGB8_1X8,
128 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
129 		.cfa_baycfg	= ISC_BAY_CFG_RGRG,
130 	},
131 	{
132 		.fourcc		= V4L2_PIX_FMT_SBGGR10,
133 		.mbus_code	= MEDIA_BUS_FMT_SBGGR10_1X10,
134 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
135 		.cfa_baycfg	= ISC_BAY_CFG_RGRG,
136 	},
137 	{
138 		.fourcc		= V4L2_PIX_FMT_SGBRG10,
139 		.mbus_code	= MEDIA_BUS_FMT_SGBRG10_1X10,
140 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
141 		.cfa_baycfg	= ISC_BAY_CFG_GBGB,
142 	},
143 	{
144 		.fourcc		= V4L2_PIX_FMT_SGRBG10,
145 		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
146 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
147 		.cfa_baycfg	= ISC_BAY_CFG_GRGR,
148 	},
149 	{
150 		.fourcc		= V4L2_PIX_FMT_SRGGB10,
151 		.mbus_code	= MEDIA_BUS_FMT_SRGGB10_1X10,
152 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
153 		.cfa_baycfg	= ISC_BAY_CFG_RGRG,
154 	},
155 	{
156 		.fourcc		= V4L2_PIX_FMT_SBGGR12,
157 		.mbus_code	= MEDIA_BUS_FMT_SBGGR12_1X12,
158 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TWELVE,
159 		.cfa_baycfg	= ISC_BAY_CFG_BGBG,
160 	},
161 	{
162 		.fourcc		= V4L2_PIX_FMT_SGBRG12,
163 		.mbus_code	= MEDIA_BUS_FMT_SGBRG12_1X12,
164 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TWELVE,
165 		.cfa_baycfg	= ISC_BAY_CFG_GBGB,
166 	},
167 	{
168 		.fourcc		= V4L2_PIX_FMT_SGRBG12,
169 		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
170 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TWELVE,
171 		.cfa_baycfg	= ISC_BAY_CFG_GRGR,
172 	},
173 	{
174 		.fourcc		= V4L2_PIX_FMT_SRGGB12,
175 		.mbus_code	= MEDIA_BUS_FMT_SRGGB12_1X12,
176 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TWELVE,
177 		.cfa_baycfg	= ISC_BAY_CFG_RGRG,
178 	},
179 	{
180 		.fourcc		= V4L2_PIX_FMT_GREY,
181 		.mbus_code	= MEDIA_BUS_FMT_Y8_1X8,
182 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
183 	},
184 	{
185 		.fourcc		= V4L2_PIX_FMT_YUYV,
186 		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
187 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
188 	},
189 	{
190 		.fourcc		= V4L2_PIX_FMT_UYVY,
191 		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
192 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
193 	},
194 	{
195 		.fourcc		= V4L2_PIX_FMT_RGB565,
196 		.mbus_code	= MEDIA_BUS_FMT_RGB565_2X8_LE,
197 		.pfe_cfg0_bps	= ISC_PFE_CFG0_BPS_EIGHT,
198 	},
199 	{
200 		.fourcc		= V4L2_PIX_FMT_Y10,
201 		.mbus_code	= MEDIA_BUS_FMT_Y10_1X10,
202 		.pfe_cfg0_bps	= ISC_PFG_CFG0_BPS_TEN,
203 	},
204 
205 };
206 
isc_sama7g5_config_csc(struct isc_device * isc)207 static void isc_sama7g5_config_csc(struct isc_device *isc)
208 {
209 	struct regmap *regmap = isc->regmap;
210 
211 	/* Convert RGB to YUV */
212 	regmap_write(regmap, ISC_CSC_YR_YG + isc->offsets.csc,
213 		     0x42 | (0x81 << 16));
214 	regmap_write(regmap, ISC_CSC_YB_OY + isc->offsets.csc,
215 		     0x19 | (0x10 << 16));
216 	regmap_write(regmap, ISC_CSC_CBR_CBG + isc->offsets.csc,
217 		     0xFDA | (0xFB6 << 16));
218 	regmap_write(regmap, ISC_CSC_CBB_OCB + isc->offsets.csc,
219 		     0x70 | (0x80 << 16));
220 	regmap_write(regmap, ISC_CSC_CRR_CRG + isc->offsets.csc,
221 		     0x70 | (0xFA2 << 16));
222 	regmap_write(regmap, ISC_CSC_CRB_OCR + isc->offsets.csc,
223 		     0xFEE | (0x80 << 16));
224 }
225 
isc_sama7g5_config_cbc(struct isc_device * isc)226 static void isc_sama7g5_config_cbc(struct isc_device *isc)
227 {
228 	struct regmap *regmap = isc->regmap;
229 
230 	/* Configure what is set via v4l2 ctrls */
231 	regmap_write(regmap, ISC_CBC_BRIGHT + isc->offsets.cbc, isc->ctrls.brightness);
232 	regmap_write(regmap, ISC_CBC_CONTRAST + isc->offsets.cbc, isc->ctrls.contrast);
233 	/* Configure Hue and Saturation as neutral midpoint */
234 	regmap_write(regmap, ISC_CBCHS_HUE, 0);
235 	regmap_write(regmap, ISC_CBCHS_SAT, (1 << 4));
236 }
237 
isc_sama7g5_config_cc(struct isc_device * isc)238 static void isc_sama7g5_config_cc(struct isc_device *isc)
239 {
240 	struct regmap *regmap = isc->regmap;
241 
242 	/* Configure each register at the neutral fixed point 1.0 or 0.0 */
243 	regmap_write(regmap, ISC_CC_RR_RG, (1 << 8));
244 	regmap_write(regmap, ISC_CC_RB_OR, 0);
245 	regmap_write(regmap, ISC_CC_GR_GG, (1 << 8) << 16);
246 	regmap_write(regmap, ISC_CC_GB_OG, 0);
247 	regmap_write(regmap, ISC_CC_BR_BG, 0);
248 	regmap_write(regmap, ISC_CC_BB_OB, (1 << 8));
249 }
250 
isc_sama7g5_config_ctrls(struct isc_device * isc,const struct v4l2_ctrl_ops * ops)251 static void isc_sama7g5_config_ctrls(struct isc_device *isc,
252 				     const struct v4l2_ctrl_ops *ops)
253 {
254 	struct isc_ctrls *ctrls = &isc->ctrls;
255 	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
256 
257 	ctrls->contrast = 16;
258 
259 	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 16);
260 }
261 
isc_sama7g5_config_dpc(struct isc_device * isc)262 static void isc_sama7g5_config_dpc(struct isc_device *isc)
263 {
264 	u32 bay_cfg = isc->config.sd_format->cfa_baycfg;
265 	struct regmap *regmap = isc->regmap;
266 
267 	regmap_update_bits(regmap, ISC_DPC_CFG, ISC_DPC_CFG_BLOFF_MASK,
268 			   (64 << ISC_DPC_CFG_BLOFF_SHIFT));
269 	regmap_update_bits(regmap, ISC_DPC_CFG, ISC_DPC_CFG_BAYCFG_MASK,
270 			   (bay_cfg << ISC_DPC_CFG_BAYCFG_SHIFT));
271 }
272 
isc_sama7g5_config_gam(struct isc_device * isc)273 static void isc_sama7g5_config_gam(struct isc_device *isc)
274 {
275 	struct regmap *regmap = isc->regmap;
276 
277 	regmap_update_bits(regmap, ISC_GAM_CTRL, ISC_GAM_CTRL_BIPART,
278 			   ISC_GAM_CTRL_BIPART);
279 }
280 
isc_sama7g5_config_rlp(struct isc_device * isc)281 static void isc_sama7g5_config_rlp(struct isc_device *isc)
282 {
283 	struct regmap *regmap = isc->regmap;
284 	u32 rlp_mode = isc->config.rlp_cfg_mode;
285 
286 	regmap_update_bits(regmap, ISC_RLP_CFG + isc->offsets.rlp,
287 			   ISC_RLP_CFG_MODE_MASK | ISC_RLP_CFG_LSH |
288 			   ISC_RLP_CFG_YMODE_MASK, rlp_mode);
289 }
290 
isc_sama7g5_adapt_pipeline(struct isc_device * isc)291 static void isc_sama7g5_adapt_pipeline(struct isc_device *isc)
292 {
293 	isc->try_config.bits_pipeline &= ISC_SAMA7G5_PIPELINE;
294 }
295 
296 /* Gamma table with gamma 1/2.2 */
297 static const u32 isc_sama7g5_gamma_table[][GAMMA_ENTRIES] = {
298 	/* index 0 --> gamma bipartite */
299 	{
300 	      0x980,  0x4c0320,  0x650260,  0x7801e0,  0x8701a0,  0x940180,
301 	   0xa00160,  0xab0120,  0xb40120,  0xbd0120,  0xc60100,  0xce0100,
302 	   0xd600e0,  0xdd00e0,  0xe400e0,  0xeb00c0,  0xf100c0,  0xf700c0,
303 	   0xfd00c0, 0x10300a0, 0x10800c0, 0x10e00a0, 0x11300a0, 0x11800a0,
304 	  0x11d00a0, 0x12200a0, 0x12700a0, 0x12c0080, 0x13000a0, 0x1350080,
305 	  0x13900a0, 0x13e0080, 0x1420076, 0x17d0062, 0x1ae0054, 0x1d8004a,
306 	  0x1fd0044, 0x21f003e, 0x23e003a, 0x25b0036, 0x2760032, 0x28f0030,
307 	  0x2a7002e, 0x2be002c, 0x2d4002c, 0x2ea0028, 0x2fe0028, 0x3120026,
308 	  0x3250024, 0x3370024, 0x3490022, 0x35a0022, 0x36b0020, 0x37b0020,
309 	  0x38b0020, 0x39b001e, 0x3aa001e, 0x3b9001c, 0x3c7001c, 0x3d5001c,
310 	  0x3e3001c, 0x3f1001c, 0x3ff001a, 0x40c001a },
311 };
312 
xisc_parse_dt(struct device * dev,struct isc_device * isc)313 static int xisc_parse_dt(struct device *dev, struct isc_device *isc)
314 {
315 	struct device_node *np = dev->of_node;
316 	struct device_node *epn = NULL;
317 	struct isc_subdev_entity *subdev_entity;
318 	unsigned int flags;
319 	int ret;
320 	bool mipi_mode;
321 
322 	INIT_LIST_HEAD(&isc->subdev_entities);
323 
324 	mipi_mode = of_property_read_bool(np, "microchip,mipi-mode");
325 
326 	while (1) {
327 		struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 };
328 
329 		epn = of_graph_get_next_endpoint(np, epn);
330 		if (!epn)
331 			return 0;
332 
333 		ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn),
334 						 &v4l2_epn);
335 		if (ret) {
336 			ret = -EINVAL;
337 			dev_err(dev, "Could not parse the endpoint\n");
338 			break;
339 		}
340 
341 		subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity),
342 					     GFP_KERNEL);
343 		if (!subdev_entity) {
344 			ret = -ENOMEM;
345 			break;
346 		}
347 		subdev_entity->epn = epn;
348 
349 		flags = v4l2_epn.bus.parallel.flags;
350 
351 		if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
352 			subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_LOW;
353 
354 		if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
355 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_LOW;
356 
357 		if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
358 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
359 
360 		if (v4l2_epn.bus_type == V4L2_MBUS_BT656)
361 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_CCIR_CRC |
362 					ISC_PFE_CFG0_CCIR656;
363 
364 		if (mipi_mode)
365 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_MIPI;
366 
367 		list_add_tail(&subdev_entity->list, &isc->subdev_entities);
368 	}
369 	of_node_put(epn);
370 
371 	return ret;
372 }
373 
microchip_xisc_probe(struct platform_device * pdev)374 static int microchip_xisc_probe(struct platform_device *pdev)
375 {
376 	struct device *dev = &pdev->dev;
377 	struct isc_device *isc;
378 	struct resource *res;
379 	void __iomem *io_base;
380 	struct isc_subdev_entity *subdev_entity;
381 	int irq;
382 	int ret;
383 	u32 ver;
384 
385 	isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL);
386 	if (!isc)
387 		return -ENOMEM;
388 
389 	platform_set_drvdata(pdev, isc);
390 	isc->dev = dev;
391 
392 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
393 	io_base = devm_ioremap_resource(dev, res);
394 	if (IS_ERR(io_base))
395 		return PTR_ERR(io_base);
396 
397 	isc->regmap = devm_regmap_init_mmio(dev, io_base, &isc_regmap_config);
398 	if (IS_ERR(isc->regmap)) {
399 		ret = PTR_ERR(isc->regmap);
400 		dev_err(dev, "failed to init register map: %d\n", ret);
401 		return ret;
402 	}
403 
404 	irq = platform_get_irq(pdev, 0);
405 	if (irq < 0)
406 		return irq;
407 
408 	ret = devm_request_irq(dev, irq, isc_interrupt, 0,
409 			       "microchip-sama7g5-xisc", isc);
410 	if (ret < 0) {
411 		dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
412 			irq, ret);
413 		return ret;
414 	}
415 
416 	isc->gamma_table = isc_sama7g5_gamma_table;
417 	isc->gamma_max = 0;
418 
419 	isc->max_width = ISC_SAMA7G5_MAX_SUPPORT_WIDTH;
420 	isc->max_height = ISC_SAMA7G5_MAX_SUPPORT_HEIGHT;
421 
422 	isc->config_dpc = isc_sama7g5_config_dpc;
423 	isc->config_csc = isc_sama7g5_config_csc;
424 	isc->config_cbc = isc_sama7g5_config_cbc;
425 	isc->config_cc = isc_sama7g5_config_cc;
426 	isc->config_gam = isc_sama7g5_config_gam;
427 	isc->config_rlp = isc_sama7g5_config_rlp;
428 	isc->config_ctrls = isc_sama7g5_config_ctrls;
429 
430 	isc->adapt_pipeline = isc_sama7g5_adapt_pipeline;
431 
432 	isc->offsets.csc = ISC_SAMA7G5_CSC_OFFSET;
433 	isc->offsets.cbc = ISC_SAMA7G5_CBC_OFFSET;
434 	isc->offsets.sub422 = ISC_SAMA7G5_SUB422_OFFSET;
435 	isc->offsets.sub420 = ISC_SAMA7G5_SUB420_OFFSET;
436 	isc->offsets.rlp = ISC_SAMA7G5_RLP_OFFSET;
437 	isc->offsets.his = ISC_SAMA7G5_HIS_OFFSET;
438 	isc->offsets.dma = ISC_SAMA7G5_DMA_OFFSET;
439 	isc->offsets.version = ISC_SAMA7G5_VERSION_OFFSET;
440 	isc->offsets.his_entry = ISC_SAMA7G5_HIS_ENTRY_OFFSET;
441 
442 	isc->controller_formats = sama7g5_controller_formats;
443 	isc->controller_formats_size = ARRAY_SIZE(sama7g5_controller_formats);
444 	isc->formats_list = sama7g5_formats_list;
445 	isc->formats_list_size = ARRAY_SIZE(sama7g5_formats_list);
446 
447 	/* sama7g5-isc RAM access port is full AXI4 - 32 bits per beat */
448 	isc->dcfg = ISC_DCFG_YMBSIZE_BEATS32 | ISC_DCFG_CMBSIZE_BEATS32;
449 
450 	ret = isc_pipeline_init(isc);
451 	if (ret)
452 		return ret;
453 
454 	isc->hclock = devm_clk_get(dev, "hclock");
455 	if (IS_ERR(isc->hclock)) {
456 		ret = PTR_ERR(isc->hclock);
457 		dev_err(dev, "failed to get hclock: %d\n", ret);
458 		return ret;
459 	}
460 
461 	ret = clk_prepare_enable(isc->hclock);
462 	if (ret) {
463 		dev_err(dev, "failed to enable hclock: %d\n", ret);
464 		return ret;
465 	}
466 
467 	ret = isc_clk_init(isc);
468 	if (ret) {
469 		dev_err(dev, "failed to init isc clock: %d\n", ret);
470 		goto unprepare_hclk;
471 	}
472 
473 	isc->ispck = isc->isc_clks[ISC_ISPCK].clk;
474 
475 	ret = clk_prepare_enable(isc->ispck);
476 	if (ret) {
477 		dev_err(dev, "failed to enable ispck: %d\n", ret);
478 		goto unprepare_hclk;
479 	}
480 
481 	/* ispck should be greater or equal to hclock */
482 	ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
483 	if (ret) {
484 		dev_err(dev, "failed to set ispck rate: %d\n", ret);
485 		goto unprepare_clk;
486 	}
487 
488 	ret = v4l2_device_register(dev, &isc->v4l2_dev);
489 	if (ret) {
490 		dev_err(dev, "unable to register v4l2 device.\n");
491 		goto unprepare_clk;
492 	}
493 
494 	ret = xisc_parse_dt(dev, isc);
495 	if (ret) {
496 		dev_err(dev, "fail to parse device tree\n");
497 		goto unregister_v4l2_device;
498 	}
499 
500 	if (list_empty(&isc->subdev_entities)) {
501 		dev_err(dev, "no subdev found\n");
502 		ret = -ENODEV;
503 		goto unregister_v4l2_device;
504 	}
505 
506 	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
507 		struct v4l2_async_subdev *asd;
508 
509 		v4l2_async_notifier_init(&subdev_entity->notifier);
510 
511 		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
512 					&subdev_entity->notifier,
513 					of_fwnode_handle(subdev_entity->epn),
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 = &isc_async_ops;
525 
526 		ret = v4l2_async_notifier_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 	regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver);
542 	dev_info(dev, "Microchip XISC version %x\n", ver);
543 
544 	return 0;
545 
546 cleanup_subdev:
547 	isc_subdev_cleanup(isc);
548 
549 unregister_v4l2_device:
550 	v4l2_device_unregister(&isc->v4l2_dev);
551 
552 unprepare_clk:
553 	clk_disable_unprepare(isc->ispck);
554 unprepare_hclk:
555 	clk_disable_unprepare(isc->hclock);
556 
557 	isc_clk_cleanup(isc);
558 
559 	return ret;
560 }
561 
microchip_xisc_remove(struct platform_device * pdev)562 static int microchip_xisc_remove(struct platform_device *pdev)
563 {
564 	struct isc_device *isc = platform_get_drvdata(pdev);
565 
566 	pm_runtime_disable(&pdev->dev);
567 
568 	isc_subdev_cleanup(isc);
569 
570 	v4l2_device_unregister(&isc->v4l2_dev);
571 
572 	clk_disable_unprepare(isc->ispck);
573 	clk_disable_unprepare(isc->hclock);
574 
575 	isc_clk_cleanup(isc);
576 
577 	return 0;
578 }
579 
xisc_runtime_suspend(struct device * dev)580 static int __maybe_unused xisc_runtime_suspend(struct device *dev)
581 {
582 	struct isc_device *isc = dev_get_drvdata(dev);
583 
584 	clk_disable_unprepare(isc->ispck);
585 	clk_disable_unprepare(isc->hclock);
586 
587 	return 0;
588 }
589 
xisc_runtime_resume(struct device * dev)590 static int __maybe_unused xisc_runtime_resume(struct device *dev)
591 {
592 	struct isc_device *isc = dev_get_drvdata(dev);
593 	int ret;
594 
595 	ret = clk_prepare_enable(isc->hclock);
596 	if (ret)
597 		return ret;
598 
599 	ret = clk_prepare_enable(isc->ispck);
600 	if (ret)
601 		clk_disable_unprepare(isc->hclock);
602 
603 	return ret;
604 }
605 
606 static const struct dev_pm_ops microchip_xisc_dev_pm_ops = {
607 	SET_RUNTIME_PM_OPS(xisc_runtime_suspend, xisc_runtime_resume, NULL)
608 };
609 
610 static const struct of_device_id microchip_xisc_of_match[] = {
611 	{ .compatible = "microchip,sama7g5-isc" },
612 	{ }
613 };
614 MODULE_DEVICE_TABLE(of, microchip_xisc_of_match);
615 
616 static struct platform_driver microchip_xisc_driver = {
617 	.probe	= microchip_xisc_probe,
618 	.remove	= microchip_xisc_remove,
619 	.driver	= {
620 		.name		= "microchip-sama7g5-xisc",
621 		.pm		= &microchip_xisc_dev_pm_ops,
622 		.of_match_table = of_match_ptr(microchip_xisc_of_match),
623 	},
624 };
625 
626 module_platform_driver(microchip_xisc_driver);
627 
628 MODULE_AUTHOR("Eugen Hristev <eugen.hristev@microchip.com>");
629 MODULE_DESCRIPTION("The V4L2 driver for Microchip-XISC");
630 MODULE_LICENSE("GPL v2");
631