Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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* */
 60static 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* */
121static 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
217static 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
236static 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
246static 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
259static 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
270static void isc_sama5d2_config_dpc(struct isc_device *isc)
271{
272	/* This module is not present on sama5d2 pipeline */
273}
274
275static void isc_sama5d2_config_gam(struct isc_device *isc)
276{
277	/* No specific gamma configuration */
278}
279
280static 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
306static 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 */
312static 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
353static 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
408static int microchip_isc_probe(struct platform_device *pdev)
409{
410	struct device *dev = &pdev->dev;
411	struct isc_device *isc;
412	struct resource *res;
413	void __iomem *io_base;
414	struct isc_subdev_entity *subdev_entity;
415	int irq;
416	int ret;
417	u32 ver;
418
419	isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL);
420	if (!isc)
421		return -ENOMEM;
422
423	platform_set_drvdata(pdev, isc);
424	isc->dev = dev;
425
426	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
427	io_base = devm_ioremap_resource(dev, res);
428	if (IS_ERR(io_base))
429		return PTR_ERR(io_base);
430
431	isc->regmap = devm_regmap_init_mmio(dev, io_base, &microchip_isc_regmap_config);
432	if (IS_ERR(isc->regmap)) {
433		ret = PTR_ERR(isc->regmap);
434		dev_err(dev, "failed to init register map: %d\n", ret);
435		return ret;
436	}
437
438	irq = platform_get_irq(pdev, 0);
439	if (irq < 0)
440		return irq;
441
442	ret = devm_request_irq(dev, irq, microchip_isc_interrupt, 0,
443			       "microchip-sama5d2-isc", isc);
444	if (ret < 0) {
445		dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
446			irq, ret);
447		return ret;
448	}
449
450	isc->gamma_table = isc_sama5d2_gamma_table;
451	isc->gamma_max = 2;
452
453	isc->max_width = ISC_SAMA5D2_MAX_SUPPORT_WIDTH;
454	isc->max_height = ISC_SAMA5D2_MAX_SUPPORT_HEIGHT;
455
456	isc->config_dpc = isc_sama5d2_config_dpc;
457	isc->config_csc = isc_sama5d2_config_csc;
458	isc->config_cbc = isc_sama5d2_config_cbc;
459	isc->config_cc = isc_sama5d2_config_cc;
460	isc->config_gam = isc_sama5d2_config_gam;
461	isc->config_rlp = isc_sama5d2_config_rlp;
462	isc->config_ctrls = isc_sama5d2_config_ctrls;
463
464	isc->adapt_pipeline = isc_sama5d2_adapt_pipeline;
465
466	isc->offsets.csc = ISC_SAMA5D2_CSC_OFFSET;
467	isc->offsets.cbc = ISC_SAMA5D2_CBC_OFFSET;
468	isc->offsets.sub422 = ISC_SAMA5D2_SUB422_OFFSET;
469	isc->offsets.sub420 = ISC_SAMA5D2_SUB420_OFFSET;
470	isc->offsets.rlp = ISC_SAMA5D2_RLP_OFFSET;
471	isc->offsets.his = ISC_SAMA5D2_HIS_OFFSET;
472	isc->offsets.dma = ISC_SAMA5D2_DMA_OFFSET;
473	isc->offsets.version = ISC_SAMA5D2_VERSION_OFFSET;
474	isc->offsets.his_entry = ISC_SAMA5D2_HIS_ENTRY_OFFSET;
475
476	isc->controller_formats = sama5d2_controller_formats;
477	isc->controller_formats_size = ARRAY_SIZE(sama5d2_controller_formats);
478	isc->formats_list = sama5d2_formats_list;
479	isc->formats_list_size = ARRAY_SIZE(sama5d2_formats_list);
480
481	/* sama5d2-isc - 8 bits per beat */
482	isc->dcfg = ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8;
483
484	/* sama5d2-isc : ISPCK is required and mandatory */
485	isc->ispck_required = true;
486
487	ret = microchip_isc_pipeline_init(isc);
488	if (ret)
489		return ret;
490
491	isc->hclock = devm_clk_get(dev, "hclock");
492	if (IS_ERR(isc->hclock)) {
493		ret = PTR_ERR(isc->hclock);
494		dev_err(dev, "failed to get hclock: %d\n", ret);
495		return ret;
496	}
497
498	ret = clk_prepare_enable(isc->hclock);
499	if (ret) {
500		dev_err(dev, "failed to enable hclock: %d\n", ret);
501		return ret;
502	}
503
504	ret = microchip_isc_clk_init(isc);
505	if (ret) {
506		dev_err(dev, "failed to init isc clock: %d\n", ret);
507		goto unprepare_hclk;
508	}
509	ret = v4l2_device_register(dev, &isc->v4l2_dev);
510	if (ret) {
511		dev_err(dev, "unable to register v4l2 device.\n");
512		goto unprepare_clk;
513	}
514
515	ret = isc_parse_dt(dev, isc);
516	if (ret) {
517		dev_err(dev, "fail to parse device tree\n");
518		goto unregister_v4l2_device;
519	}
520
521	if (list_empty(&isc->subdev_entities)) {
522		dev_err(dev, "no subdev found\n");
523		ret = -ENODEV;
524		goto unregister_v4l2_device;
525	}
526
527	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
528		struct v4l2_async_subdev *asd;
529		struct fwnode_handle *fwnode =
530			of_fwnode_handle(subdev_entity->epn);
531
532		v4l2_async_nf_init(&subdev_entity->notifier);
533
534		asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
535						      fwnode,
536						      struct v4l2_async_subdev);
537
538		of_node_put(subdev_entity->epn);
539		subdev_entity->epn = NULL;
540
541		if (IS_ERR(asd)) {
542			ret = PTR_ERR(asd);
543			goto cleanup_subdev;
544		}
545
546		subdev_entity->notifier.ops = &microchip_isc_async_ops;
547
548		ret = v4l2_async_nf_register(&isc->v4l2_dev,
549					     &subdev_entity->notifier);
550		if (ret) {
551			dev_err(dev, "fail to register async notifier\n");
552			goto cleanup_subdev;
553		}
554
555		if (video_is_registered(&isc->video_dev))
556			break;
557	}
558
559	regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver);
560
561	ret = isc_mc_init(isc, ver);
562	if (ret < 0)
563		goto isc_probe_mc_init_err;
564
565	pm_runtime_set_active(dev);
566	pm_runtime_enable(dev);
567	pm_request_idle(dev);
568
569	isc->ispck = isc->isc_clks[ISC_ISPCK].clk;
570
571	ret = clk_prepare_enable(isc->ispck);
572	if (ret) {
573		dev_err(dev, "failed to enable ispck: %d\n", ret);
574		goto disable_pm;
575	}
576
577	/* ispck should be greater or equal to hclock */
578	ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
579	if (ret) {
580		dev_err(dev, "failed to set ispck rate: %d\n", ret);
581		goto unprepare_clk;
582	}
583
584	dev_info(dev, "Microchip ISC version %x\n", ver);
585
586	return 0;
587
588unprepare_clk:
589	clk_disable_unprepare(isc->ispck);
590
591disable_pm:
592	pm_runtime_disable(dev);
593
594isc_probe_mc_init_err:
595	isc_mc_cleanup(isc);
596
597cleanup_subdev:
598	microchip_isc_subdev_cleanup(isc);
599
600unregister_v4l2_device:
601	v4l2_device_unregister(&isc->v4l2_dev);
602
603unprepare_hclk:
604	clk_disable_unprepare(isc->hclock);
605
606	microchip_isc_clk_cleanup(isc);
607
608	return ret;
609}
610
611static int microchip_isc_remove(struct platform_device *pdev)
612{
613	struct isc_device *isc = platform_get_drvdata(pdev);
614
615	pm_runtime_disable(&pdev->dev);
616
617	isc_mc_cleanup(isc);
618
619	microchip_isc_subdev_cleanup(isc);
620
621	v4l2_device_unregister(&isc->v4l2_dev);
622
623	clk_disable_unprepare(isc->ispck);
624	clk_disable_unprepare(isc->hclock);
625
626	microchip_isc_clk_cleanup(isc);
627
628	return 0;
629}
630
631static int __maybe_unused isc_runtime_suspend(struct device *dev)
632{
633	struct isc_device *isc = dev_get_drvdata(dev);
634
635	clk_disable_unprepare(isc->ispck);
636	clk_disable_unprepare(isc->hclock);
637
638	return 0;
639}
640
641static int __maybe_unused isc_runtime_resume(struct device *dev)
642{
643	struct isc_device *isc = dev_get_drvdata(dev);
644	int ret;
645
646	ret = clk_prepare_enable(isc->hclock);
647	if (ret)
648		return ret;
649
650	ret = clk_prepare_enable(isc->ispck);
651	if (ret)
652		clk_disable_unprepare(isc->hclock);
653
654	return ret;
655}
656
657static const struct dev_pm_ops microchip_isc_dev_pm_ops = {
658	SET_RUNTIME_PM_OPS(isc_runtime_suspend, isc_runtime_resume, NULL)
659};
660
661#if IS_ENABLED(CONFIG_OF)
662static const struct of_device_id microchip_isc_of_match[] = {
663	{ .compatible = "atmel,sama5d2-isc" },
664	{ }
665};
666MODULE_DEVICE_TABLE(of, microchip_isc_of_match);
667#endif
668
669static struct platform_driver microchip_isc_driver = {
670	.probe	= microchip_isc_probe,
671	.remove	= microchip_isc_remove,
672	.driver	= {
673		.name		= "microchip-sama5d2-isc",
674		.pm		= &microchip_isc_dev_pm_ops,
675		.of_match_table = of_match_ptr(microchip_isc_of_match),
676	},
677};
678
679module_platform_driver(microchip_isc_driver);
680
681MODULE_AUTHOR("Songjun Wu");
682MODULE_DESCRIPTION("The V4L2 driver for Microchip-ISC");
683MODULE_LICENSE("GPL v2");