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 	/* sama5d2-isc : ISPCK is required and mandatory */
458 	isc->ispck_required = true;
459 
460 	ret = isc_pipeline_init(isc);
461 	if (ret)
462 		return ret;
463 
464 	isc->hclock = devm_clk_get(dev, "hclock");
465 	if (IS_ERR(isc->hclock)) {
466 		ret = PTR_ERR(isc->hclock);
467 		dev_err(dev, "failed to get hclock: %d\n", ret);
468 		return ret;
469 	}
470 
471 	ret = clk_prepare_enable(isc->hclock);
472 	if (ret) {
473 		dev_err(dev, "failed to enable hclock: %d\n", ret);
474 		return ret;
475 	}
476 
477 	ret = isc_clk_init(isc);
478 	if (ret) {
479 		dev_err(dev, "failed to init isc clock: %d\n", ret);
480 		goto unprepare_hclk;
481 	}
482 	ret = v4l2_device_register(dev, &isc->v4l2_dev);
483 	if (ret) {
484 		dev_err(dev, "unable to register v4l2 device.\n");
485 		goto unprepare_clk;
486 	}
487 
488 	ret = isc_parse_dt(dev, isc);
489 	if (ret) {
490 		dev_err(dev, "fail to parse device tree\n");
491 		goto unregister_v4l2_device;
492 	}
493 
494 	if (list_empty(&isc->subdev_entities)) {
495 		dev_err(dev, "no subdev found\n");
496 		ret = -ENODEV;
497 		goto unregister_v4l2_device;
498 	}
499 
500 	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
501 		struct v4l2_async_subdev *asd;
502 		struct fwnode_handle *fwnode =
503 			of_fwnode_handle(subdev_entity->epn);
504 
505 		v4l2_async_nf_init(&subdev_entity->notifier);
506 
507 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
508 						      fwnode,
509 						      struct v4l2_async_subdev);
510 
511 		of_node_put(subdev_entity->epn);
512 		subdev_entity->epn = NULL;
513 
514 		if (IS_ERR(asd)) {
515 			ret = PTR_ERR(asd);
516 			goto cleanup_subdev;
517 		}
518 
519 		subdev_entity->notifier.ops = &isc_async_ops;
520 
521 		ret = v4l2_async_nf_register(&isc->v4l2_dev,
522 					     &subdev_entity->notifier);
523 		if (ret) {
524 			dev_err(dev, "fail to register async notifier\n");
525 			goto cleanup_subdev;
526 		}
527 
528 		if (video_is_registered(&isc->video_dev))
529 			break;
530 	}
531 
532 	pm_runtime_set_active(dev);
533 	pm_runtime_enable(dev);
534 	pm_request_idle(dev);
535 
536 	isc->ispck = isc->isc_clks[ISC_ISPCK].clk;
537 
538 	ret = clk_prepare_enable(isc->ispck);
539 	if (ret) {
540 		dev_err(dev, "failed to enable ispck: %d\n", ret);
541 		goto cleanup_subdev;
542 	}
543 
544 	/* ispck should be greater or equal to hclock */
545 	ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
546 	if (ret) {
547 		dev_err(dev, "failed to set ispck rate: %d\n", ret);
548 		goto unprepare_clk;
549 	}
550 
551 	regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver);
552 	dev_info(dev, "Microchip ISC version %x\n", ver);
553 
554 	return 0;
555 
556 unprepare_clk:
557 	clk_disable_unprepare(isc->ispck);
558 
559 cleanup_subdev:
560 	isc_subdev_cleanup(isc);
561 
562 unregister_v4l2_device:
563 	v4l2_device_unregister(&isc->v4l2_dev);
564 
565 unprepare_hclk:
566 	clk_disable_unprepare(isc->hclock);
567 
568 	isc_clk_cleanup(isc);
569 
570 	return ret;
571 }
572 
atmel_isc_remove(struct platform_device * pdev)573 static int atmel_isc_remove(struct platform_device *pdev)
574 {
575 	struct isc_device *isc = platform_get_drvdata(pdev);
576 
577 	pm_runtime_disable(&pdev->dev);
578 
579 	isc_subdev_cleanup(isc);
580 
581 	v4l2_device_unregister(&isc->v4l2_dev);
582 
583 	clk_disable_unprepare(isc->ispck);
584 	clk_disable_unprepare(isc->hclock);
585 
586 	isc_clk_cleanup(isc);
587 
588 	return 0;
589 }
590 
isc_runtime_suspend(struct device * dev)591 static int __maybe_unused isc_runtime_suspend(struct device *dev)
592 {
593 	struct isc_device *isc = dev_get_drvdata(dev);
594 
595 	clk_disable_unprepare(isc->ispck);
596 	clk_disable_unprepare(isc->hclock);
597 
598 	return 0;
599 }
600 
isc_runtime_resume(struct device * dev)601 static int __maybe_unused isc_runtime_resume(struct device *dev)
602 {
603 	struct isc_device *isc = dev_get_drvdata(dev);
604 	int ret;
605 
606 	ret = clk_prepare_enable(isc->hclock);
607 	if (ret)
608 		return ret;
609 
610 	ret = clk_prepare_enable(isc->ispck);
611 	if (ret)
612 		clk_disable_unprepare(isc->hclock);
613 
614 	return ret;
615 }
616 
617 static const struct dev_pm_ops atmel_isc_dev_pm_ops = {
618 	SET_RUNTIME_PM_OPS(isc_runtime_suspend, isc_runtime_resume, NULL)
619 };
620 
621 #if IS_ENABLED(CONFIG_OF)
622 static const struct of_device_id atmel_isc_of_match[] = {
623 	{ .compatible = "atmel,sama5d2-isc" },
624 	{ }
625 };
626 MODULE_DEVICE_TABLE(of, atmel_isc_of_match);
627 #endif
628 
629 static struct platform_driver atmel_isc_driver = {
630 	.probe	= atmel_isc_probe,
631 	.remove	= atmel_isc_remove,
632 	.driver	= {
633 		.name		= "atmel-sama5d2-isc",
634 		.pm		= &atmel_isc_dev_pm_ops,
635 		.of_match_table = of_match_ptr(atmel_isc_of_match),
636 	},
637 };
638 
639 module_platform_driver(atmel_isc_driver);
640 
641 MODULE_AUTHOR("Songjun Wu");
642 MODULE_DESCRIPTION("The V4L2 driver for Atmel-ISC");
643 MODULE_LICENSE("GPL v2");
644