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