• 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 		.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 
isc_sama5d2_config_csc(struct isc_device * isc)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 
isc_sama5d2_config_cbc(struct isc_device * isc)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 
isc_sama5d2_config_cc(struct isc_device * isc)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 
isc_sama5d2_config_ctrls(struct isc_device * isc,const struct v4l2_ctrl_ops * ops)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 
isc_sama5d2_config_dpc(struct isc_device * isc)250 static void isc_sama5d2_config_dpc(struct isc_device *isc)
251 {
252 	/* This module is not present on sama5d2 pipeline */
253 }
254 
isc_sama5d2_config_gam(struct isc_device * isc)255 static void isc_sama5d2_config_gam(struct isc_device *isc)
256 {
257 	/* No specific gamma configuration */
258 }
259 
isc_sama5d2_config_rlp(struct isc_device * isc)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 
isc_sama5d2_adapt_pipeline(struct isc_device * isc)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 
isc_parse_dt(struct device * dev,struct isc_device * isc)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;
337 	struct isc_subdev_entity *subdev_entity;
338 	unsigned int flags;
339 	int ret = -EINVAL;
340 
341 	INIT_LIST_HEAD(&isc->subdev_entities);
342 
343 	for_each_endpoint_of_node(np, epn) {
344 		struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 };
345 
346 		ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn),
347 						 &v4l2_epn);
348 		if (ret) {
349 			ret = -EINVAL;
350 			dev_err(dev, "Could not parse the endpoint\n");
351 			break;
352 		}
353 
354 		subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity),
355 					     GFP_KERNEL);
356 		if (!subdev_entity) {
357 			ret = -ENOMEM;
358 			break;
359 		}
360 		subdev_entity->epn = epn;
361 
362 		flags = v4l2_epn.bus.parallel.flags;
363 
364 		if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
365 			subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_LOW;
366 
367 		if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
368 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_LOW;
369 
370 		if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
371 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
372 
373 		if (v4l2_epn.bus_type == V4L2_MBUS_BT656)
374 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_CCIR_CRC |
375 					ISC_PFE_CFG0_CCIR656;
376 
377 		list_add_tail(&subdev_entity->list, &isc->subdev_entities);
378 	}
379 	of_node_put(epn);
380 
381 	return ret;
382 }
383 
atmel_isc_probe(struct platform_device * pdev)384 static int atmel_isc_probe(struct platform_device *pdev)
385 {
386 	struct device *dev = &pdev->dev;
387 	struct isc_device *isc;
388 	void __iomem *io_base;
389 	struct isc_subdev_entity *subdev_entity;
390 	int irq;
391 	int ret;
392 	u32 ver;
393 
394 	isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL);
395 	if (!isc)
396 		return -ENOMEM;
397 
398 	platform_set_drvdata(pdev, isc);
399 	isc->dev = dev;
400 
401 	io_base = devm_platform_ioremap_resource(pdev, 0);
402 	if (IS_ERR(io_base))
403 		return PTR_ERR(io_base);
404 
405 	isc->regmap = devm_regmap_init_mmio(dev, io_base, &atmel_isc_regmap_config);
406 	if (IS_ERR(isc->regmap)) {
407 		ret = PTR_ERR(isc->regmap);
408 		dev_err(dev, "failed to init register map: %d\n", ret);
409 		return ret;
410 	}
411 
412 	irq = platform_get_irq(pdev, 0);
413 	if (irq < 0)
414 		return irq;
415 
416 	ret = devm_request_irq(dev, irq, atmel_isc_interrupt, 0,
417 			       "atmel-sama5d2-isc", isc);
418 	if (ret < 0) {
419 		dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
420 			irq, ret);
421 		return ret;
422 	}
423 
424 	isc->gamma_table = isc_sama5d2_gamma_table;
425 	isc->gamma_max = 2;
426 
427 	isc->max_width = ISC_SAMA5D2_MAX_SUPPORT_WIDTH;
428 	isc->max_height = ISC_SAMA5D2_MAX_SUPPORT_HEIGHT;
429 
430 	isc->config_dpc = isc_sama5d2_config_dpc;
431 	isc->config_csc = isc_sama5d2_config_csc;
432 	isc->config_cbc = isc_sama5d2_config_cbc;
433 	isc->config_cc = isc_sama5d2_config_cc;
434 	isc->config_gam = isc_sama5d2_config_gam;
435 	isc->config_rlp = isc_sama5d2_config_rlp;
436 	isc->config_ctrls = isc_sama5d2_config_ctrls;
437 
438 	isc->adapt_pipeline = isc_sama5d2_adapt_pipeline;
439 
440 	isc->offsets.csc = ISC_SAMA5D2_CSC_OFFSET;
441 	isc->offsets.cbc = ISC_SAMA5D2_CBC_OFFSET;
442 	isc->offsets.sub422 = ISC_SAMA5D2_SUB422_OFFSET;
443 	isc->offsets.sub420 = ISC_SAMA5D2_SUB420_OFFSET;
444 	isc->offsets.rlp = ISC_SAMA5D2_RLP_OFFSET;
445 	isc->offsets.his = ISC_SAMA5D2_HIS_OFFSET;
446 	isc->offsets.dma = ISC_SAMA5D2_DMA_OFFSET;
447 	isc->offsets.version = ISC_SAMA5D2_VERSION_OFFSET;
448 	isc->offsets.his_entry = ISC_SAMA5D2_HIS_ENTRY_OFFSET;
449 
450 	isc->controller_formats = sama5d2_controller_formats;
451 	isc->controller_formats_size = ARRAY_SIZE(sama5d2_controller_formats);
452 	isc->formats_list = sama5d2_formats_list;
453 	isc->formats_list_size = ARRAY_SIZE(sama5d2_formats_list);
454 
455 	/* sama5d2-isc - 8 bits per beat */
456 	isc->dcfg = ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8;
457 
458 	/* sama5d2-isc : ISPCK is required and mandatory */
459 	isc->ispck_required = true;
460 
461 	ret = atmel_isc_pipeline_init(isc);
462 	if (ret)
463 		return ret;
464 
465 	isc->hclock = devm_clk_get(dev, "hclock");
466 	if (IS_ERR(isc->hclock)) {
467 		ret = PTR_ERR(isc->hclock);
468 		dev_err(dev, "failed to get hclock: %d\n", ret);
469 		return ret;
470 	}
471 
472 	ret = clk_prepare_enable(isc->hclock);
473 	if (ret) {
474 		dev_err(dev, "failed to enable hclock: %d\n", ret);
475 		return ret;
476 	}
477 
478 	ret = atmel_isc_clk_init(isc);
479 	if (ret) {
480 		dev_err(dev, "failed to init isc clock: %d\n", ret);
481 		goto unprepare_hclk;
482 	}
483 	ret = v4l2_device_register(dev, &isc->v4l2_dev);
484 	if (ret) {
485 		dev_err(dev, "unable to register v4l2 device.\n");
486 		goto unprepare_clk;
487 	}
488 
489 	ret = isc_parse_dt(dev, isc);
490 	if (ret) {
491 		dev_err(dev, "fail to parse device tree\n");
492 		goto unregister_v4l2_device;
493 	}
494 
495 	if (list_empty(&isc->subdev_entities)) {
496 		dev_err(dev, "no subdev found\n");
497 		ret = -ENODEV;
498 		goto unregister_v4l2_device;
499 	}
500 
501 	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
502 		struct v4l2_async_connection *asd;
503 		struct fwnode_handle *fwnode =
504 			of_fwnode_handle(subdev_entity->epn);
505 
506 		v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
507 
508 		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
509 						      fwnode,
510 						      struct v4l2_async_connection);
511 
512 		of_node_put(subdev_entity->epn);
513 		subdev_entity->epn = NULL;
514 
515 		if (IS_ERR(asd)) {
516 			ret = PTR_ERR(asd);
517 			goto cleanup_subdev;
518 		}
519 
520 		subdev_entity->notifier.ops = &atmel_isc_async_ops;
521 
522 		ret = v4l2_async_nf_register(&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 disable_pm;
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 disable_pm:
560 	pm_runtime_disable(dev);
561 
562 cleanup_subdev:
563 	atmel_isc_subdev_cleanup(isc);
564 
565 unregister_v4l2_device:
566 	v4l2_device_unregister(&isc->v4l2_dev);
567 
568 unprepare_hclk:
569 	clk_disable_unprepare(isc->hclock);
570 
571 	atmel_isc_clk_cleanup(isc);
572 
573 	return ret;
574 }
575 
atmel_isc_remove(struct platform_device * pdev)576 static void atmel_isc_remove(struct platform_device *pdev)
577 {
578 	struct isc_device *isc = platform_get_drvdata(pdev);
579 
580 	pm_runtime_disable(&pdev->dev);
581 
582 	atmel_isc_subdev_cleanup(isc);
583 
584 	v4l2_device_unregister(&isc->v4l2_dev);
585 
586 	clk_disable_unprepare(isc->ispck);
587 	clk_disable_unprepare(isc->hclock);
588 
589 	atmel_isc_clk_cleanup(isc);
590 }
591 
isc_runtime_suspend(struct device * dev)592 static int __maybe_unused isc_runtime_suspend(struct device *dev)
593 {
594 	struct isc_device *isc = dev_get_drvdata(dev);
595 
596 	clk_disable_unprepare(isc->ispck);
597 	clk_disable_unprepare(isc->hclock);
598 
599 	return 0;
600 }
601 
isc_runtime_resume(struct device * dev)602 static int __maybe_unused isc_runtime_resume(struct device *dev)
603 {
604 	struct isc_device *isc = dev_get_drvdata(dev);
605 	int ret;
606 
607 	ret = clk_prepare_enable(isc->hclock);
608 	if (ret)
609 		return ret;
610 
611 	ret = clk_prepare_enable(isc->ispck);
612 	if (ret)
613 		clk_disable_unprepare(isc->hclock);
614 
615 	return ret;
616 }
617 
618 static const struct dev_pm_ops atmel_isc_dev_pm_ops = {
619 	SET_RUNTIME_PM_OPS(isc_runtime_suspend, isc_runtime_resume, NULL)
620 };
621 
622 #if IS_ENABLED(CONFIG_OF)
623 static const struct of_device_id atmel_isc_of_match[] = {
624 	{ .compatible = "atmel,sama5d2-isc" },
625 	{ }
626 };
627 MODULE_DEVICE_TABLE(of, atmel_isc_of_match);
628 #endif
629 
630 static struct platform_driver atmel_isc_driver = {
631 	.probe	= atmel_isc_probe,
632 	.remove_new = atmel_isc_remove,
633 	.driver	= {
634 		.name		= "atmel-sama5d2-isc",
635 		.pm		= &atmel_isc_dev_pm_ops,
636 		.of_match_table = of_match_ptr(atmel_isc_of_match),
637 	},
638 };
639 
640 module_platform_driver(atmel_isc_driver);
641 
642 MODULE_AUTHOR("Songjun Wu");
643 MODULE_DESCRIPTION("The V4L2 driver for Atmel-ISC");
644 MODULE_LICENSE("GPL v2");
645