GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / media / platform / microchip / microchip-sama5d2-isc.c
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
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
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
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
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
270 static void isc_sama5d2_config_dpc(struct isc_device *isc)
271 {
272         /* This module is not present on sama5d2 pipeline */
273 }
274
275 static void isc_sama5d2_config_gam(struct isc_device *isc)
276 {
277         /* No specific gamma configuration */
278 }
279
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
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
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
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
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
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
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");