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; 357 struct isc_subdev_entity *subdev_entity; 358 unsigned int flags; 359 360 INIT_LIST_HEAD(&isc->subdev_entities); 361 362 for_each_endpoint_of_node(np, epn) { 363 struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 }; 364 int ret; 365 366 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn), 367 &v4l2_epn); 368 if (ret) { 369 of_node_put(epn); 370 dev_err(dev, "Could not parse the endpoint\n"); 371 return -EINVAL; 372 } 373 374 subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity), 375 GFP_KERNEL); 376 if (!subdev_entity) { 377 of_node_put(epn); 378 return -ENOMEM; 379 } 380 subdev_entity->epn = epn; 381 382 flags = v4l2_epn.bus.parallel.flags; 383 384 if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) 385 subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_LOW; 386 387 if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) 388 subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_LOW; 389 390 if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) 391 subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW; 392 393 if (v4l2_epn.bus_type == V4L2_MBUS_BT656) 394 subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_CCIR_CRC | 395 ISC_PFE_CFG0_CCIR656; 396 397 list_add_tail(&subdev_entity->list, &isc->subdev_entities); 398 } 399 400 return 0; 401 } 402 403 static int microchip_isc_probe(struct platform_device *pdev) 404 { 405 struct device *dev = &pdev->dev; 406 struct isc_device *isc; 407 void __iomem *io_base; 408 struct isc_subdev_entity *subdev_entity; 409 int irq; 410 int ret; 411 u32 ver; 412 413 isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL); 414 if (!isc) 415 return -ENOMEM; 416 417 platform_set_drvdata(pdev, isc); 418 isc->dev = dev; 419 420 io_base = devm_platform_ioremap_resource(pdev, 0); 421 if (IS_ERR(io_base)) 422 return PTR_ERR(io_base); 423 424 isc->regmap = devm_regmap_init_mmio(dev, io_base, µchip_isc_regmap_config); 425 if (IS_ERR(isc->regmap)) { 426 ret = PTR_ERR(isc->regmap); 427 dev_err(dev, "failed to init register map: %d\n", ret); 428 return ret; 429 } 430 431 irq = platform_get_irq(pdev, 0); 432 if (irq < 0) 433 return irq; 434 435 ret = devm_request_irq(dev, irq, microchip_isc_interrupt, 0, 436 "microchip-sama5d2-isc", isc); 437 if (ret < 0) { 438 dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", 439 irq, ret); 440 return ret; 441 } 442 443 isc->gamma_table = isc_sama5d2_gamma_table; 444 isc->gamma_max = 2; 445 446 isc->max_width = ISC_SAMA5D2_MAX_SUPPORT_WIDTH; 447 isc->max_height = ISC_SAMA5D2_MAX_SUPPORT_HEIGHT; 448 449 isc->config_dpc = isc_sama5d2_config_dpc; 450 isc->config_csc = isc_sama5d2_config_csc; 451 isc->config_cbc = isc_sama5d2_config_cbc; 452 isc->config_cc = isc_sama5d2_config_cc; 453 isc->config_gam = isc_sama5d2_config_gam; 454 isc->config_rlp = isc_sama5d2_config_rlp; 455 isc->config_ctrls = isc_sama5d2_config_ctrls; 456 457 isc->adapt_pipeline = isc_sama5d2_adapt_pipeline; 458 459 isc->offsets.csc = ISC_SAMA5D2_CSC_OFFSET; 460 isc->offsets.cbc = ISC_SAMA5D2_CBC_OFFSET; 461 isc->offsets.sub422 = ISC_SAMA5D2_SUB422_OFFSET; 462 isc->offsets.sub420 = ISC_SAMA5D2_SUB420_OFFSET; 463 isc->offsets.rlp = ISC_SAMA5D2_RLP_OFFSET; 464 isc->offsets.his = ISC_SAMA5D2_HIS_OFFSET; 465 isc->offsets.dma = ISC_SAMA5D2_DMA_OFFSET; 466 isc->offsets.version = ISC_SAMA5D2_VERSION_OFFSET; 467 isc->offsets.his_entry = ISC_SAMA5D2_HIS_ENTRY_OFFSET; 468 469 isc->controller_formats = sama5d2_controller_formats; 470 isc->controller_formats_size = ARRAY_SIZE(sama5d2_controller_formats); 471 isc->formats_list = sama5d2_formats_list; 472 isc->formats_list_size = ARRAY_SIZE(sama5d2_formats_list); 473 474 /* sama5d2-isc - 8 bits per beat */ 475 isc->dcfg = ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8; 476 477 /* sama5d2-isc : ISPCK is required and mandatory */ 478 isc->ispck_required = true; 479 480 ret = microchip_isc_pipeline_init(isc); 481 if (ret) 482 return ret; 483 484 isc->hclock = devm_clk_get(dev, "hclock"); 485 if (IS_ERR(isc->hclock)) { 486 ret = PTR_ERR(isc->hclock); 487 dev_err(dev, "failed to get hclock: %d\n", ret); 488 return ret; 489 } 490 491 ret = clk_prepare_enable(isc->hclock); 492 if (ret) { 493 dev_err(dev, "failed to enable hclock: %d\n", ret); 494 return ret; 495 } 496 497 ret = microchip_isc_clk_init(isc); 498 if (ret) { 499 dev_err(dev, "failed to init isc clock: %d\n", ret); 500 goto unprepare_hclk; 501 } 502 ret = v4l2_device_register(dev, &isc->v4l2_dev); 503 if (ret) { 504 dev_err(dev, "unable to register v4l2 device.\n"); 505 goto unprepare_clk; 506 } 507 508 ret = isc_parse_dt(dev, isc); 509 if (ret) { 510 dev_err(dev, "fail to parse device tree\n"); 511 goto unregister_v4l2_device; 512 } 513 514 if (list_empty(&isc->subdev_entities)) { 515 dev_err(dev, "no subdev found\n"); 516 ret = -ENODEV; 517 goto unregister_v4l2_device; 518 } 519 520 list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { 521 struct v4l2_async_connection *asd; 522 struct fwnode_handle *fwnode = 523 of_fwnode_handle(subdev_entity->epn); 524 525 v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev); 526 527 asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier, 528 fwnode, 529 struct v4l2_async_connection); 530 531 of_node_put(subdev_entity->epn); 532 subdev_entity->epn = NULL; 533 534 if (IS_ERR(asd)) { 535 ret = PTR_ERR(asd); 536 goto cleanup_subdev; 537 } 538 539 subdev_entity->notifier.ops = µchip_isc_async_ops; 540 541 ret = v4l2_async_nf_register(&subdev_entity->notifier); 542 if (ret) { 543 dev_err(dev, "fail to register async notifier\n"); 544 goto cleanup_subdev; 545 } 546 547 if (video_is_registered(&isc->video_dev)) 548 break; 549 } 550 551 regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver); 552 553 ret = isc_mc_init(isc, ver); 554 if (ret < 0) 555 goto isc_probe_mc_init_err; 556 557 pm_runtime_set_active(dev); 558 pm_runtime_enable(dev); 559 pm_request_idle(dev); 560 561 isc->ispck = isc->isc_clks[ISC_ISPCK].clk; 562 563 ret = clk_prepare_enable(isc->ispck); 564 if (ret) { 565 dev_err(dev, "failed to enable ispck: %d\n", ret); 566 goto disable_pm; 567 } 568 569 /* ispck should be greater or equal to hclock */ 570 ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); 571 if (ret) { 572 dev_err(dev, "failed to set ispck rate: %d\n", ret); 573 goto unprepare_clk; 574 } 575 576 dev_info(dev, "Microchip ISC version %x\n", ver); 577 578 return 0; 579 580 unprepare_clk: 581 clk_disable_unprepare(isc->ispck); 582 583 disable_pm: 584 pm_runtime_disable(dev); 585 586 isc_probe_mc_init_err: 587 isc_mc_cleanup(isc); 588 589 cleanup_subdev: 590 microchip_isc_subdev_cleanup(isc); 591 592 unregister_v4l2_device: 593 v4l2_device_unregister(&isc->v4l2_dev); 594 595 unprepare_hclk: 596 clk_disable_unprepare(isc->hclock); 597 598 microchip_isc_clk_cleanup(isc); 599 600 return ret; 601 } 602 603 static void microchip_isc_remove(struct platform_device *pdev) 604 { 605 struct isc_device *isc = platform_get_drvdata(pdev); 606 607 pm_runtime_disable(&pdev->dev); 608 609 isc_mc_cleanup(isc); 610 611 microchip_isc_subdev_cleanup(isc); 612 613 v4l2_device_unregister(&isc->v4l2_dev); 614 615 clk_disable_unprepare(isc->ispck); 616 clk_disable_unprepare(isc->hclock); 617 618 microchip_isc_clk_cleanup(isc); 619 } 620 621 static int __maybe_unused isc_runtime_suspend(struct device *dev) 622 { 623 struct isc_device *isc = dev_get_drvdata(dev); 624 625 clk_disable_unprepare(isc->ispck); 626 clk_disable_unprepare(isc->hclock); 627 628 return 0; 629 } 630 631 static int __maybe_unused isc_runtime_resume(struct device *dev) 632 { 633 struct isc_device *isc = dev_get_drvdata(dev); 634 int ret; 635 636 ret = clk_prepare_enable(isc->hclock); 637 if (ret) 638 return ret; 639 640 ret = clk_prepare_enable(isc->ispck); 641 if (ret) 642 clk_disable_unprepare(isc->hclock); 643 644 return ret; 645 } 646 647 static const struct dev_pm_ops microchip_isc_dev_pm_ops = { 648 SET_RUNTIME_PM_OPS(isc_runtime_suspend, isc_runtime_resume, NULL) 649 }; 650 651 #if IS_ENABLED(CONFIG_OF) 652 static const struct of_device_id microchip_isc_of_match[] = { 653 { .compatible = "atmel,sama5d2-isc" }, 654 { } 655 }; 656 MODULE_DEVICE_TABLE(of, microchip_isc_of_match); 657 #endif 658 659 static struct platform_driver microchip_isc_driver = { 660 .probe = microchip_isc_probe, 661 .remove = microchip_isc_remove, 662 .driver = { 663 .name = "microchip-sama5d2-isc", 664 .pm = µchip_isc_dev_pm_ops, 665 .of_match_table = of_match_ptr(microchip_isc_of_match), 666 }, 667 }; 668 669 module_platform_driver(microchip_isc_driver); 670 671 MODULE_AUTHOR("Songjun Wu"); 672 MODULE_DESCRIPTION("The V4L2 driver for Microchip-ISC"); 673 MODULE_LICENSE("GPL v2"); 674