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 }; 81 82 static const struct rcar_isp_format *risp_code_to_fmt(unsigned int code) 83 { 84 unsigned int i; 85 86 for (i = 0; i < ARRAY_SIZE(rcar_isp_formats); i++) { 87 if (rcar_isp_formats[i].code == code) 88 return &rcar_isp_formats[i]; 89 } 90 91 return NULL; 92 } 93 94 enum rcar_isp_input { 95 RISP_CSI_INPUT0, 96 RISP_CSI_INPUT1, 97 }; 98 99 enum rcar_isp_pads { 100 RCAR_ISP_SINK, 101 RCAR_ISP_PORT0, 102 RCAR_ISP_PORT1, 103 RCAR_ISP_PORT2, 104 RCAR_ISP_PORT3, 105 RCAR_ISP_PORT4, 106 RCAR_ISP_PORT5, 107 RCAR_ISP_PORT6, 108 RCAR_ISP_PORT7, 109 RCAR_ISP_NUM_PADS, 110 }; 111 112 struct rcar_isp { 113 struct device *dev; 114 void __iomem *base; 115 struct reset_control *rstc; 116 117 enum rcar_isp_input csi_input; 118 119 struct v4l2_subdev subdev; 120 struct media_pad pads[RCAR_ISP_NUM_PADS]; 121 122 struct v4l2_async_notifier notifier; 123 struct v4l2_subdev *remote; 124 125 struct mutex lock; /* Protects mf and stream_count. */ 126 struct v4l2_mbus_framefmt mf; 127 int stream_count; 128 }; 129 130 static inline struct rcar_isp *sd_to_isp(struct v4l2_subdev *sd) 131 { 132 return container_of(sd, struct rcar_isp, subdev); 133 } 134 135 static inline struct rcar_isp *notifier_to_isp(struct v4l2_async_notifier *n) 136 { 137 return container_of(n, struct rcar_isp, notifier); 138 } 139 140 static void risp_write(struct rcar_isp *isp, u32 offset, u32 value) 141 { 142 iowrite32(value, isp->base + offset); 143 } 144 145 static u32 risp_read(struct rcar_isp *isp, u32 offset) 146 { 147 return ioread32(isp->base + offset); 148 } 149 150 static int risp_power_on(struct rcar_isp *isp) 151 { 152 int ret; 153 154 ret = pm_runtime_resume_and_get(isp->dev); 155 if (ret < 0) 156 return ret; 157 158 ret = reset_control_deassert(isp->rstc); 159 if (ret < 0) { 160 pm_runtime_put(isp->dev); 161 return ret; 162 } 163 164 return 0; 165 } 166 167 static void risp_power_off(struct rcar_isp *isp) 168 { 169 reset_control_assert(isp->rstc); 170 pm_runtime_put(isp->dev); 171 } 172 173 static int risp_start(struct rcar_isp *isp) 174 { 175 const struct rcar_isp_format *format; 176 unsigned int vc; 177 u32 sel_csi = 0; 178 int ret; 179 180 format = risp_code_to_fmt(isp->mf.code); 181 if (!format) { 182 dev_err(isp->dev, "Unsupported bus format\n"); 183 return -EINVAL; 184 } 185 186 ret = risp_power_on(isp); 187 if (ret) { 188 dev_err(isp->dev, "Failed to power on ISP\n"); 189 return ret; 190 } 191 192 /* Select CSI-2 input source. */ 193 if (isp->csi_input == RISP_CSI_INPUT1) 194 sel_csi = ISPINPUTSEL0_SEL_CSI0; 195 196 risp_write(isp, ISPINPUTSEL0_REG, 197 risp_read(isp, ISPINPUTSEL0_REG) | sel_csi); 198 199 /* Configure Channel Selector. */ 200 for (vc = 0; vc < 4; vc++) { 201 u8 ch = vc + 4; 202 u8 dt = format->datatype; 203 204 risp_write(isp, ISPCS_FILTER_ID_CH_REG(ch), BIT(vc)); 205 risp_write(isp, ISPCS_DT_CODE03_CH_REG(ch), 206 ISPCS_DT_CODE03_EN3 | ISPCS_DT_CODE03_DT3(dt) | 207 ISPCS_DT_CODE03_EN2 | ISPCS_DT_CODE03_DT2(dt) | 208 ISPCS_DT_CODE03_EN1 | ISPCS_DT_CODE03_DT1(dt) | 209 ISPCS_DT_CODE03_EN0 | ISPCS_DT_CODE03_DT0(dt)); 210 } 211 212 /* Setup processing method. */ 213 risp_write(isp, ISPPROCMODE_DT_REG(format->datatype), 214 ISPPROCMODE_DT_PROC_MODE_VC3(format->procmode) | 215 ISPPROCMODE_DT_PROC_MODE_VC2(format->procmode) | 216 ISPPROCMODE_DT_PROC_MODE_VC1(format->procmode) | 217 ISPPROCMODE_DT_PROC_MODE_VC0(format->procmode)); 218 219 /* Start ISP. */ 220 risp_write(isp, ISPSTART_REG, ISPSTART_START); 221 222 ret = v4l2_subdev_call(isp->remote, video, s_stream, 1); 223 if (ret) 224 risp_power_off(isp); 225 226 return ret; 227 } 228 229 static void risp_stop(struct rcar_isp *isp) 230 { 231 v4l2_subdev_call(isp->remote, video, s_stream, 0); 232 233 /* Stop ISP. */ 234 risp_write(isp, ISPSTART_REG, ISPSTART_STOP); 235 236 risp_power_off(isp); 237 } 238 239 static int risp_s_stream(struct v4l2_subdev *sd, int enable) 240 { 241 struct rcar_isp *isp = sd_to_isp(sd); 242 int ret = 0; 243 244 mutex_lock(&isp->lock); 245 246 if (!isp->remote) { 247 ret = -ENODEV; 248 goto out; 249 } 250 251 if (enable && isp->stream_count == 0) { 252 ret = risp_start(isp); 253 if (ret) 254 goto out; 255 } else if (!enable && isp->stream_count == 1) { 256 risp_stop(isp); 257 } 258 259 isp->stream_count += enable ? 1 : -1; 260 out: 261 mutex_unlock(&isp->lock); 262 263 return ret; 264 } 265 266 static const struct v4l2_subdev_video_ops risp_video_ops = { 267 .s_stream = risp_s_stream, 268 }; 269 270 static int risp_set_pad_format(struct v4l2_subdev *sd, 271 struct v4l2_subdev_state *sd_state, 272 struct v4l2_subdev_format *format) 273 { 274 struct rcar_isp *isp = sd_to_isp(sd); 275 struct v4l2_mbus_framefmt *framefmt; 276 277 mutex_lock(&isp->lock); 278 279 if (!risp_code_to_fmt(format->format.code)) 280 format->format.code = rcar_isp_formats[0].code; 281 282 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 283 isp->mf = format->format; 284 } else { 285 framefmt = v4l2_subdev_state_get_format(sd_state, 0); 286 *framefmt = format->format; 287 } 288 289 mutex_unlock(&isp->lock); 290 291 return 0; 292 } 293 294 static int risp_get_pad_format(struct v4l2_subdev *sd, 295 struct v4l2_subdev_state *sd_state, 296 struct v4l2_subdev_format *format) 297 { 298 struct rcar_isp *isp = sd_to_isp(sd); 299 300 mutex_lock(&isp->lock); 301 302 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) 303 format->format = isp->mf; 304 else 305 format->format = *v4l2_subdev_state_get_format(sd_state, 0); 306 307 mutex_unlock(&isp->lock); 308 309 return 0; 310 } 311 312 static const struct v4l2_subdev_pad_ops risp_pad_ops = { 313 .set_fmt = risp_set_pad_format, 314 .get_fmt = risp_get_pad_format, 315 .link_validate = v4l2_subdev_link_validate_default, 316 }; 317 318 static const struct v4l2_subdev_ops rcar_isp_subdev_ops = { 319 .video = &risp_video_ops, 320 .pad = &risp_pad_ops, 321 }; 322 323 /* ----------------------------------------------------------------------------- 324 * Async handling and registration of subdevices and links 325 */ 326 327 static int risp_notify_bound(struct v4l2_async_notifier *notifier, 328 struct v4l2_subdev *subdev, 329 struct v4l2_async_connection *asd) 330 { 331 struct rcar_isp *isp = notifier_to_isp(notifier); 332 int pad; 333 334 pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode, 335 MEDIA_PAD_FL_SOURCE); 336 if (pad < 0) { 337 dev_err(isp->dev, "Failed to find pad for %s\n", subdev->name); 338 return pad; 339 } 340 341 isp->remote = subdev; 342 343 dev_dbg(isp->dev, "Bound %s pad: %d\n", subdev->name, pad); 344 345 return media_create_pad_link(&subdev->entity, pad, 346 &isp->subdev.entity, 0, 347 MEDIA_LNK_FL_ENABLED | 348 MEDIA_LNK_FL_IMMUTABLE); 349 } 350 351 static void risp_notify_unbind(struct v4l2_async_notifier *notifier, 352 struct v4l2_subdev *subdev, 353 struct v4l2_async_connection *asd) 354 { 355 struct rcar_isp *isp = notifier_to_isp(notifier); 356 357 isp->remote = NULL; 358 359 dev_dbg(isp->dev, "Unbind %s\n", subdev->name); 360 } 361 362 static const struct v4l2_async_notifier_operations risp_notify_ops = { 363 .bound = risp_notify_bound, 364 .unbind = risp_notify_unbind, 365 }; 366 367 static int risp_parse_dt(struct rcar_isp *isp) 368 { 369 struct v4l2_async_connection *asd; 370 struct fwnode_handle *fwnode; 371 struct fwnode_handle *ep; 372 unsigned int id; 373 int ret; 374 375 for (id = 0; id < 2; id++) { 376 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(isp->dev), 377 0, id, 0); 378 if (ep) 379 break; 380 } 381 382 if (!ep) { 383 dev_err(isp->dev, "Not connected to subdevice\n"); 384 return -EINVAL; 385 } 386 387 if (id == 1) 388 isp->csi_input = RISP_CSI_INPUT1; 389 390 fwnode = fwnode_graph_get_remote_endpoint(ep); 391 fwnode_handle_put(ep); 392 393 dev_dbg(isp->dev, "Found '%pOF'\n", to_of_node(fwnode)); 394 395 v4l2_async_subdev_nf_init(&isp->notifier, &isp->subdev); 396 isp->notifier.ops = &risp_notify_ops; 397 398 asd = v4l2_async_nf_add_fwnode(&isp->notifier, fwnode, 399 struct v4l2_async_connection); 400 fwnode_handle_put(fwnode); 401 if (IS_ERR(asd)) 402 return PTR_ERR(asd); 403 404 ret = v4l2_async_nf_register(&isp->notifier); 405 if (ret) 406 v4l2_async_nf_cleanup(&isp->notifier); 407 408 return ret; 409 } 410 411 /* ----------------------------------------------------------------------------- 412 * Platform Device Driver 413 */ 414 415 static const struct media_entity_operations risp_entity_ops = { 416 .link_validate = v4l2_subdev_link_validate, 417 }; 418 419 static int risp_probe_resources(struct rcar_isp *isp, 420 struct platform_device *pdev) 421 { 422 isp->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 423 if (IS_ERR(isp->base)) 424 return PTR_ERR(isp->base); 425 426 isp->rstc = devm_reset_control_get(&pdev->dev, NULL); 427 428 return PTR_ERR_OR_ZERO(isp->rstc); 429 } 430 431 static const struct of_device_id risp_of_id_table[] = { 432 { .compatible = "renesas,r8a779a0-isp" }, 433 { .compatible = "renesas,r8a779g0-isp" }, 434 { /* sentinel */ }, 435 }; 436 MODULE_DEVICE_TABLE(of, risp_of_id_table); 437 438 static int risp_probe(struct platform_device *pdev) 439 { 440 struct rcar_isp *isp; 441 unsigned int i; 442 int ret; 443 444 isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL); 445 if (!isp) 446 return -ENOMEM; 447 448 isp->dev = &pdev->dev; 449 450 mutex_init(&isp->lock); 451 452 ret = risp_probe_resources(isp, pdev); 453 if (ret) { 454 dev_err(isp->dev, "Failed to get resources\n"); 455 goto error_mutex; 456 } 457 458 platform_set_drvdata(pdev, isp); 459 460 pm_runtime_enable(&pdev->dev); 461 462 ret = risp_parse_dt(isp); 463 if (ret) 464 goto error_pm; 465 466 isp->subdev.owner = THIS_MODULE; 467 isp->subdev.dev = &pdev->dev; 468 v4l2_subdev_init(&isp->subdev, &rcar_isp_subdev_ops); 469 v4l2_set_subdevdata(&isp->subdev, &pdev->dev); 470 snprintf(isp->subdev.name, sizeof(isp->subdev.name), "%s %s", 471 KBUILD_MODNAME, dev_name(&pdev->dev)); 472 isp->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; 473 474 isp->subdev.entity.function = MEDIA_ENT_F_VID_MUX; 475 isp->subdev.entity.ops = &risp_entity_ops; 476 477 isp->pads[RCAR_ISP_SINK].flags = MEDIA_PAD_FL_SINK; 478 for (i = RCAR_ISP_PORT0; i < RCAR_ISP_NUM_PADS; i++) 479 isp->pads[i].flags = MEDIA_PAD_FL_SOURCE; 480 481 ret = media_entity_pads_init(&isp->subdev.entity, RCAR_ISP_NUM_PADS, 482 isp->pads); 483 if (ret) 484 goto error_notifier; 485 486 ret = v4l2_async_register_subdev(&isp->subdev); 487 if (ret < 0) 488 goto error_notifier; 489 490 dev_info(isp->dev, "Using CSI-2 input: %u\n", isp->csi_input); 491 492 return 0; 493 error_notifier: 494 v4l2_async_nf_unregister(&isp->notifier); 495 v4l2_async_nf_cleanup(&isp->notifier); 496 error_pm: 497 pm_runtime_disable(&pdev->dev); 498 error_mutex: 499 mutex_destroy(&isp->lock); 500 501 return ret; 502 } 503 504 static void risp_remove(struct platform_device *pdev) 505 { 506 struct rcar_isp *isp = platform_get_drvdata(pdev); 507 508 v4l2_async_nf_unregister(&isp->notifier); 509 v4l2_async_nf_cleanup(&isp->notifier); 510 511 v4l2_async_unregister_subdev(&isp->subdev); 512 513 pm_runtime_disable(&pdev->dev); 514 515 mutex_destroy(&isp->lock); 516 } 517 518 static struct platform_driver rcar_isp_driver = { 519 .driver = { 520 .name = "rcar-isp", 521 .suppress_bind_attrs = true, 522 .of_match_table = risp_of_id_table, 523 }, 524 .probe = risp_probe, 525 .remove_new = risp_remove, 526 }; 527 528 module_platform_driver(rcar_isp_driver); 529 530 MODULE_AUTHOR("Niklas Söderlund <niklas.soderlund@ragnatech.se>"); 531 MODULE_DESCRIPTION("Renesas R-Car ISP Channel Selector driver"); 532 MODULE_LICENSE("GPL"); 533