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, µchip_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 = µchip_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 = µchip_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