1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 Renesas Electronics Corp. 4 * 5 * Driver for Renesas R-Car ISP Channel Selector 6 * 7 * The ISP hardware is capable of more than just channel selection, features 8 * such as demosaicing, white balance control and color space conversion are 9 * also possible. These more advanced features are not supported by the driver 10 * due to lack of documentation. 11 */ 12 13 #include <linux/module.h> 14 #include <linux/mutex.h> 15 #include <linux/of.h> 16 #include <linux/platform_device.h> 17 #include <linux/pm_runtime.h> 18 #include <linux/reset.h> 19 20 #include <media/mipi-csi2.h> 21 #include <media/v4l2-subdev.h> 22 23 #define ISPINPUTSEL0_REG 0x0008 24 #define ISPINPUTSEL0_SEL_CSI0 BIT(31) 25 26 #define ISPSTART_REG 0x0014 27 #define ISPSTART_START 0xffff 28 #define ISPSTART_STOP 0x0000 29 30 #define ISPPROCMODE_DT_REG(n) (0x1100 + (0x4 * (n))) 31 #define ISPPROCMODE_DT_PROC_MODE_VC3(pm) (((pm) & 0x3f) << 24) 32 #define ISPPROCMODE_DT_PROC_MODE_VC2(pm) (((pm) & 0x3f) << 16) 33 #define ISPPROCMODE_DT_PROC_MODE_VC1(pm) (((pm) & 0x3f) << 8) 34 #define ISPPROCMODE_DT_PROC_MODE_VC0(pm) ((pm) & 0x3f) 35 36 #define ISPCS_FILTER_ID_CH_REG(n) (0x3000 + (0x0100 * (n))) 37 38 #define ISPCS_DT_CODE03_CH_REG(n) (0x3008 + (0x100 * (n))) 39 #define ISPCS_DT_CODE03_EN3 BIT(31) 40 #define ISPCS_DT_CODE03_DT3(dt) (((dt) & 0x3f) << 24) 41 #define ISPCS_DT_CODE03_EN2 BIT(23) 42 #define ISPCS_DT_CODE03_DT2(dt) (((dt) & 0x3f) << 16) 43 #define ISPCS_DT_CODE03_EN1 BIT(15) 44 #define ISPCS_DT_CODE03_DT1(dt) (((dt) & 0x3f) << 8) 45 #define ISPCS_DT_CODE03_EN0 BIT(7) 46 #define ISPCS_DT_CODE03_DT0(dt) ((dt) & 0x3f) 47 48 struct rcar_isp_format { 49 u32 code; 50 unsigned int datatype; 51 unsigned int procmode; 52 }; 53 54 static const struct rcar_isp_format rcar_isp_formats[] = { 55 { 56 .code = MEDIA_BUS_FMT_RGB888_1X24, 57 .datatype = MIPI_CSI2_DT_RGB888, 58 .procmode = 0x15 59 }, { 60 .code = MEDIA_BUS_FMT_Y10_1X10, 61 .datatype = MIPI_CSI2_DT_RAW10, 62 .procmode = 0x10, 63 }, { 64 .code = MEDIA_BUS_FMT_UYVY8_1X16, 65 .datatype = MIPI_CSI2_DT_YUV422_8B, 66 .procmode = 0x0c, 67 }, { 68 .code = MEDIA_BUS_FMT_YUYV8_1X16, 69 .datatype = MIPI_CSI2_DT_YUV422_8B, 70 .procmode = 0x0c, 71 }, { 72 .code = MEDIA_BUS_FMT_UYVY8_2X8, 73 .datatype = MIPI_CSI2_DT_YUV422_8B, 74 .procmode = 0x0c, 75 }, { 76 .code = MEDIA_BUS_FMT_YUYV10_2X10, 77 .datatype = MIPI_CSI2_DT_YUV422_8B, 78 .procmode = 0x0c, 79 }, { 80 .code = MEDIA_BUS_FMT_SBGGR8_1X8, 81 .datatype = MIPI_CSI2_DT_RAW8, 82 .procmode = 0x00, 83 }, { 84 .code = MEDIA_BUS_FMT_SGBRG8_1X8, 85 .datatype = MIPI_CSI2_DT_RAW8, 86 .procmode = 0x00, 87 }, { 88 .code = MEDIA_BUS_FMT_SGRBG8_1X8, 89 .datatype = MIPI_CSI2_DT_RAW8, 90 .procmode = 0x00, 91 }, { 92 .code = MEDIA_BUS_FMT_SRGGB8_1X8, 93 .datatype = MIPI_CSI2_DT_RAW8, 94 .procmode = 0x00, 95 }, { 96 .code = MEDIA_BUS_FMT_SBGGR10_1X10, 97 .datatype = MIPI_CSI2_DT_RAW10, 98 .procmode = 0x01, 99 }, { 100 .code = MEDIA_BUS_FMT_SGBRG10_1X10, 101 .datatype = MIPI_CSI2_DT_RAW10, 102 .procmode = 0x01, 103 }, { 104 .code = MEDIA_BUS_FMT_SGRBG10_1X10, 105 .datatype = MIPI_CSI2_DT_RAW10, 106 .procmode = 0x01, 107 }, { 108 .code = MEDIA_BUS_FMT_SRGGB10_1X10, 109 .datatype = MIPI_CSI2_DT_RAW10, 110 .procmode = 0x01, 111 }, { 112 .code = MEDIA_BUS_FMT_SBGGR12_1X12, 113 .datatype = MIPI_CSI2_DT_RAW12, 114 .procmode = 0x02, 115 }, { 116 .code = MEDIA_BUS_FMT_SGBRG12_1X12, 117 .datatype = MIPI_CSI2_DT_RAW12, 118 .procmode = 0x02, 119 }, { 120 .code = MEDIA_BUS_FMT_SGRBG12_1X12, 121 .datatype = MIPI_CSI2_DT_RAW12, 122 .procmode = 0x02, 123 }, { 124 .code = MEDIA_BUS_FMT_SRGGB12_1X12, 125 .datatype = MIPI_CSI2_DT_RAW12, 126 .procmode = 0x02, 127 }, 128 }; 129 130 static const struct rcar_isp_format *risp_code_to_fmt(unsigned int code) 131 { 132 unsigned int i; 133 134 for (i = 0; i < ARRAY_SIZE(rcar_isp_formats); i++) { 135 if (rcar_isp_formats[i].code == code) 136 return &rcar_isp_formats[i]; 137 } 138 139 return NULL; 140 } 141 142 enum rcar_isp_input { 143 RISP_CSI_INPUT0, 144 RISP_CSI_INPUT1, 145 }; 146 147 enum rcar_isp_pads { 148 RCAR_ISP_SINK, 149 RCAR_ISP_PORT0, 150 RCAR_ISP_PORT1, 151 RCAR_ISP_PORT2, 152 RCAR_ISP_PORT3, 153 RCAR_ISP_PORT4, 154 RCAR_ISP_PORT5, 155 RCAR_ISP_PORT6, 156 RCAR_ISP_PORT7, 157 RCAR_ISP_NUM_PADS, 158 }; 159 160 struct rcar_isp { 161 struct device *dev; 162 void __iomem *csbase; 163 struct reset_control *rstc; 164 165 enum rcar_isp_input csi_input; 166 167 struct v4l2_subdev subdev; 168 struct media_pad pads[RCAR_ISP_NUM_PADS]; 169 170 struct v4l2_async_notifier notifier; 171 struct v4l2_subdev *remote; 172 unsigned int remote_pad; 173 174 int stream_count; 175 }; 176 177 static inline struct rcar_isp *sd_to_isp(struct v4l2_subdev *sd) 178 { 179 return container_of(sd, struct rcar_isp, subdev); 180 } 181 182 static inline struct rcar_isp *notifier_to_isp(struct v4l2_async_notifier *n) 183 { 184 return container_of(n, struct rcar_isp, notifier); 185 } 186 187 static void risp_write_cs(struct rcar_isp *isp, u32 offset, u32 value) 188 { 189 iowrite32(value, isp->csbase + offset); 190 } 191 192 static u32 risp_read_cs(struct rcar_isp *isp, u32 offset) 193 { 194 return ioread32(isp->csbase + offset); 195 } 196 197 static int risp_power_on(struct rcar_isp *isp) 198 { 199 int ret; 200 201 ret = pm_runtime_resume_and_get(isp->dev); 202 if (ret < 0) 203 return ret; 204 205 ret = reset_control_deassert(isp->rstc); 206 if (ret < 0) { 207 pm_runtime_put(isp->dev); 208 return ret; 209 } 210 211 return 0; 212 } 213 214 static void risp_power_off(struct rcar_isp *isp) 215 { 216 reset_control_assert(isp->rstc); 217 pm_runtime_put(isp->dev); 218 } 219 220 static int risp_start(struct rcar_isp *isp, struct v4l2_subdev_state *state) 221 { 222 const struct v4l2_mbus_framefmt *fmt; 223 const struct rcar_isp_format *format; 224 unsigned int vc; 225 u32 sel_csi = 0; 226 int ret; 227 228 fmt = v4l2_subdev_state_get_format(state, RCAR_ISP_SINK); 229 if (!fmt) 230 return -EINVAL; 231 232 format = risp_code_to_fmt(fmt->code); 233 if (!format) { 234 dev_err(isp->dev, "Unsupported bus format\n"); 235 return -EINVAL; 236 } 237 238 ret = risp_power_on(isp); 239 if (ret) { 240 dev_err(isp->dev, "Failed to power on ISP\n"); 241 return ret; 242 } 243 244 /* Select CSI-2 input source. */ 245 if (isp->csi_input == RISP_CSI_INPUT1) 246 sel_csi = ISPINPUTSEL0_SEL_CSI0; 247 248 risp_write_cs(isp, ISPINPUTSEL0_REG, 249 risp_read_cs(isp, ISPINPUTSEL0_REG) | sel_csi); 250 251 /* Configure Channel Selector. */ 252 for (vc = 0; vc < 4; vc++) { 253 u8 ch = vc + 4; 254 u8 dt = format->datatype; 255 256 risp_write_cs(isp, ISPCS_FILTER_ID_CH_REG(ch), BIT(vc)); 257 risp_write_cs(isp, ISPCS_DT_CODE03_CH_REG(ch), 258 ISPCS_DT_CODE03_EN3 | ISPCS_DT_CODE03_DT3(dt) | 259 ISPCS_DT_CODE03_EN2 | ISPCS_DT_CODE03_DT2(dt) | 260 ISPCS_DT_CODE03_EN1 | ISPCS_DT_CODE03_DT1(dt) | 261 ISPCS_DT_CODE03_EN0 | ISPCS_DT_CODE03_DT0(dt)); 262 } 263 264 /* Setup processing method. */ 265 risp_write_cs(isp, ISPPROCMODE_DT_REG(format->datatype), 266 ISPPROCMODE_DT_PROC_MODE_VC3(format->procmode) | 267 ISPPROCMODE_DT_PROC_MODE_VC2(format->procmode) | 268 ISPPROCMODE_DT_PROC_MODE_VC1(format->procmode) | 269 ISPPROCMODE_DT_PROC_MODE_VC0(format->procmode)); 270 271 /* Start ISP. */ 272 risp_write_cs(isp, ISPSTART_REG, ISPSTART_START); 273 274 ret = v4l2_subdev_enable_streams(isp->remote, isp->remote_pad, 275 BIT_ULL(0)); 276 if (ret) 277 risp_power_off(isp); 278 279 return ret; 280 } 281 282 static void risp_stop(struct rcar_isp *isp) 283 { 284 v4l2_subdev_disable_streams(isp->remote, isp->remote_pad, BIT_ULL(0)); 285 286 /* Stop ISP. */ 287 risp_write_cs(isp, ISPSTART_REG, ISPSTART_STOP); 288 289 risp_power_off(isp); 290 } 291 292 static int risp_enable_streams(struct v4l2_subdev *sd, 293 struct v4l2_subdev_state *state, u32 source_pad, 294 u64 source_streams_mask) 295 { 296 struct rcar_isp *isp = sd_to_isp(sd); 297 int ret = 0; 298 299 if (source_streams_mask != 1) 300 return -EINVAL; 301 302 if (!isp->remote) 303 return -ENODEV; 304 305 if (isp->stream_count == 0) { 306 ret = risp_start(isp, state); 307 if (ret) 308 return ret; 309 } 310 311 isp->stream_count += 1; 312 313 return ret; 314 } 315 316 static int risp_disable_streams(struct v4l2_subdev *sd, 317 struct v4l2_subdev_state *state, u32 source_pad, 318 u64 source_streams_mask) 319 { 320 struct rcar_isp *isp = sd_to_isp(sd); 321 322 if (source_streams_mask != 1) 323 return -EINVAL; 324 325 if (!isp->remote) 326 return -ENODEV; 327 328 if (isp->stream_count == 1) 329 risp_stop(isp); 330 331 isp->stream_count -= 1; 332 333 return 0; 334 } 335 336 static int risp_set_pad_format(struct v4l2_subdev *sd, 337 struct v4l2_subdev_state *state, 338 struct v4l2_subdev_format *format) 339 { 340 struct v4l2_mbus_framefmt *framefmt; 341 342 if (format->pad > RCAR_ISP_SINK) 343 return v4l2_subdev_get_fmt(sd, state, format); 344 345 if (!risp_code_to_fmt(format->format.code)) 346 format->format.code = rcar_isp_formats[0].code; 347 348 for (unsigned int i = 0; i < RCAR_ISP_NUM_PADS; i++) { 349 framefmt = v4l2_subdev_state_get_format(state, i); 350 *framefmt = format->format; 351 } 352 353 return 0; 354 } 355 356 static const struct v4l2_subdev_pad_ops risp_pad_ops = { 357 .enable_streams = risp_enable_streams, 358 .disable_streams = risp_disable_streams, 359 .set_fmt = risp_set_pad_format, 360 .get_fmt = v4l2_subdev_get_fmt, 361 .link_validate = v4l2_subdev_link_validate_default, 362 }; 363 364 static const struct v4l2_subdev_ops rcar_isp_subdev_ops = { 365 .pad = &risp_pad_ops, 366 }; 367 368 /* ----------------------------------------------------------------------------- 369 * Async handling and registration of subdevices and links 370 */ 371 372 static int risp_notify_bound(struct v4l2_async_notifier *notifier, 373 struct v4l2_subdev *subdev, 374 struct v4l2_async_connection *asd) 375 { 376 struct rcar_isp *isp = notifier_to_isp(notifier); 377 int pad; 378 379 pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode, 380 MEDIA_PAD_FL_SOURCE); 381 if (pad < 0) { 382 dev_err(isp->dev, "Failed to find pad for %s\n", subdev->name); 383 return pad; 384 } 385 386 isp->remote = subdev; 387 isp->remote_pad = pad; 388 389 dev_dbg(isp->dev, "Bound %s pad: %d\n", subdev->name, pad); 390 391 return media_create_pad_link(&subdev->entity, pad, 392 &isp->subdev.entity, 0, 393 MEDIA_LNK_FL_ENABLED | 394 MEDIA_LNK_FL_IMMUTABLE); 395 } 396 397 static void risp_notify_unbind(struct v4l2_async_notifier *notifier, 398 struct v4l2_subdev *subdev, 399 struct v4l2_async_connection *asd) 400 { 401 struct rcar_isp *isp = notifier_to_isp(notifier); 402 403 isp->remote = NULL; 404 405 dev_dbg(isp->dev, "Unbind %s\n", subdev->name); 406 } 407 408 static const struct v4l2_async_notifier_operations risp_notify_ops = { 409 .bound = risp_notify_bound, 410 .unbind = risp_notify_unbind, 411 }; 412 413 static int risp_parse_dt(struct rcar_isp *isp) 414 { 415 struct v4l2_async_connection *asd; 416 struct fwnode_handle *fwnode; 417 struct fwnode_handle *ep; 418 unsigned int id; 419 int ret; 420 421 for (id = 0; id < 2; id++) { 422 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(isp->dev), 423 0, id, 0); 424 if (ep) 425 break; 426 } 427 428 if (!ep) { 429 dev_err(isp->dev, "Not connected to subdevice\n"); 430 return -EINVAL; 431 } 432 433 if (id == 1) 434 isp->csi_input = RISP_CSI_INPUT1; 435 436 fwnode = fwnode_graph_get_remote_endpoint(ep); 437 fwnode_handle_put(ep); 438 439 dev_dbg(isp->dev, "Found '%pOF'\n", to_of_node(fwnode)); 440 441 v4l2_async_subdev_nf_init(&isp->notifier, &isp->subdev); 442 isp->notifier.ops = &risp_notify_ops; 443 444 asd = v4l2_async_nf_add_fwnode(&isp->notifier, fwnode, 445 struct v4l2_async_connection); 446 fwnode_handle_put(fwnode); 447 if (IS_ERR(asd)) 448 return PTR_ERR(asd); 449 450 ret = v4l2_async_nf_register(&isp->notifier); 451 if (ret) 452 v4l2_async_nf_cleanup(&isp->notifier); 453 454 return ret; 455 } 456 457 /* ----------------------------------------------------------------------------- 458 * Platform Device Driver 459 */ 460 461 static const struct media_entity_operations risp_entity_ops = { 462 .link_validate = v4l2_subdev_link_validate, 463 }; 464 465 static int risp_probe_resources(struct rcar_isp *isp, 466 struct platform_device *pdev) 467 { 468 struct resource *res; 469 470 /* 471 * For backward compatibility allow cs base to be the only reg if no 472 * reg-names are set in DT. 473 */ 474 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs"); 475 if (!res) 476 isp->csbase = devm_platform_ioremap_resource(pdev, 0); 477 else 478 isp->csbase = devm_ioremap_resource(&pdev->dev, res); 479 480 if (IS_ERR(isp->csbase)) 481 return PTR_ERR(isp->csbase); 482 483 isp->rstc = devm_reset_control_get(&pdev->dev, NULL); 484 485 return PTR_ERR_OR_ZERO(isp->rstc); 486 } 487 488 static const struct of_device_id risp_of_id_table[] = { 489 { .compatible = "renesas,r8a779a0-isp" }, 490 { .compatible = "renesas,r8a779g0-isp" }, 491 /* Keep above for compatibility with old DTB files. */ 492 { .compatible = "renesas,rcar-gen4-isp" }, 493 { /* sentinel */ } 494 }; 495 MODULE_DEVICE_TABLE(of, risp_of_id_table); 496 497 static int risp_probe(struct platform_device *pdev) 498 { 499 struct rcar_isp *isp; 500 unsigned int i; 501 int ret; 502 503 isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL); 504 if (!isp) 505 return -ENOMEM; 506 507 isp->dev = &pdev->dev; 508 509 ret = risp_probe_resources(isp, pdev); 510 if (ret) { 511 dev_err(isp->dev, "Failed to get resources\n"); 512 return ret; 513 } 514 515 platform_set_drvdata(pdev, isp); 516 517 pm_runtime_enable(&pdev->dev); 518 519 ret = risp_parse_dt(isp); 520 if (ret) 521 goto error_pm; 522 523 isp->subdev.owner = THIS_MODULE; 524 isp->subdev.dev = &pdev->dev; 525 v4l2_subdev_init(&isp->subdev, &rcar_isp_subdev_ops); 526 v4l2_set_subdevdata(&isp->subdev, &pdev->dev); 527 snprintf(isp->subdev.name, sizeof(isp->subdev.name), "%s %s", 528 KBUILD_MODNAME, dev_name(&pdev->dev)); 529 isp->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; 530 531 isp->subdev.entity.function = MEDIA_ENT_F_VID_MUX; 532 isp->subdev.entity.ops = &risp_entity_ops; 533 534 isp->pads[RCAR_ISP_SINK].flags = MEDIA_PAD_FL_SINK; 535 for (i = RCAR_ISP_PORT0; i < RCAR_ISP_NUM_PADS; i++) 536 isp->pads[i].flags = MEDIA_PAD_FL_SOURCE; 537 538 ret = media_entity_pads_init(&isp->subdev.entity, RCAR_ISP_NUM_PADS, 539 isp->pads); 540 if (ret) 541 goto error_notifier; 542 543 ret = v4l2_subdev_init_finalize(&isp->subdev); 544 if (ret) 545 goto error_notifier; 546 547 ret = v4l2_async_register_subdev(&isp->subdev); 548 if (ret < 0) 549 goto error_subdev; 550 551 dev_info(isp->dev, "Using CSI-2 input: %u\n", isp->csi_input); 552 553 return 0; 554 555 error_subdev: 556 v4l2_subdev_cleanup(&isp->subdev); 557 error_notifier: 558 v4l2_async_nf_unregister(&isp->notifier); 559 v4l2_async_nf_cleanup(&isp->notifier); 560 error_pm: 561 pm_runtime_disable(&pdev->dev); 562 563 return ret; 564 } 565 566 static void risp_remove(struct platform_device *pdev) 567 { 568 struct rcar_isp *isp = platform_get_drvdata(pdev); 569 570 v4l2_async_nf_unregister(&isp->notifier); 571 v4l2_async_nf_cleanup(&isp->notifier); 572 573 v4l2_async_unregister_subdev(&isp->subdev); 574 v4l2_subdev_cleanup(&isp->subdev); 575 576 pm_runtime_disable(&pdev->dev); 577 } 578 579 static struct platform_driver rcar_isp_driver = { 580 .driver = { 581 .name = "rcar-isp", 582 .suppress_bind_attrs = true, 583 .of_match_table = risp_of_id_table, 584 }, 585 .probe = risp_probe, 586 .remove = risp_remove, 587 }; 588 589 module_platform_driver(rcar_isp_driver); 590 591 MODULE_AUTHOR("Niklas Söderlund <niklas.soderlund@ragnatech.se>"); 592 MODULE_DESCRIPTION("Renesas R-Car ISP Channel Selector driver"); 593 MODULE_LICENSE("GPL"); 594