• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_MASK) == 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 
503 		v4l2_async_notifier_init(&subdev_entity->notifier);
504 
505 		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
506 					&subdev_entity->notifier,
507 					of_fwnode_handle(subdev_entity->epn),
508 					struct v4l2_async_subdev);
509 
510 		of_node_put(subdev_entity->epn);
511 		subdev_entity->epn = NULL;
512 
513 		if (IS_ERR(asd)) {
514 			ret = PTR_ERR(asd);
515 			goto cleanup_subdev;
516 		}
517 
518 		subdev_entity->notifier.ops = &isc_async_ops;
519 
520 		ret = v4l2_async_notifier_register(&isc->v4l2_dev,
521 						   &subdev_entity->notifier);
522 		if (ret) {
523 			dev_err(dev, "fail to register async notifier\n");
524 			goto cleanup_subdev;
525 		}
526 
527 		if (video_is_registered(&isc->video_dev))
528 			break;
529 	}
530 
531 	pm_runtime_set_active(dev);
532 	pm_runtime_enable(dev);
533 	pm_request_idle(dev);
534 
535 	isc->ispck = isc->isc_clks[ISC_ISPCK].clk;
536 
537 	ret = clk_prepare_enable(isc->ispck);
538 	if (ret) {
539 		dev_err(dev, "failed to enable ispck: %d\n", ret);
540 		goto disable_pm;
541 	}
542 
543 	/* ispck should be greater or equal to hclock */
544 	ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
545 	if (ret) {
546 		dev_err(dev, "failed to set ispck rate: %d\n", ret);
547 		goto unprepare_clk;
548 	}
549 
550 	regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver);
551 	dev_info(dev, "Microchip ISC version %x\n", ver);
552 
553 	return 0;
554 
555 unprepare_clk:
556 	clk_disable_unprepare(isc->ispck);
557 
558 disable_pm:
559 	pm_runtime_disable(dev);
560 
561 cleanup_subdev:
562 	isc_subdev_cleanup(isc);
563 
564 unregister_v4l2_device:
565 	v4l2_device_unregister(&isc->v4l2_dev);
566 
567 unprepare_hclk:
568 	clk_disable_unprepare(isc->hclock);
569 
570 	isc_clk_cleanup(isc);
571 
572 	return ret;
573 }
574 
atmel_isc_remove(struct platform_device * pdev)575 static int atmel_isc_remove(struct platform_device *pdev)
576 {
577 	struct isc_device *isc = platform_get_drvdata(pdev);
578 
579 	pm_runtime_disable(&pdev->dev);
580 
581 	isc_subdev_cleanup(isc);
582 
583 	v4l2_device_unregister(&isc->v4l2_dev);
584 
585 	clk_disable_unprepare(isc->ispck);
586 	clk_disable_unprepare(isc->hclock);
587 
588 	isc_clk_cleanup(isc);
589 
590 	return 0;
591 }
592 
isc_runtime_suspend(struct device * dev)593 static int __maybe_unused isc_runtime_suspend(struct device *dev)
594 {
595 	struct isc_device *isc = dev_get_drvdata(dev);
596 
597 	clk_disable_unprepare(isc->ispck);
598 	clk_disable_unprepare(isc->hclock);
599 
600 	return 0;
601 }
602 
isc_runtime_resume(struct device * dev)603 static int __maybe_unused isc_runtime_resume(struct device *dev)
604 {
605 	struct isc_device *isc = dev_get_drvdata(dev);
606 	int ret;
607 
608 	ret = clk_prepare_enable(isc->hclock);
609 	if (ret)
610 		return ret;
611 
612 	ret = clk_prepare_enable(isc->ispck);
613 	if (ret)
614 		clk_disable_unprepare(isc->hclock);
615 
616 	return ret;
617 }
618 
619 static const struct dev_pm_ops atmel_isc_dev_pm_ops = {
620 	SET_RUNTIME_PM_OPS(isc_runtime_suspend, isc_runtime_resume, NULL)
621 };
622 
623 #if IS_ENABLED(CONFIG_OF)
624 static const struct of_device_id atmel_isc_of_match[] = {
625 	{ .compatible = "atmel,sama5d2-isc" },
626 	{ }
627 };
628 MODULE_DEVICE_TABLE(of, atmel_isc_of_match);
629 #endif
630 
631 static struct platform_driver atmel_isc_driver = {
632 	.probe	= atmel_isc_probe,
633 	.remove	= atmel_isc_remove,
634 	.driver	= {
635 		.name		= "atmel-sama5d2-isc",
636 		.pm		= &atmel_isc_dev_pm_ops,
637 		.of_match_table = of_match_ptr(atmel_isc_of_match),
638 	},
639 };
640 
641 module_platform_driver(atmel_isc_driver);
642 
643 MODULE_AUTHOR("Songjun Wu");
644 MODULE_DESCRIPTION("The V4L2 driver for Atmel-ISC");
645 MODULE_LICENSE("GPL v2");
646