191b4e487SEugen Hristev // SPDX-License-Identifier: GPL-2.0
291b4e487SEugen Hristev /*
391b4e487SEugen Hristev * Microchip Image Sensor Controller (ISC) driver
491b4e487SEugen Hristev *
591b4e487SEugen Hristev * Copyright (C) 2016-2019 Microchip Technology, Inc.
691b4e487SEugen Hristev *
791b4e487SEugen Hristev * Author: Songjun Wu
891b4e487SEugen Hristev * Author: Eugen Hristev <eugen.hristev@microchip.com>
991b4e487SEugen Hristev *
1091b4e487SEugen Hristev *
1191b4e487SEugen Hristev * Sensor-->PFE-->WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB-->RLP-->DMA
1291b4e487SEugen Hristev *
1391b4e487SEugen Hristev * ISC video pipeline integrates the following submodules:
1491b4e487SEugen Hristev * PFE: Parallel Front End to sample the camera sensor input stream
1591b4e487SEugen Hristev * WB: Programmable white balance in the Bayer domain
1691b4e487SEugen Hristev * CFA: Color filter array interpolation module
1791b4e487SEugen Hristev * CC: Programmable color correction
1891b4e487SEugen Hristev * GAM: Gamma correction
1991b4e487SEugen Hristev * CSC: Programmable color space conversion
2091b4e487SEugen Hristev * CBC: Contrast and Brightness control
2191b4e487SEugen Hristev * SUB: This module performs YCbCr444 to YCbCr420 chrominance subsampling
2291b4e487SEugen Hristev * RLP: This module performs rounding, range limiting
2391b4e487SEugen Hristev * and packing of the incoming data
2491b4e487SEugen Hristev */
2591b4e487SEugen Hristev
2691b4e487SEugen Hristev #include <linux/clk.h>
2791b4e487SEugen Hristev #include <linux/clkdev.h>
2891b4e487SEugen Hristev #include <linux/clk-provider.h>
2991b4e487SEugen Hristev #include <linux/delay.h>
3091b4e487SEugen Hristev #include <linux/interrupt.h>
3191b4e487SEugen Hristev #include <linux/math64.h>
3291b4e487SEugen Hristev #include <linux/module.h>
3391b4e487SEugen Hristev #include <linux/of.h>
3491b4e487SEugen Hristev #include <linux/of_graph.h>
3591b4e487SEugen Hristev #include <linux/platform_device.h>
3691b4e487SEugen Hristev #include <linux/pm_runtime.h>
3791b4e487SEugen Hristev #include <linux/regmap.h>
3891b4e487SEugen Hristev #include <linux/videodev2.h>
3991b4e487SEugen Hristev
4091b4e487SEugen Hristev #include <media/v4l2-ctrls.h>
4191b4e487SEugen Hristev #include <media/v4l2-device.h>
4291b4e487SEugen Hristev #include <media/v4l2-event.h>
4391b4e487SEugen Hristev #include <media/v4l2-image-sizes.h>
4491b4e487SEugen Hristev #include <media/v4l2-ioctl.h>
4591b4e487SEugen Hristev #include <media/v4l2-fwnode.h>
4691b4e487SEugen Hristev #include <media/v4l2-subdev.h>
4791b4e487SEugen Hristev #include <media/videobuf2-dma-contig.h>
4891b4e487SEugen Hristev
4991b4e487SEugen Hristev #include "microchip-isc-regs.h"
5091b4e487SEugen Hristev #include "microchip-isc.h"
5191b4e487SEugen Hristev
5291b4e487SEugen Hristev #define ISC_SAMA5D2_MAX_SUPPORT_WIDTH 2592
5391b4e487SEugen Hristev #define ISC_SAMA5D2_MAX_SUPPORT_HEIGHT 1944
5491b4e487SEugen Hristev
5591b4e487SEugen Hristev #define ISC_SAMA5D2_PIPELINE \
5691b4e487SEugen Hristev (WB_ENABLE | CFA_ENABLE | CC_ENABLE | GAM_ENABLES | CSC_ENABLE | \
5791b4e487SEugen Hristev CBC_ENABLE | SUB422_ENABLE | SUB420_ENABLE)
5891b4e487SEugen Hristev
5991b4e487SEugen Hristev /* This is a list of the formats that the ISC can *output* */
6091b4e487SEugen Hristev static const struct isc_format sama5d2_controller_formats[] = {
6191b4e487SEugen Hristev {
6291b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_ARGB444,
6391b4e487SEugen Hristev }, {
6491b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_ARGB555,
6591b4e487SEugen Hristev }, {
6691b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_RGB565,
6791b4e487SEugen Hristev }, {
6891b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_ABGR32,
6991b4e487SEugen Hristev }, {
7091b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_XBGR32,
7191b4e487SEugen Hristev }, {
7291b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_YUV420,
7391b4e487SEugen Hristev }, {
7491b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_YUYV,
7591b4e487SEugen Hristev }, {
7691b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_YUV422P,
7791b4e487SEugen Hristev }, {
7891b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_GREY,
7991b4e487SEugen Hristev }, {
8091b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_Y10,
8191b4e487SEugen Hristev }, {
8291b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SBGGR8,
8378ba0d79SEugen Hristev .raw = true,
8491b4e487SEugen Hristev }, {
8591b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGBRG8,
8678ba0d79SEugen Hristev .raw = true,
8791b4e487SEugen Hristev }, {
8891b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGRBG8,
8978ba0d79SEugen Hristev .raw = true,
9091b4e487SEugen Hristev }, {
9191b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SRGGB8,
9278ba0d79SEugen Hristev .raw = true,
9391b4e487SEugen Hristev }, {
9491b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SBGGR10,
9578ba0d79SEugen Hristev .raw = true,
9691b4e487SEugen Hristev }, {
9791b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGBRG10,
9878ba0d79SEugen Hristev .raw = true,
9991b4e487SEugen Hristev }, {
10091b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGRBG10,
10178ba0d79SEugen Hristev .raw = true,
10291b4e487SEugen Hristev }, {
10391b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SRGGB10,
10478ba0d79SEugen Hristev .raw = true,
10578ba0d79SEugen Hristev }, {
10678ba0d79SEugen Hristev .fourcc = V4L2_PIX_FMT_SBGGR12,
10778ba0d79SEugen Hristev .raw = true,
10878ba0d79SEugen Hristev }, {
10978ba0d79SEugen Hristev .fourcc = V4L2_PIX_FMT_SGBRG12,
11078ba0d79SEugen Hristev .raw = true,
11178ba0d79SEugen Hristev }, {
11278ba0d79SEugen Hristev .fourcc = V4L2_PIX_FMT_SGRBG12,
11378ba0d79SEugen Hristev .raw = true,
11478ba0d79SEugen Hristev }, {
11578ba0d79SEugen Hristev .fourcc = V4L2_PIX_FMT_SRGGB12,
11678ba0d79SEugen Hristev .raw = true,
11791b4e487SEugen Hristev },
11891b4e487SEugen Hristev };
11991b4e487SEugen Hristev
12091b4e487SEugen Hristev /* This is a list of formats that the ISC can receive as *input* */
12191b4e487SEugen Hristev static struct isc_format sama5d2_formats_list[] = {
12291b4e487SEugen Hristev {
12391b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SBGGR8,
12491b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
12591b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
12691b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_BGBG,
12791b4e487SEugen Hristev },
12891b4e487SEugen Hristev {
12991b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGBRG8,
13091b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
13191b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
13291b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_GBGB,
13391b4e487SEugen Hristev },
13491b4e487SEugen Hristev {
13591b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGRBG8,
13691b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
13791b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
13891b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_GRGR,
13991b4e487SEugen Hristev },
14091b4e487SEugen Hristev {
14191b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SRGGB8,
14291b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
14391b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
14491b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_RGRG,
14591b4e487SEugen Hristev },
14691b4e487SEugen Hristev {
14791b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SBGGR10,
14891b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
14991b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
15091b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_RGRG,
15191b4e487SEugen Hristev },
15291b4e487SEugen Hristev {
15391b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGBRG10,
15491b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
15591b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
15691b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_GBGB,
15791b4e487SEugen Hristev },
15891b4e487SEugen Hristev {
15991b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGRBG10,
16091b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
16191b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
16291b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_GRGR,
16391b4e487SEugen Hristev },
16491b4e487SEugen Hristev {
16591b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SRGGB10,
16691b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
16791b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
16891b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_RGRG,
16991b4e487SEugen Hristev },
17091b4e487SEugen Hristev {
17191b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SBGGR12,
17291b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
17391b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE,
17491b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_BGBG,
17591b4e487SEugen Hristev },
17691b4e487SEugen Hristev {
17791b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGBRG12,
17891b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
17991b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE,
18091b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_GBGB,
18191b4e487SEugen Hristev },
18291b4e487SEugen Hristev {
18391b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SGRBG12,
18491b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
18591b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE,
18691b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_GRGR,
18791b4e487SEugen Hristev },
18891b4e487SEugen Hristev {
18991b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_SRGGB12,
19091b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
19191b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE,
19291b4e487SEugen Hristev .cfa_baycfg = ISC_BAY_CFG_RGRG,
19391b4e487SEugen Hristev },
19491b4e487SEugen Hristev {
19591b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_GREY,
19691b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_Y8_1X8,
19791b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
19891b4e487SEugen Hristev },
19991b4e487SEugen Hristev {
20091b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_YUYV,
20191b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
20291b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
20391b4e487SEugen Hristev },
20491b4e487SEugen Hristev {
20591b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_RGB565,
20691b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
20791b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
20891b4e487SEugen Hristev },
20991b4e487SEugen Hristev {
21091b4e487SEugen Hristev .fourcc = V4L2_PIX_FMT_Y10,
21191b4e487SEugen Hristev .mbus_code = MEDIA_BUS_FMT_Y10_1X10,
21291b4e487SEugen Hristev .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
21391b4e487SEugen Hristev },
21491b4e487SEugen Hristev
21591b4e487SEugen Hristev };
21691b4e487SEugen Hristev
isc_sama5d2_config_csc(struct isc_device * isc)21791b4e487SEugen Hristev static void isc_sama5d2_config_csc(struct isc_device *isc)
21891b4e487SEugen Hristev {
21991b4e487SEugen Hristev struct regmap *regmap = isc->regmap;
22091b4e487SEugen Hristev
22191b4e487SEugen Hristev /* Convert RGB to YUV */
22291b4e487SEugen Hristev regmap_write(regmap, ISC_CSC_YR_YG + isc->offsets.csc,
22391b4e487SEugen Hristev 0x42 | (0x81 << 16));
22491b4e487SEugen Hristev regmap_write(regmap, ISC_CSC_YB_OY + isc->offsets.csc,
22591b4e487SEugen Hristev 0x19 | (0x10 << 16));
22691b4e487SEugen Hristev regmap_write(regmap, ISC_CSC_CBR_CBG + isc->offsets.csc,
22791b4e487SEugen Hristev 0xFDA | (0xFB6 << 16));
22891b4e487SEugen Hristev regmap_write(regmap, ISC_CSC_CBB_OCB + isc->offsets.csc,
22991b4e487SEugen Hristev 0x70 | (0x80 << 16));
23091b4e487SEugen Hristev regmap_write(regmap, ISC_CSC_CRR_CRG + isc->offsets.csc,
23191b4e487SEugen Hristev 0x70 | (0xFA2 << 16));
23291b4e487SEugen Hristev regmap_write(regmap, ISC_CSC_CRB_OCR + isc->offsets.csc,
23391b4e487SEugen Hristev 0xFEE | (0x80 << 16));
23491b4e487SEugen Hristev }
23591b4e487SEugen Hristev
isc_sama5d2_config_cbc(struct isc_device * isc)23691b4e487SEugen Hristev static void isc_sama5d2_config_cbc(struct isc_device *isc)
23791b4e487SEugen Hristev {
23891b4e487SEugen Hristev struct regmap *regmap = isc->regmap;
23991b4e487SEugen Hristev
24091b4e487SEugen Hristev regmap_write(regmap, ISC_CBC_BRIGHT + isc->offsets.cbc,
24191b4e487SEugen Hristev isc->ctrls.brightness);
24291b4e487SEugen Hristev regmap_write(regmap, ISC_CBC_CONTRAST + isc->offsets.cbc,
24391b4e487SEugen Hristev isc->ctrls.contrast);
24491b4e487SEugen Hristev }
24591b4e487SEugen Hristev
isc_sama5d2_config_cc(struct isc_device * isc)24691b4e487SEugen Hristev static void isc_sama5d2_config_cc(struct isc_device *isc)
24791b4e487SEugen Hristev {
24891b4e487SEugen Hristev struct regmap *regmap = isc->regmap;
24991b4e487SEugen Hristev
25091b4e487SEugen Hristev /* Configure each register at the neutral fixed point 1.0 or 0.0 */
25191b4e487SEugen Hristev regmap_write(regmap, ISC_CC_RR_RG, (1 << 8));
25291b4e487SEugen Hristev regmap_write(regmap, ISC_CC_RB_OR, 0);
25391b4e487SEugen Hristev regmap_write(regmap, ISC_CC_GR_GG, (1 << 8) << 16);
25491b4e487SEugen Hristev regmap_write(regmap, ISC_CC_GB_OG, 0);
25591b4e487SEugen Hristev regmap_write(regmap, ISC_CC_BR_BG, 0);
25691b4e487SEugen Hristev regmap_write(regmap, ISC_CC_BB_OB, (1 << 8));
25791b4e487SEugen Hristev }
25891b4e487SEugen Hristev
isc_sama5d2_config_ctrls(struct isc_device * isc,const struct v4l2_ctrl_ops * ops)25991b4e487SEugen Hristev static void isc_sama5d2_config_ctrls(struct isc_device *isc,
26091b4e487SEugen Hristev const struct v4l2_ctrl_ops *ops)
26191b4e487SEugen Hristev {
26291b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls;
26391b4e487SEugen Hristev struct v4l2_ctrl_handler *hdl = &ctrls->handler;
26491b4e487SEugen Hristev
26591b4e487SEugen Hristev ctrls->contrast = 256;
26691b4e487SEugen Hristev
26791b4e487SEugen Hristev v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 256);
26891b4e487SEugen Hristev }
26991b4e487SEugen Hristev
isc_sama5d2_config_dpc(struct isc_device * isc)27091b4e487SEugen Hristev static void isc_sama5d2_config_dpc(struct isc_device *isc)
27191b4e487SEugen Hristev {
27291b4e487SEugen Hristev /* This module is not present on sama5d2 pipeline */
27391b4e487SEugen Hristev }
27491b4e487SEugen Hristev
isc_sama5d2_config_gam(struct isc_device * isc)27591b4e487SEugen Hristev static void isc_sama5d2_config_gam(struct isc_device *isc)
27691b4e487SEugen Hristev {
27791b4e487SEugen Hristev /* No specific gamma configuration */
27891b4e487SEugen Hristev }
27991b4e487SEugen Hristev
isc_sama5d2_config_rlp(struct isc_device * isc)28091b4e487SEugen Hristev static void isc_sama5d2_config_rlp(struct isc_device *isc)
28191b4e487SEugen Hristev {
28291b4e487SEugen Hristev struct regmap *regmap = isc->regmap;
28391b4e487SEugen Hristev u32 rlp_mode = isc->config.rlp_cfg_mode;
28491b4e487SEugen Hristev
28591b4e487SEugen Hristev /*
28691b4e487SEugen Hristev * In sama5d2, the YUV planar modes and the YUYV modes are treated
28791b4e487SEugen Hristev * in the same way in RLP register.
28891b4e487SEugen Hristev * Normally, YYCC mode should be Luma(n) - Color B(n) - Color R (n)
28991b4e487SEugen Hristev * and YCYC should be Luma(n + 1) - Color B (n) - Luma (n) - Color R (n)
29091b4e487SEugen Hristev * but in sama5d2, the YCYC mode does not exist, and YYCC must be
29191b4e487SEugen Hristev * selected for both planar and interleaved modes, as in fact
29291b4e487SEugen Hristev * both modes are supported.
29391b4e487SEugen Hristev *
29491b4e487SEugen Hristev * Thus, if the YCYC mode is selected, replace it with the
29591b4e487SEugen Hristev * sama5d2-compliant mode which is YYCC .
29691b4e487SEugen Hristev */
29791b4e487SEugen Hristev if ((rlp_mode & ISC_RLP_CFG_MODE_MASK) == ISC_RLP_CFG_MODE_YCYC) {
29891b4e487SEugen Hristev rlp_mode &= ~ISC_RLP_CFG_MODE_MASK;
29991b4e487SEugen Hristev rlp_mode |= ISC_RLP_CFG_MODE_YYCC;
30091b4e487SEugen Hristev }
30191b4e487SEugen Hristev
30291b4e487SEugen Hristev regmap_update_bits(regmap, ISC_RLP_CFG + isc->offsets.rlp,
30391b4e487SEugen Hristev ISC_RLP_CFG_MODE_MASK, rlp_mode);
30491b4e487SEugen Hristev }
30591b4e487SEugen Hristev
isc_sama5d2_adapt_pipeline(struct isc_device * isc)30691b4e487SEugen Hristev static void isc_sama5d2_adapt_pipeline(struct isc_device *isc)
30791b4e487SEugen Hristev {
30891b4e487SEugen Hristev isc->try_config.bits_pipeline &= ISC_SAMA5D2_PIPELINE;
30991b4e487SEugen Hristev }
31091b4e487SEugen Hristev
31191b4e487SEugen Hristev /* Gamma table with gamma 1/2.2 */
31291b4e487SEugen Hristev static const u32 isc_sama5d2_gamma_table[][GAMMA_ENTRIES] = {
31391b4e487SEugen Hristev /* 0 --> gamma 1/1.8 */
31491b4e487SEugen Hristev { 0x65, 0x66002F, 0x950025, 0xBB0020, 0xDB001D, 0xF8001A,
31591b4e487SEugen Hristev 0x1130018, 0x12B0017, 0x1420016, 0x1580014, 0x16D0013, 0x1810012,
31691b4e487SEugen Hristev 0x1940012, 0x1A60012, 0x1B80011, 0x1C90010, 0x1DA0010, 0x1EA000F,
31791b4e487SEugen Hristev 0x1FA000F, 0x209000F, 0x218000F, 0x227000E, 0x235000E, 0x243000E,
31891b4e487SEugen Hristev 0x251000E, 0x25F000D, 0x26C000D, 0x279000D, 0x286000D, 0x293000C,
31991b4e487SEugen Hristev 0x2A0000C, 0x2AC000C, 0x2B8000C, 0x2C4000C, 0x2D0000B, 0x2DC000B,
32091b4e487SEugen Hristev 0x2E7000B, 0x2F3000B, 0x2FE000B, 0x309000B, 0x314000B, 0x31F000A,
32191b4e487SEugen Hristev 0x32A000A, 0x334000B, 0x33F000A, 0x349000A, 0x354000A, 0x35E000A,
32291b4e487SEugen Hristev 0x368000A, 0x372000A, 0x37C000A, 0x386000A, 0x3900009, 0x399000A,
32391b4e487SEugen Hristev 0x3A30009, 0x3AD0009, 0x3B60009, 0x3BF000A, 0x3C90009, 0x3D20009,
32491b4e487SEugen Hristev 0x3DB0009, 0x3E40009, 0x3ED0009, 0x3F60009 },
32591b4e487SEugen Hristev
32691b4e487SEugen Hristev /* 1 --> gamma 1/2 */
32791b4e487SEugen Hristev { 0x7F, 0x800034, 0xB50028, 0xDE0021, 0x100001E, 0x11E001B,
32891b4e487SEugen Hristev 0x1390019, 0x1520017, 0x16A0015, 0x1800014, 0x1940014, 0x1A80013,
32991b4e487SEugen Hristev 0x1BB0012, 0x1CD0011, 0x1DF0010, 0x1EF0010, 0x200000F, 0x20F000F,
33091b4e487SEugen Hristev 0x21F000E, 0x22D000F, 0x23C000E, 0x24A000E, 0x258000D, 0x265000D,
33191b4e487SEugen Hristev 0x273000C, 0x27F000D, 0x28C000C, 0x299000C, 0x2A5000C, 0x2B1000B,
33291b4e487SEugen Hristev 0x2BC000C, 0x2C8000B, 0x2D3000C, 0x2DF000B, 0x2EA000A, 0x2F5000A,
33391b4e487SEugen Hristev 0x2FF000B, 0x30A000A, 0x314000B, 0x31F000A, 0x329000A, 0x333000A,
33491b4e487SEugen Hristev 0x33D0009, 0x3470009, 0x350000A, 0x35A0009, 0x363000A, 0x36D0009,
33591b4e487SEugen Hristev 0x3760009, 0x37F0009, 0x3880009, 0x3910009, 0x39A0009, 0x3A30009,
33691b4e487SEugen Hristev 0x3AC0008, 0x3B40009, 0x3BD0008, 0x3C60008, 0x3CE0008, 0x3D60009,
33791b4e487SEugen Hristev 0x3DF0008, 0x3E70008, 0x3EF0008, 0x3F70008 },
33891b4e487SEugen Hristev
33991b4e487SEugen Hristev /* 2 --> gamma 1/2.2 */
34091b4e487SEugen Hristev { 0x99, 0x9B0038, 0xD4002A, 0xFF0023, 0x122001F, 0x141001B,
34191b4e487SEugen Hristev 0x15D0019, 0x1760017, 0x18E0015, 0x1A30015, 0x1B80013, 0x1CC0012,
34291b4e487SEugen Hristev 0x1DE0011, 0x1F00010, 0x2010010, 0x2110010, 0x221000F, 0x230000F,
34391b4e487SEugen Hristev 0x23F000E, 0x24D000E, 0x25B000D, 0x269000C, 0x276000C, 0x283000C,
34491b4e487SEugen Hristev 0x28F000C, 0x29B000C, 0x2A7000C, 0x2B3000B, 0x2BF000B, 0x2CA000B,
34591b4e487SEugen Hristev 0x2D5000B, 0x2E0000A, 0x2EB000A, 0x2F5000A, 0x2FF000A, 0x30A000A,
34691b4e487SEugen Hristev 0x3140009, 0x31E0009, 0x327000A, 0x3310009, 0x33A0009, 0x3440009,
34791b4e487SEugen Hristev 0x34D0009, 0x3560009, 0x35F0009, 0x3680008, 0x3710008, 0x3790009,
34891b4e487SEugen Hristev 0x3820008, 0x38A0008, 0x3930008, 0x39B0008, 0x3A30008, 0x3AB0008,
34991b4e487SEugen Hristev 0x3B30008, 0x3BB0008, 0x3C30008, 0x3CB0007, 0x3D20008, 0x3DA0007,
35091b4e487SEugen Hristev 0x3E20007, 0x3E90007, 0x3F00008, 0x3F80007 },
35191b4e487SEugen Hristev };
35291b4e487SEugen Hristev
isc_parse_dt(struct device * dev,struct isc_device * isc)35391b4e487SEugen Hristev static int isc_parse_dt(struct device *dev, struct isc_device *isc)
35491b4e487SEugen Hristev {
35591b4e487SEugen Hristev struct device_node *np = dev->of_node;
35691b4e487SEugen Hristev struct device_node *epn = NULL;
35791b4e487SEugen Hristev struct isc_subdev_entity *subdev_entity;
35891b4e487SEugen Hristev unsigned int flags;
35991b4e487SEugen Hristev int ret;
36091b4e487SEugen Hristev
36191b4e487SEugen Hristev INIT_LIST_HEAD(&isc->subdev_entities);
36291b4e487SEugen Hristev
36391b4e487SEugen Hristev while (1) {
36491b4e487SEugen Hristev struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 };
36591b4e487SEugen Hristev
36691b4e487SEugen Hristev epn = of_graph_get_next_endpoint(np, epn);
36791b4e487SEugen Hristev if (!epn)
36891b4e487SEugen Hristev return 0;
36991b4e487SEugen Hristev
37091b4e487SEugen Hristev ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn),
37191b4e487SEugen Hristev &v4l2_epn);
37291b4e487SEugen Hristev if (ret) {
37391b4e487SEugen Hristev ret = -EINVAL;
37491b4e487SEugen Hristev dev_err(dev, "Could not parse the endpoint\n");
37591b4e487SEugen Hristev break;
37691b4e487SEugen Hristev }
37791b4e487SEugen Hristev
37891b4e487SEugen Hristev subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity),
37991b4e487SEugen Hristev GFP_KERNEL);
38091b4e487SEugen Hristev if (!subdev_entity) {
38191b4e487SEugen Hristev ret = -ENOMEM;
38291b4e487SEugen Hristev break;
38391b4e487SEugen Hristev }
38491b4e487SEugen Hristev subdev_entity->epn = epn;
38591b4e487SEugen Hristev
38691b4e487SEugen Hristev flags = v4l2_epn.bus.parallel.flags;
38791b4e487SEugen Hristev
38891b4e487SEugen Hristev if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
38991b4e487SEugen Hristev subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_LOW;
39091b4e487SEugen Hristev
39191b4e487SEugen Hristev if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
39291b4e487SEugen Hristev subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_LOW;
39391b4e487SEugen Hristev
39491b4e487SEugen Hristev if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
39591b4e487SEugen Hristev subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
39691b4e487SEugen Hristev
39791b4e487SEugen Hristev if (v4l2_epn.bus_type == V4L2_MBUS_BT656)
39891b4e487SEugen Hristev subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_CCIR_CRC |
39991b4e487SEugen Hristev ISC_PFE_CFG0_CCIR656;
40091b4e487SEugen Hristev
40191b4e487SEugen Hristev list_add_tail(&subdev_entity->list, &isc->subdev_entities);
40291b4e487SEugen Hristev }
40391b4e487SEugen Hristev of_node_put(epn);
40491b4e487SEugen Hristev
40591b4e487SEugen Hristev return ret;
40691b4e487SEugen Hristev }
40791b4e487SEugen Hristev
microchip_isc_probe(struct platform_device * pdev)40891b4e487SEugen Hristev static int microchip_isc_probe(struct platform_device *pdev)
40991b4e487SEugen Hristev {
41091b4e487SEugen Hristev struct device *dev = &pdev->dev;
41191b4e487SEugen Hristev struct isc_device *isc;
41291b4e487SEugen Hristev void __iomem *io_base;
41391b4e487SEugen Hristev struct isc_subdev_entity *subdev_entity;
41491b4e487SEugen Hristev int irq;
41591b4e487SEugen Hristev int ret;
41691b4e487SEugen Hristev u32 ver;
41791b4e487SEugen Hristev
41891b4e487SEugen Hristev isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL);
41991b4e487SEugen Hristev if (!isc)
42091b4e487SEugen Hristev return -ENOMEM;
42191b4e487SEugen Hristev
42291b4e487SEugen Hristev platform_set_drvdata(pdev, isc);
42391b4e487SEugen Hristev isc->dev = dev;
42491b4e487SEugen Hristev
425639a6fa4SYangtao Li io_base = devm_platform_ioremap_resource(pdev, 0);
42691b4e487SEugen Hristev if (IS_ERR(io_base))
42791b4e487SEugen Hristev return PTR_ERR(io_base);
42891b4e487SEugen Hristev
42991b4e487SEugen Hristev isc->regmap = devm_regmap_init_mmio(dev, io_base, µchip_isc_regmap_config);
43091b4e487SEugen Hristev if (IS_ERR(isc->regmap)) {
43191b4e487SEugen Hristev ret = PTR_ERR(isc->regmap);
43291b4e487SEugen Hristev dev_err(dev, "failed to init register map: %d\n", ret);
43391b4e487SEugen Hristev return ret;
43491b4e487SEugen Hristev }
43591b4e487SEugen Hristev
43691b4e487SEugen Hristev irq = platform_get_irq(pdev, 0);
43791b4e487SEugen Hristev if (irq < 0)
43891b4e487SEugen Hristev return irq;
43991b4e487SEugen Hristev
44091b4e487SEugen Hristev ret = devm_request_irq(dev, irq, microchip_isc_interrupt, 0,
44191b4e487SEugen Hristev "microchip-sama5d2-isc", isc);
44291b4e487SEugen Hristev if (ret < 0) {
44391b4e487SEugen Hristev dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
44491b4e487SEugen Hristev irq, ret);
44591b4e487SEugen Hristev return ret;
44691b4e487SEugen Hristev }
44791b4e487SEugen Hristev
44891b4e487SEugen Hristev isc->gamma_table = isc_sama5d2_gamma_table;
44991b4e487SEugen Hristev isc->gamma_max = 2;
45091b4e487SEugen Hristev
45191b4e487SEugen Hristev isc->max_width = ISC_SAMA5D2_MAX_SUPPORT_WIDTH;
45291b4e487SEugen Hristev isc->max_height = ISC_SAMA5D2_MAX_SUPPORT_HEIGHT;
45391b4e487SEugen Hristev
45491b4e487SEugen Hristev isc->config_dpc = isc_sama5d2_config_dpc;
45591b4e487SEugen Hristev isc->config_csc = isc_sama5d2_config_csc;
45691b4e487SEugen Hristev isc->config_cbc = isc_sama5d2_config_cbc;
45791b4e487SEugen Hristev isc->config_cc = isc_sama5d2_config_cc;
45891b4e487SEugen Hristev isc->config_gam = isc_sama5d2_config_gam;
45991b4e487SEugen Hristev isc->config_rlp = isc_sama5d2_config_rlp;
46091b4e487SEugen Hristev isc->config_ctrls = isc_sama5d2_config_ctrls;
46191b4e487SEugen Hristev
46291b4e487SEugen Hristev isc->adapt_pipeline = isc_sama5d2_adapt_pipeline;
46391b4e487SEugen Hristev
46491b4e487SEugen Hristev isc->offsets.csc = ISC_SAMA5D2_CSC_OFFSET;
46591b4e487SEugen Hristev isc->offsets.cbc = ISC_SAMA5D2_CBC_OFFSET;
46691b4e487SEugen Hristev isc->offsets.sub422 = ISC_SAMA5D2_SUB422_OFFSET;
46791b4e487SEugen Hristev isc->offsets.sub420 = ISC_SAMA5D2_SUB420_OFFSET;
46891b4e487SEugen Hristev isc->offsets.rlp = ISC_SAMA5D2_RLP_OFFSET;
46991b4e487SEugen Hristev isc->offsets.his = ISC_SAMA5D2_HIS_OFFSET;
47091b4e487SEugen Hristev isc->offsets.dma = ISC_SAMA5D2_DMA_OFFSET;
47191b4e487SEugen Hristev isc->offsets.version = ISC_SAMA5D2_VERSION_OFFSET;
47291b4e487SEugen Hristev isc->offsets.his_entry = ISC_SAMA5D2_HIS_ENTRY_OFFSET;
47391b4e487SEugen Hristev
47491b4e487SEugen Hristev isc->controller_formats = sama5d2_controller_formats;
47591b4e487SEugen Hristev isc->controller_formats_size = ARRAY_SIZE(sama5d2_controller_formats);
47691b4e487SEugen Hristev isc->formats_list = sama5d2_formats_list;
47791b4e487SEugen Hristev isc->formats_list_size = ARRAY_SIZE(sama5d2_formats_list);
47891b4e487SEugen Hristev
47991b4e487SEugen Hristev /* sama5d2-isc - 8 bits per beat */
48091b4e487SEugen Hristev isc->dcfg = ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8;
48191b4e487SEugen Hristev
48291b4e487SEugen Hristev /* sama5d2-isc : ISPCK is required and mandatory */
48391b4e487SEugen Hristev isc->ispck_required = true;
48491b4e487SEugen Hristev
48591b4e487SEugen Hristev ret = microchip_isc_pipeline_init(isc);
48691b4e487SEugen Hristev if (ret)
48791b4e487SEugen Hristev return ret;
48891b4e487SEugen Hristev
48991b4e487SEugen Hristev isc->hclock = devm_clk_get(dev, "hclock");
49091b4e487SEugen Hristev if (IS_ERR(isc->hclock)) {
49191b4e487SEugen Hristev ret = PTR_ERR(isc->hclock);
49291b4e487SEugen Hristev dev_err(dev, "failed to get hclock: %d\n", ret);
49391b4e487SEugen Hristev return ret;
49491b4e487SEugen Hristev }
49591b4e487SEugen Hristev
49691b4e487SEugen Hristev ret = clk_prepare_enable(isc->hclock);
49791b4e487SEugen Hristev if (ret) {
49891b4e487SEugen Hristev dev_err(dev, "failed to enable hclock: %d\n", ret);
49991b4e487SEugen Hristev return ret;
50091b4e487SEugen Hristev }
50191b4e487SEugen Hristev
50291b4e487SEugen Hristev ret = microchip_isc_clk_init(isc);
50391b4e487SEugen Hristev if (ret) {
50491b4e487SEugen Hristev dev_err(dev, "failed to init isc clock: %d\n", ret);
50591b4e487SEugen Hristev goto unprepare_hclk;
50691b4e487SEugen Hristev }
50791b4e487SEugen Hristev ret = v4l2_device_register(dev, &isc->v4l2_dev);
50891b4e487SEugen Hristev if (ret) {
50991b4e487SEugen Hristev dev_err(dev, "unable to register v4l2 device.\n");
51091b4e487SEugen Hristev goto unprepare_clk;
51191b4e487SEugen Hristev }
51291b4e487SEugen Hristev
51391b4e487SEugen Hristev ret = isc_parse_dt(dev, isc);
51491b4e487SEugen Hristev if (ret) {
51591b4e487SEugen Hristev dev_err(dev, "fail to parse device tree\n");
51691b4e487SEugen Hristev goto unregister_v4l2_device;
51791b4e487SEugen Hristev }
51891b4e487SEugen Hristev
51991b4e487SEugen Hristev if (list_empty(&isc->subdev_entities)) {
52091b4e487SEugen Hristev dev_err(dev, "no subdev found\n");
52191b4e487SEugen Hristev ret = -ENODEV;
52291b4e487SEugen Hristev goto unregister_v4l2_device;
52391b4e487SEugen Hristev }
52491b4e487SEugen Hristev
52591b4e487SEugen Hristev list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
526adb2dcd5SSakari Ailus struct v4l2_async_connection *asd;
52791b4e487SEugen Hristev struct fwnode_handle *fwnode =
52891b4e487SEugen Hristev of_fwnode_handle(subdev_entity->epn);
52991b4e487SEugen Hristev
530*b8ec754aSSakari Ailus v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev);
53191b4e487SEugen Hristev
53291b4e487SEugen Hristev asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
53391b4e487SEugen Hristev fwnode,
534adb2dcd5SSakari Ailus struct v4l2_async_connection);
53591b4e487SEugen Hristev
53691b4e487SEugen Hristev of_node_put(subdev_entity->epn);
53791b4e487SEugen Hristev subdev_entity->epn = NULL;
53891b4e487SEugen Hristev
53991b4e487SEugen Hristev if (IS_ERR(asd)) {
54091b4e487SEugen Hristev ret = PTR_ERR(asd);
54191b4e487SEugen Hristev goto cleanup_subdev;
54291b4e487SEugen Hristev }
54391b4e487SEugen Hristev
54491b4e487SEugen Hristev subdev_entity->notifier.ops = µchip_isc_async_ops;
54591b4e487SEugen Hristev
546*b8ec754aSSakari Ailus ret = v4l2_async_nf_register(&subdev_entity->notifier);
54791b4e487SEugen Hristev if (ret) {
54891b4e487SEugen Hristev dev_err(dev, "fail to register async notifier\n");
54991b4e487SEugen Hristev goto cleanup_subdev;
55091b4e487SEugen Hristev }
55191b4e487SEugen Hristev
55291b4e487SEugen Hristev if (video_is_registered(&isc->video_dev))
55391b4e487SEugen Hristev break;
55491b4e487SEugen Hristev }
55591b4e487SEugen Hristev
556920b2665SEugen Hristev regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver);
557920b2665SEugen Hristev
558920b2665SEugen Hristev ret = isc_mc_init(isc, ver);
559920b2665SEugen Hristev if (ret < 0)
560920b2665SEugen Hristev goto isc_probe_mc_init_err;
561920b2665SEugen Hristev
56291b4e487SEugen Hristev pm_runtime_set_active(dev);
56391b4e487SEugen Hristev pm_runtime_enable(dev);
56491b4e487SEugen Hristev pm_request_idle(dev);
56591b4e487SEugen Hristev
56691b4e487SEugen Hristev isc->ispck = isc->isc_clks[ISC_ISPCK].clk;
56791b4e487SEugen Hristev
56891b4e487SEugen Hristev ret = clk_prepare_enable(isc->ispck);
56991b4e487SEugen Hristev if (ret) {
57091b4e487SEugen Hristev dev_err(dev, "failed to enable ispck: %d\n", ret);
57191b4e487SEugen Hristev goto disable_pm;
57291b4e487SEugen Hristev }
57391b4e487SEugen Hristev
57491b4e487SEugen Hristev /* ispck should be greater or equal to hclock */
57591b4e487SEugen Hristev ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
57691b4e487SEugen Hristev if (ret) {
57791b4e487SEugen Hristev dev_err(dev, "failed to set ispck rate: %d\n", ret);
57891b4e487SEugen Hristev goto unprepare_clk;
57991b4e487SEugen Hristev }
58091b4e487SEugen Hristev
58191b4e487SEugen Hristev dev_info(dev, "Microchip ISC version %x\n", ver);
58291b4e487SEugen Hristev
58391b4e487SEugen Hristev return 0;
58491b4e487SEugen Hristev
58591b4e487SEugen Hristev unprepare_clk:
58691b4e487SEugen Hristev clk_disable_unprepare(isc->ispck);
58791b4e487SEugen Hristev
58891b4e487SEugen Hristev disable_pm:
58991b4e487SEugen Hristev pm_runtime_disable(dev);
59091b4e487SEugen Hristev
591920b2665SEugen Hristev isc_probe_mc_init_err:
592920b2665SEugen Hristev isc_mc_cleanup(isc);
593920b2665SEugen Hristev
59491b4e487SEugen Hristev cleanup_subdev:
59591b4e487SEugen Hristev microchip_isc_subdev_cleanup(isc);
59691b4e487SEugen Hristev
59791b4e487SEugen Hristev unregister_v4l2_device:
59891b4e487SEugen Hristev v4l2_device_unregister(&isc->v4l2_dev);
59991b4e487SEugen Hristev
60091b4e487SEugen Hristev unprepare_hclk:
60191b4e487SEugen Hristev clk_disable_unprepare(isc->hclock);
60291b4e487SEugen Hristev
60391b4e487SEugen Hristev microchip_isc_clk_cleanup(isc);
60491b4e487SEugen Hristev
60591b4e487SEugen Hristev return ret;
60691b4e487SEugen Hristev }
60791b4e487SEugen Hristev
microchip_isc_remove(struct platform_device * pdev)60861263f17SUwe Kleine-König static void microchip_isc_remove(struct platform_device *pdev)
60991b4e487SEugen Hristev {
61091b4e487SEugen Hristev struct isc_device *isc = platform_get_drvdata(pdev);
61191b4e487SEugen Hristev
61291b4e487SEugen Hristev pm_runtime_disable(&pdev->dev);
61391b4e487SEugen Hristev
614920b2665SEugen Hristev isc_mc_cleanup(isc);
615920b2665SEugen Hristev
61691b4e487SEugen Hristev microchip_isc_subdev_cleanup(isc);
61791b4e487SEugen Hristev
61891b4e487SEugen Hristev v4l2_device_unregister(&isc->v4l2_dev);
61991b4e487SEugen Hristev
62091b4e487SEugen Hristev clk_disable_unprepare(isc->ispck);
62191b4e487SEugen Hristev clk_disable_unprepare(isc->hclock);
62291b4e487SEugen Hristev
62391b4e487SEugen Hristev microchip_isc_clk_cleanup(isc);
62491b4e487SEugen Hristev }
62591b4e487SEugen Hristev
isc_runtime_suspend(struct device * dev)62691b4e487SEugen Hristev static int __maybe_unused isc_runtime_suspend(struct device *dev)
62791b4e487SEugen Hristev {
62891b4e487SEugen Hristev struct isc_device *isc = dev_get_drvdata(dev);
62991b4e487SEugen Hristev
63091b4e487SEugen Hristev clk_disable_unprepare(isc->ispck);
63191b4e487SEugen Hristev clk_disable_unprepare(isc->hclock);
63291b4e487SEugen Hristev
63391b4e487SEugen Hristev return 0;
63491b4e487SEugen Hristev }
63591b4e487SEugen Hristev
isc_runtime_resume(struct device * dev)63691b4e487SEugen Hristev static int __maybe_unused isc_runtime_resume(struct device *dev)
63791b4e487SEugen Hristev {
63891b4e487SEugen Hristev struct isc_device *isc = dev_get_drvdata(dev);
63991b4e487SEugen Hristev int ret;
64091b4e487SEugen Hristev
64191b4e487SEugen Hristev ret = clk_prepare_enable(isc->hclock);
64291b4e487SEugen Hristev if (ret)
64391b4e487SEugen Hristev return ret;
64491b4e487SEugen Hristev
64591b4e487SEugen Hristev ret = clk_prepare_enable(isc->ispck);
64691b4e487SEugen Hristev if (ret)
64791b4e487SEugen Hristev clk_disable_unprepare(isc->hclock);
64891b4e487SEugen Hristev
64991b4e487SEugen Hristev return ret;
65091b4e487SEugen Hristev }
65191b4e487SEugen Hristev
65291b4e487SEugen Hristev static const struct dev_pm_ops microchip_isc_dev_pm_ops = {
65391b4e487SEugen Hristev SET_RUNTIME_PM_OPS(isc_runtime_suspend, isc_runtime_resume, NULL)
65491b4e487SEugen Hristev };
65591b4e487SEugen Hristev
65691b4e487SEugen Hristev #if IS_ENABLED(CONFIG_OF)
65791b4e487SEugen Hristev static const struct of_device_id microchip_isc_of_match[] = {
65891b4e487SEugen Hristev { .compatible = "atmel,sama5d2-isc" },
65991b4e487SEugen Hristev { }
66091b4e487SEugen Hristev };
66191b4e487SEugen Hristev MODULE_DEVICE_TABLE(of, microchip_isc_of_match);
66291b4e487SEugen Hristev #endif
66391b4e487SEugen Hristev
66491b4e487SEugen Hristev static struct platform_driver microchip_isc_driver = {
66591b4e487SEugen Hristev .probe = microchip_isc_probe,
66661263f17SUwe Kleine-König .remove_new = microchip_isc_remove,
66791b4e487SEugen Hristev .driver = {
66891b4e487SEugen Hristev .name = "microchip-sama5d2-isc",
66991b4e487SEugen Hristev .pm = µchip_isc_dev_pm_ops,
67091b4e487SEugen Hristev .of_match_table = of_match_ptr(microchip_isc_of_match),
67191b4e487SEugen Hristev },
67291b4e487SEugen Hristev };
67391b4e487SEugen Hristev
67491b4e487SEugen Hristev module_platform_driver(microchip_isc_driver);
67591b4e487SEugen Hristev
67691b4e487SEugen Hristev MODULE_AUTHOR("Songjun Wu");
67791b4e487SEugen Hristev MODULE_DESCRIPTION("The V4L2 driver for Microchip-ISC");
67891b4e487SEugen Hristev MODULE_LICENSE("GPL v2");
679