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