1e6938cc1SHelen Koike // SPDX-License-Identifier: (GPL-2.0+ OR MIT) 2e6938cc1SHelen Koike /* 3e6938cc1SHelen Koike * Rockchip ISP1 Driver - Base driver 4e6938cc1SHelen Koike * 5e6938cc1SHelen Koike * Copyright (C) 2019 Collabora, Ltd. 6e6938cc1SHelen Koike * 7e6938cc1SHelen Koike * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. 8e6938cc1SHelen Koike * Copyright (C) 2017 Rockchip Electronics Co., Ltd. 9e6938cc1SHelen Koike */ 10e6938cc1SHelen Koike 11e6938cc1SHelen Koike #include <linux/clk.h> 12e6938cc1SHelen Koike #include <linux/debugfs.h> 13e6938cc1SHelen Koike #include <linux/interrupt.h> 14e6938cc1SHelen Koike #include <linux/module.h> 15e6938cc1SHelen Koike #include <linux/of.h> 16e6938cc1SHelen Koike #include <linux/of_graph.h> 17e6938cc1SHelen Koike #include <linux/of_platform.h> 18e6938cc1SHelen Koike #include <linux/pinctrl/consumer.h> 19e6938cc1SHelen Koike #include <linux/phy/phy.h> 20e6938cc1SHelen Koike #include <linux/phy/phy-mipi-dphy.h> 21e6938cc1SHelen Koike #include <media/v4l2-fwnode.h> 22e6938cc1SHelen Koike 23e6938cc1SHelen Koike #include "rkisp1-common.h" 24e6938cc1SHelen Koike 25e6938cc1SHelen Koike /* 26e6938cc1SHelen Koike * ISP Details 27e6938cc1SHelen Koike * ----------- 28e6938cc1SHelen Koike * 29e6938cc1SHelen Koike * ISP Comprises with: 30e6938cc1SHelen Koike * MIPI serial camera interface 31e6938cc1SHelen Koike * Image Signal Processing 32e6938cc1SHelen Koike * Many Image Enhancement Blocks 33e6938cc1SHelen Koike * Crop 34e6938cc1SHelen Koike * Resizer 35e6938cc1SHelen Koike * RBG display ready image 36e6938cc1SHelen Koike * Image Rotation 37e6938cc1SHelen Koike * 38e6938cc1SHelen Koike * ISP Block Diagram 39e6938cc1SHelen Koike * ----------------- 40e6938cc1SHelen Koike * rkisp1-resizer.c rkisp1-capture.c 41e6938cc1SHelen Koike * |====================| |=======================| 42e6938cc1SHelen Koike * rkisp1-isp.c Main Picture Path 43e6938cc1SHelen Koike * |==========================| |===============================================| 44e6938cc1SHelen Koike * +-----------+ +--+--+--+--+ +--------+ +--------+ +-----------+ 45e6938cc1SHelen Koike * | | | | | | | | | | | | | 46e6938cc1SHelen Koike * +--------+ |\ | | | | | | | -->| Crop |->| RSZ |------------->| | 47e6938cc1SHelen Koike * | MIPI |--->| \ | | | | | | | | | | | | | | 48e6938cc1SHelen Koike * +--------+ | | | | |IE|IE|IE|IE| | +--------+ +--------+ | Memory | 49e6938cc1SHelen Koike * |MUX|--->| ISP |->|0 |1 |2 |3 |---+ | Interface | 50e6938cc1SHelen Koike * +--------+ | | | | | | | | | | +--------+ +--------+ +--------+ | | 51e6938cc1SHelen Koike * |Parallel|--->| / | | | | | | | | | | | | | | | | 52e6938cc1SHelen Koike * +--------+ |/ | | | | | | | -->| Crop |->| RSZ |->| RGB |->| | 53e6938cc1SHelen Koike * | | | | | | | | | | | | Rotate | | | 54e6938cc1SHelen Koike * +-----------+ +--+--+--+--+ +--------+ +--------+ +--------+ +-----------+ 55e6938cc1SHelen Koike * ^ 56e6938cc1SHelen Koike * +--------+ | |===============================================| 57e6938cc1SHelen Koike * | DMA |------------------------------------+ Self Picture Path 58e6938cc1SHelen Koike * +--------+ 59e6938cc1SHelen Koike * 60e6938cc1SHelen Koike * rkisp1-stats.c rkisp1-params.c 61e6938cc1SHelen Koike * |===============| |===============| 62e6938cc1SHelen Koike * +---------------+ +---------------+ 63e6938cc1SHelen Koike * | | | | 64e6938cc1SHelen Koike * | ISP | | ISP | 65e6938cc1SHelen Koike * | | | | 66e6938cc1SHelen Koike * +---------------+ +---------------+ 67e6938cc1SHelen Koike * 68e6938cc1SHelen Koike * 69e6938cc1SHelen Koike * Media Topology 70e6938cc1SHelen Koike * -------------- 71e6938cc1SHelen Koike * +----------+ +----------+ 72e6938cc1SHelen Koike * | Sensor 2 | | Sensor X | 73e6938cc1SHelen Koike * ------------ ... ------------ 74e6938cc1SHelen Koike * | 0 | | 0 | 75e6938cc1SHelen Koike * +----------+ +----------+ +-----------+ 76e6938cc1SHelen Koike * \ | | params | 77e6938cc1SHelen Koike * \ | | (output) | 78e6938cc1SHelen Koike * +----------+ \ | +-----------+ 79e6938cc1SHelen Koike * | Sensor 1 | v v | 80e6938cc1SHelen Koike * ------------ +------+------+ | 81e6938cc1SHelen Koike * | 0 |----->| 0 | 1 |<---------+ 82e6938cc1SHelen Koike * +----------+ |------+------| 83e6938cc1SHelen Koike * | ISP | 84e6938cc1SHelen Koike * |------+------| 85e6938cc1SHelen Koike * +-------------| 2 | 3 |----------+ 86e6938cc1SHelen Koike * | +------+------+ | 87e6938cc1SHelen Koike * | | | 88e6938cc1SHelen Koike * v v v 89e6938cc1SHelen Koike * +- ---------+ +-----------+ +-----------+ 90e6938cc1SHelen Koike * | 0 | | 0 | | stats | 91e6938cc1SHelen Koike * ------------- ------------- | (capture) | 92e6938cc1SHelen Koike * | Resizer | | Resizer | +-----------+ 93e6938cc1SHelen Koike * ------------| ------------| 94e6938cc1SHelen Koike * | 1 | | 1 | 95e6938cc1SHelen Koike * +-----------+ +-----------+ 96e6938cc1SHelen Koike * | | 97e6938cc1SHelen Koike * v v 98e6938cc1SHelen Koike * +-----------+ +-----------+ 99e6938cc1SHelen Koike * | selfpath | | mainpath | 100e6938cc1SHelen Koike * | (capture) | | (capture) | 101e6938cc1SHelen Koike * +-----------+ +-----------+ 102e6938cc1SHelen Koike */ 103e6938cc1SHelen Koike 104e6938cc1SHelen Koike struct rkisp1_match_data { 105e6938cc1SHelen Koike const char * const *clks; 106e6938cc1SHelen Koike unsigned int size; 107e6938cc1SHelen Koike }; 108e6938cc1SHelen Koike 109e6938cc1SHelen Koike /* ---------------------------------------------------------------------------- 110e6938cc1SHelen Koike * Sensor DT bindings 111e6938cc1SHelen Koike */ 112e6938cc1SHelen Koike 113e6938cc1SHelen Koike static int rkisp1_create_links(struct rkisp1_device *rkisp1) 114e6938cc1SHelen Koike { 115e6938cc1SHelen Koike struct media_entity *source, *sink; 116e6938cc1SHelen Koike unsigned int flags, source_pad; 117e6938cc1SHelen Koike struct v4l2_subdev *sd; 118e6938cc1SHelen Koike unsigned int i; 119e6938cc1SHelen Koike int ret; 120e6938cc1SHelen Koike 121e6938cc1SHelen Koike /* sensor links */ 122e6938cc1SHelen Koike flags = MEDIA_LNK_FL_ENABLED; 123e6938cc1SHelen Koike list_for_each_entry(sd, &rkisp1->v4l2_dev.subdevs, list) { 124e6938cc1SHelen Koike if (sd == &rkisp1->isp.sd || 125e6938cc1SHelen Koike sd == &rkisp1->resizer_devs[RKISP1_MAINPATH].sd || 126e6938cc1SHelen Koike sd == &rkisp1->resizer_devs[RKISP1_SELFPATH].sd) 127e6938cc1SHelen Koike continue; 128e6938cc1SHelen Koike 129e6938cc1SHelen Koike ret = media_entity_get_fwnode_pad(&sd->entity, sd->fwnode, 130e6938cc1SHelen Koike MEDIA_PAD_FL_SOURCE); 131e6938cc1SHelen Koike if (ret < 0) { 132e6938cc1SHelen Koike dev_err(rkisp1->dev, "failed to find src pad for %s\n", 133e6938cc1SHelen Koike sd->name); 134e6938cc1SHelen Koike return ret; 135e6938cc1SHelen Koike } 136e6938cc1SHelen Koike source_pad = ret; 137e6938cc1SHelen Koike 138e6938cc1SHelen Koike ret = media_create_pad_link(&sd->entity, source_pad, 139e6938cc1SHelen Koike &rkisp1->isp.sd.entity, 140e6938cc1SHelen Koike RKISP1_ISP_PAD_SINK_VIDEO, 141e6938cc1SHelen Koike flags); 142e6938cc1SHelen Koike if (ret) 143e6938cc1SHelen Koike return ret; 144e6938cc1SHelen Koike 145e6938cc1SHelen Koike flags = 0; 146e6938cc1SHelen Koike } 147e6938cc1SHelen Koike 148e6938cc1SHelen Koike flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; 149e6938cc1SHelen Koike 150e6938cc1SHelen Koike /* create ISP->RSZ->CAP links */ 151e6938cc1SHelen Koike for (i = 0; i < 2; i++) { 152e6938cc1SHelen Koike source = &rkisp1->isp.sd.entity; 153e6938cc1SHelen Koike sink = &rkisp1->resizer_devs[i].sd.entity; 154e6938cc1SHelen Koike ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_VIDEO, 155e6938cc1SHelen Koike sink, RKISP1_RSZ_PAD_SINK, 156e6938cc1SHelen Koike MEDIA_LNK_FL_ENABLED); 157e6938cc1SHelen Koike if (ret) 158e6938cc1SHelen Koike return ret; 159e6938cc1SHelen Koike 160e6938cc1SHelen Koike source = sink; 161e6938cc1SHelen Koike sink = &rkisp1->capture_devs[i].vnode.vdev.entity; 162e6938cc1SHelen Koike ret = media_create_pad_link(source, RKISP1_RSZ_PAD_SRC, 163e6938cc1SHelen Koike sink, 0, flags); 164e6938cc1SHelen Koike if (ret) 165e6938cc1SHelen Koike return ret; 166e6938cc1SHelen Koike } 167e6938cc1SHelen Koike 168e6938cc1SHelen Koike /* params links */ 169e6938cc1SHelen Koike source = &rkisp1->params.vnode.vdev.entity; 170e6938cc1SHelen Koike sink = &rkisp1->isp.sd.entity; 171e6938cc1SHelen Koike ret = media_create_pad_link(source, 0, sink, 172e6938cc1SHelen Koike RKISP1_ISP_PAD_SINK_PARAMS, flags); 173e6938cc1SHelen Koike if (ret) 174e6938cc1SHelen Koike return ret; 175e6938cc1SHelen Koike 176e6938cc1SHelen Koike /* 3A stats links */ 177e6938cc1SHelen Koike source = &rkisp1->isp.sd.entity; 178e6938cc1SHelen Koike sink = &rkisp1->stats.vnode.vdev.entity; 179e6938cc1SHelen Koike return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS, 180e6938cc1SHelen Koike sink, 0, flags); 181e6938cc1SHelen Koike } 182e6938cc1SHelen Koike 183e6938cc1SHelen Koike static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier, 184e6938cc1SHelen Koike struct v4l2_subdev *sd, 185e6938cc1SHelen Koike struct v4l2_async_subdev *asd) 186e6938cc1SHelen Koike { 187e6938cc1SHelen Koike struct rkisp1_device *rkisp1 = 188e6938cc1SHelen Koike container_of(notifier, struct rkisp1_device, notifier); 189e6938cc1SHelen Koike struct rkisp1_sensor_async *s_asd = 190e6938cc1SHelen Koike container_of(asd, struct rkisp1_sensor_async, asd); 191e6938cc1SHelen Koike 192e6938cc1SHelen Koike s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler, 193e6938cc1SHelen Koike V4L2_CID_PIXEL_RATE); 194e6938cc1SHelen Koike s_asd->sd = sd; 195e6938cc1SHelen Koike s_asd->dphy = devm_phy_get(rkisp1->dev, "dphy"); 196e6938cc1SHelen Koike if (IS_ERR(s_asd->dphy)) { 197e6938cc1SHelen Koike if (PTR_ERR(s_asd->dphy) != -EPROBE_DEFER) 198e6938cc1SHelen Koike dev_err(rkisp1->dev, "Couldn't get the MIPI D-PHY\n"); 199e6938cc1SHelen Koike return PTR_ERR(s_asd->dphy); 200e6938cc1SHelen Koike } 201e6938cc1SHelen Koike 202e6938cc1SHelen Koike phy_init(s_asd->dphy); 203e6938cc1SHelen Koike 204e6938cc1SHelen Koike return 0; 205e6938cc1SHelen Koike } 206e6938cc1SHelen Koike 207e6938cc1SHelen Koike static void rkisp1_subdev_notifier_unbind(struct v4l2_async_notifier *notifier, 208e6938cc1SHelen Koike struct v4l2_subdev *sd, 209e6938cc1SHelen Koike struct v4l2_async_subdev *asd) 210e6938cc1SHelen Koike { 211e6938cc1SHelen Koike struct rkisp1_sensor_async *s_asd = 212e6938cc1SHelen Koike container_of(asd, struct rkisp1_sensor_async, asd); 213e6938cc1SHelen Koike 214e6938cc1SHelen Koike phy_exit(s_asd->dphy); 215e6938cc1SHelen Koike } 216e6938cc1SHelen Koike 217e6938cc1SHelen Koike static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier) 218e6938cc1SHelen Koike { 219e6938cc1SHelen Koike struct rkisp1_device *rkisp1 = 220e6938cc1SHelen Koike container_of(notifier, struct rkisp1_device, notifier); 221e6938cc1SHelen Koike int ret; 222e6938cc1SHelen Koike 223e6938cc1SHelen Koike ret = rkisp1_create_links(rkisp1); 224e6938cc1SHelen Koike if (ret) 225e6938cc1SHelen Koike return ret; 226e6938cc1SHelen Koike 227e6938cc1SHelen Koike ret = v4l2_device_register_subdev_nodes(&rkisp1->v4l2_dev); 228e6938cc1SHelen Koike if (ret) 229e6938cc1SHelen Koike return ret; 230e6938cc1SHelen Koike 231e6938cc1SHelen Koike dev_dbg(rkisp1->dev, "Async subdev notifier completed\n"); 232e6938cc1SHelen Koike 233e6938cc1SHelen Koike return 0; 234e6938cc1SHelen Koike } 235e6938cc1SHelen Koike 236e6938cc1SHelen Koike static const struct v4l2_async_notifier_operations rkisp1_subdev_notifier_ops = { 237e6938cc1SHelen Koike .bound = rkisp1_subdev_notifier_bound, 238e6938cc1SHelen Koike .unbind = rkisp1_subdev_notifier_unbind, 239e6938cc1SHelen Koike .complete = rkisp1_subdev_notifier_complete, 240e6938cc1SHelen Koike }; 241e6938cc1SHelen Koike 242e6938cc1SHelen Koike static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1) 243e6938cc1SHelen Koike { 244e6938cc1SHelen Koike struct v4l2_async_notifier *ntf = &rkisp1->notifier; 245e6938cc1SHelen Koike unsigned int next_id = 0; 246e6938cc1SHelen Koike int ret; 247e6938cc1SHelen Koike 248e6938cc1SHelen Koike v4l2_async_notifier_init(ntf); 249e6938cc1SHelen Koike 250e6938cc1SHelen Koike while (1) { 251e6938cc1SHelen Koike struct v4l2_fwnode_endpoint vep = { 252e6938cc1SHelen Koike .bus_type = V4L2_MBUS_CSI2_DPHY 253e6938cc1SHelen Koike }; 254*b01edcbdSLaurent Pinchart struct rkisp1_sensor_async *rk_asd; 255e6938cc1SHelen Koike struct fwnode_handle *ep; 256e6938cc1SHelen Koike 257e6938cc1SHelen Koike ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev), 258e6938cc1SHelen Koike 0, next_id, 259e6938cc1SHelen Koike FWNODE_GRAPH_ENDPOINT_NEXT); 260e6938cc1SHelen Koike if (!ep) 261e6938cc1SHelen Koike break; 262e6938cc1SHelen Koike 263e6938cc1SHelen Koike ret = v4l2_fwnode_endpoint_parse(ep, &vep); 264e6938cc1SHelen Koike if (ret) 265e6938cc1SHelen Koike goto err_parse; 266e6938cc1SHelen Koike 267*b01edcbdSLaurent Pinchart rk_asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep, 268*b01edcbdSLaurent Pinchart struct rkisp1_sensor_async); 269*b01edcbdSLaurent Pinchart if (IS_ERR(rk_asd)) { 270*b01edcbdSLaurent Pinchart ret = PTR_ERR(rk_asd); 271e6938cc1SHelen Koike goto err_parse; 272e6938cc1SHelen Koike } 273e6938cc1SHelen Koike 274e6938cc1SHelen Koike rk_asd->mbus_type = vep.bus_type; 275e6938cc1SHelen Koike rk_asd->mbus_flags = vep.bus.mipi_csi2.flags; 276e6938cc1SHelen Koike rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes; 277e6938cc1SHelen Koike 278e6938cc1SHelen Koike dev_dbg(rkisp1->dev, "registered ep id %d with %d lanes\n", 279e6938cc1SHelen Koike vep.base.id, rk_asd->lanes); 280e6938cc1SHelen Koike 281e6938cc1SHelen Koike next_id = vep.base.id + 1; 282e6938cc1SHelen Koike 283e6938cc1SHelen Koike fwnode_handle_put(ep); 284e6938cc1SHelen Koike 285e6938cc1SHelen Koike continue; 286e6938cc1SHelen Koike err_parse: 287e6938cc1SHelen Koike fwnode_handle_put(ep); 288e6938cc1SHelen Koike v4l2_async_notifier_cleanup(ntf); 289e6938cc1SHelen Koike return ret; 290e6938cc1SHelen Koike } 291e6938cc1SHelen Koike 292e6938cc1SHelen Koike if (next_id == 0) 293e6938cc1SHelen Koike dev_dbg(rkisp1->dev, "no remote subdevice found\n"); 294e6938cc1SHelen Koike ntf->ops = &rkisp1_subdev_notifier_ops; 295e6938cc1SHelen Koike ret = v4l2_async_notifier_register(&rkisp1->v4l2_dev, ntf); 296e6938cc1SHelen Koike if (ret) { 297e6938cc1SHelen Koike v4l2_async_notifier_cleanup(ntf); 298e6938cc1SHelen Koike return ret; 299e6938cc1SHelen Koike } 300e6938cc1SHelen Koike return 0; 301e6938cc1SHelen Koike } 302e6938cc1SHelen Koike 303e6938cc1SHelen Koike /* ---------------------------------------------------------------------------- 304e6938cc1SHelen Koike * Power 305e6938cc1SHelen Koike */ 306e6938cc1SHelen Koike 307e6938cc1SHelen Koike static int __maybe_unused rkisp1_runtime_suspend(struct device *dev) 308e6938cc1SHelen Koike { 309e6938cc1SHelen Koike struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); 310e6938cc1SHelen Koike 311e6938cc1SHelen Koike clk_bulk_disable_unprepare(rkisp1->clk_size, rkisp1->clks); 312e6938cc1SHelen Koike return pinctrl_pm_select_sleep_state(dev); 313e6938cc1SHelen Koike } 314e6938cc1SHelen Koike 315e6938cc1SHelen Koike static int __maybe_unused rkisp1_runtime_resume(struct device *dev) 316e6938cc1SHelen Koike { 317e6938cc1SHelen Koike struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); 318e6938cc1SHelen Koike int ret; 319e6938cc1SHelen Koike 320e6938cc1SHelen Koike ret = pinctrl_pm_select_default_state(dev); 321e6938cc1SHelen Koike if (ret) 322e6938cc1SHelen Koike return ret; 323e6938cc1SHelen Koike ret = clk_bulk_prepare_enable(rkisp1->clk_size, rkisp1->clks); 324e6938cc1SHelen Koike if (ret) 325e6938cc1SHelen Koike return ret; 326e6938cc1SHelen Koike 327e6938cc1SHelen Koike return 0; 328e6938cc1SHelen Koike } 329e6938cc1SHelen Koike 330e6938cc1SHelen Koike static const struct dev_pm_ops rkisp1_pm_ops = { 331e6938cc1SHelen Koike SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 332e6938cc1SHelen Koike pm_runtime_force_resume) 333e6938cc1SHelen Koike SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL) 334e6938cc1SHelen Koike }; 335e6938cc1SHelen Koike 336e6938cc1SHelen Koike /* ---------------------------------------------------------------------------- 337e6938cc1SHelen Koike * Core 338e6938cc1SHelen Koike */ 339e6938cc1SHelen Koike 340e6938cc1SHelen Koike static int rkisp1_entities_register(struct rkisp1_device *rkisp1) 341e6938cc1SHelen Koike { 342e6938cc1SHelen Koike int ret; 343e6938cc1SHelen Koike 344e6938cc1SHelen Koike ret = rkisp1_isp_register(rkisp1); 345e6938cc1SHelen Koike if (ret) 346e6938cc1SHelen Koike return ret; 347e6938cc1SHelen Koike 348e6938cc1SHelen Koike ret = rkisp1_resizer_devs_register(rkisp1); 349e6938cc1SHelen Koike if (ret) 350e6938cc1SHelen Koike goto err_unreg_isp_subdev; 351e6938cc1SHelen Koike 352e6938cc1SHelen Koike ret = rkisp1_capture_devs_register(rkisp1); 353e6938cc1SHelen Koike if (ret) 354e6938cc1SHelen Koike goto err_unreg_resizer_devs; 355e6938cc1SHelen Koike 356e6938cc1SHelen Koike ret = rkisp1_stats_register(rkisp1); 357e6938cc1SHelen Koike if (ret) 358e6938cc1SHelen Koike goto err_unreg_capture_devs; 359e6938cc1SHelen Koike 360e6938cc1SHelen Koike ret = rkisp1_params_register(rkisp1); 361e6938cc1SHelen Koike if (ret) 362e6938cc1SHelen Koike goto err_unreg_stats; 363e6938cc1SHelen Koike 364e6938cc1SHelen Koike ret = rkisp1_subdev_notifier(rkisp1); 365e6938cc1SHelen Koike if (ret) { 366e6938cc1SHelen Koike dev_err(rkisp1->dev, 367e6938cc1SHelen Koike "Failed to register subdev notifier(%d)\n", ret); 368e6938cc1SHelen Koike goto err_unreg_params; 369e6938cc1SHelen Koike } 370e6938cc1SHelen Koike 371e6938cc1SHelen Koike return 0; 372e6938cc1SHelen Koike err_unreg_params: 373e6938cc1SHelen Koike rkisp1_params_unregister(rkisp1); 374e6938cc1SHelen Koike err_unreg_stats: 375e6938cc1SHelen Koike rkisp1_stats_unregister(rkisp1); 376e6938cc1SHelen Koike err_unreg_capture_devs: 377e6938cc1SHelen Koike rkisp1_capture_devs_unregister(rkisp1); 378e6938cc1SHelen Koike err_unreg_resizer_devs: 379e6938cc1SHelen Koike rkisp1_resizer_devs_unregister(rkisp1); 380e6938cc1SHelen Koike err_unreg_isp_subdev: 381e6938cc1SHelen Koike rkisp1_isp_unregister(rkisp1); 382e6938cc1SHelen Koike return ret; 383e6938cc1SHelen Koike } 384e6938cc1SHelen Koike 385e6938cc1SHelen Koike static irqreturn_t rkisp1_isr(int irq, void *ctx) 386e6938cc1SHelen Koike { 387e6938cc1SHelen Koike struct device *dev = ctx; 388e6938cc1SHelen Koike struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); 389e6938cc1SHelen Koike 390e6938cc1SHelen Koike /* 391e6938cc1SHelen Koike * Call rkisp1_capture_isr() first to handle the frame that 392e6938cc1SHelen Koike * potentially completed using the current frame_sequence number before 393e6938cc1SHelen Koike * it is potentially incremented by rkisp1_isp_isr() in the vertical 394e6938cc1SHelen Koike * sync. 395e6938cc1SHelen Koike */ 396e6938cc1SHelen Koike rkisp1_capture_isr(rkisp1); 397e6938cc1SHelen Koike rkisp1_isp_isr(rkisp1); 398e6938cc1SHelen Koike rkisp1_mipi_isr(rkisp1); 399e6938cc1SHelen Koike 400e6938cc1SHelen Koike return IRQ_HANDLED; 401e6938cc1SHelen Koike } 402e6938cc1SHelen Koike 403e6938cc1SHelen Koike static const char * const rk3399_isp_clks[] = { 404e6938cc1SHelen Koike "isp", 405e6938cc1SHelen Koike "aclk", 406e6938cc1SHelen Koike "hclk", 407e6938cc1SHelen Koike }; 408e6938cc1SHelen Koike 409e6938cc1SHelen Koike static const struct rkisp1_match_data rk3399_isp_clk_data = { 410e6938cc1SHelen Koike .clks = rk3399_isp_clks, 411e6938cc1SHelen Koike .size = ARRAY_SIZE(rk3399_isp_clks), 412e6938cc1SHelen Koike }; 413e6938cc1SHelen Koike 414e6938cc1SHelen Koike static const struct of_device_id rkisp1_of_match[] = { 415e6938cc1SHelen Koike { 416e6938cc1SHelen Koike .compatible = "rockchip,rk3399-cif-isp", 417e6938cc1SHelen Koike .data = &rk3399_isp_clk_data, 418e6938cc1SHelen Koike }, 419e6938cc1SHelen Koike {}, 420e6938cc1SHelen Koike }; 421e6938cc1SHelen Koike MODULE_DEVICE_TABLE(of, rkisp1_of_match); 422e6938cc1SHelen Koike 423e6938cc1SHelen Koike static void rkisp1_debug_init(struct rkisp1_device *rkisp1) 424e6938cc1SHelen Koike { 425e6938cc1SHelen Koike struct rkisp1_debug *debug = &rkisp1->debug; 426e6938cc1SHelen Koike 427e6938cc1SHelen Koike debug->debugfs_dir = debugfs_create_dir(RKISP1_DRIVER_NAME, NULL); 428e6938cc1SHelen Koike debugfs_create_ulong("data_loss", 0444, debug->debugfs_dir, 429e6938cc1SHelen Koike &debug->data_loss); 430e6938cc1SHelen Koike debugfs_create_ulong("outform_size_err", 0444, debug->debugfs_dir, 431e6938cc1SHelen Koike &debug->outform_size_error); 432e6938cc1SHelen Koike debugfs_create_ulong("img_stabilization_size_error", 0444, 433e6938cc1SHelen Koike debug->debugfs_dir, 434e6938cc1SHelen Koike &debug->img_stabilization_size_error); 435e6938cc1SHelen Koike debugfs_create_ulong("inform_size_error", 0444, debug->debugfs_dir, 436e6938cc1SHelen Koike &debug->inform_size_error); 437e6938cc1SHelen Koike debugfs_create_ulong("irq_delay", 0444, debug->debugfs_dir, 438e6938cc1SHelen Koike &debug->irq_delay); 439e6938cc1SHelen Koike debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir, 440e6938cc1SHelen Koike &debug->mipi_error); 441e6938cc1SHelen Koike debugfs_create_ulong("stats_error", 0444, debug->debugfs_dir, 442e6938cc1SHelen Koike &debug->stats_error); 443e6938cc1SHelen Koike debugfs_create_ulong("mp_stop_timeout", 0444, debug->debugfs_dir, 444e6938cc1SHelen Koike &debug->stop_timeout[RKISP1_MAINPATH]); 445e6938cc1SHelen Koike debugfs_create_ulong("sp_stop_timeout", 0444, debug->debugfs_dir, 446e6938cc1SHelen Koike &debug->stop_timeout[RKISP1_SELFPATH]); 447e6938cc1SHelen Koike debugfs_create_ulong("mp_frame_drop", 0444, debug->debugfs_dir, 448e6938cc1SHelen Koike &debug->frame_drop[RKISP1_MAINPATH]); 449e6938cc1SHelen Koike debugfs_create_ulong("sp_frame_drop", 0444, debug->debugfs_dir, 450e6938cc1SHelen Koike &debug->frame_drop[RKISP1_SELFPATH]); 451e6938cc1SHelen Koike } 452e6938cc1SHelen Koike 453e6938cc1SHelen Koike static int rkisp1_probe(struct platform_device *pdev) 454e6938cc1SHelen Koike { 455e6938cc1SHelen Koike const struct rkisp1_match_data *clk_data; 456e6938cc1SHelen Koike struct device *dev = &pdev->dev; 457e6938cc1SHelen Koike struct rkisp1_device *rkisp1; 458e6938cc1SHelen Koike struct v4l2_device *v4l2_dev; 459e6938cc1SHelen Koike unsigned int i; 460e6938cc1SHelen Koike int ret, irq; 461e6938cc1SHelen Koike 462e6938cc1SHelen Koike clk_data = of_device_get_match_data(&pdev->dev); 463e6938cc1SHelen Koike if (!clk_data) 464e6938cc1SHelen Koike return -ENODEV; 465e6938cc1SHelen Koike 466e6938cc1SHelen Koike rkisp1 = devm_kzalloc(dev, sizeof(*rkisp1), GFP_KERNEL); 467e6938cc1SHelen Koike if (!rkisp1) 468e6938cc1SHelen Koike return -ENOMEM; 469e6938cc1SHelen Koike 470e6938cc1SHelen Koike dev_set_drvdata(dev, rkisp1); 471e6938cc1SHelen Koike rkisp1->dev = dev; 472e6938cc1SHelen Koike 473e6938cc1SHelen Koike mutex_init(&rkisp1->stream_lock); 474e6938cc1SHelen Koike 475e6938cc1SHelen Koike rkisp1->base_addr = devm_platform_ioremap_resource(pdev, 0); 476e6938cc1SHelen Koike if (IS_ERR(rkisp1->base_addr)) 477e6938cc1SHelen Koike return PTR_ERR(rkisp1->base_addr); 478e6938cc1SHelen Koike 479e6938cc1SHelen Koike irq = platform_get_irq(pdev, 0); 480e6938cc1SHelen Koike if (irq < 0) 481e6938cc1SHelen Koike return irq; 482e6938cc1SHelen Koike 483e6938cc1SHelen Koike ret = devm_request_irq(dev, irq, rkisp1_isr, IRQF_SHARED, 484e6938cc1SHelen Koike dev_driver_string(dev), dev); 485e6938cc1SHelen Koike if (ret) { 486e6938cc1SHelen Koike dev_err(dev, "request irq failed: %d\n", ret); 487e6938cc1SHelen Koike return ret; 488e6938cc1SHelen Koike } 489e6938cc1SHelen Koike 490e6938cc1SHelen Koike rkisp1->irq = irq; 491e6938cc1SHelen Koike 492e6938cc1SHelen Koike for (i = 0; i < clk_data->size; i++) 493e6938cc1SHelen Koike rkisp1->clks[i].id = clk_data->clks[i]; 494e6938cc1SHelen Koike ret = devm_clk_bulk_get(dev, clk_data->size, rkisp1->clks); 495e6938cc1SHelen Koike if (ret) 496e6938cc1SHelen Koike return ret; 497e6938cc1SHelen Koike rkisp1->clk_size = clk_data->size; 498e6938cc1SHelen Koike 499e6938cc1SHelen Koike pm_runtime_enable(&pdev->dev); 500e6938cc1SHelen Koike 501e6938cc1SHelen Koike strscpy(rkisp1->media_dev.model, RKISP1_DRIVER_NAME, 502e6938cc1SHelen Koike sizeof(rkisp1->media_dev.model)); 503e6938cc1SHelen Koike rkisp1->media_dev.dev = &pdev->dev; 504e6938cc1SHelen Koike strscpy(rkisp1->media_dev.bus_info, RKISP1_BUS_INFO, 505e6938cc1SHelen Koike sizeof(rkisp1->media_dev.bus_info)); 506e6938cc1SHelen Koike media_device_init(&rkisp1->media_dev); 507e6938cc1SHelen Koike 508e6938cc1SHelen Koike v4l2_dev = &rkisp1->v4l2_dev; 509e6938cc1SHelen Koike v4l2_dev->mdev = &rkisp1->media_dev; 510e6938cc1SHelen Koike strscpy(v4l2_dev->name, RKISP1_DRIVER_NAME, sizeof(v4l2_dev->name)); 511e6938cc1SHelen Koike 512e6938cc1SHelen Koike ret = v4l2_device_register(rkisp1->dev, &rkisp1->v4l2_dev); 513e6938cc1SHelen Koike if (ret) 514e6938cc1SHelen Koike return ret; 515e6938cc1SHelen Koike 516e6938cc1SHelen Koike ret = media_device_register(&rkisp1->media_dev); 517e6938cc1SHelen Koike if (ret) { 518e6938cc1SHelen Koike dev_err(dev, "Failed to register media device: %d\n", ret); 519e6938cc1SHelen Koike goto err_unreg_v4l2_dev; 520e6938cc1SHelen Koike } 521e6938cc1SHelen Koike 522e6938cc1SHelen Koike ret = rkisp1_entities_register(rkisp1); 523e6938cc1SHelen Koike if (ret) 524e6938cc1SHelen Koike goto err_unreg_media_dev; 525e6938cc1SHelen Koike 526e6938cc1SHelen Koike rkisp1_debug_init(rkisp1); 527e6938cc1SHelen Koike 528e6938cc1SHelen Koike return 0; 529e6938cc1SHelen Koike 530e6938cc1SHelen Koike err_unreg_media_dev: 531e6938cc1SHelen Koike media_device_unregister(&rkisp1->media_dev); 532e6938cc1SHelen Koike err_unreg_v4l2_dev: 533e6938cc1SHelen Koike v4l2_device_unregister(&rkisp1->v4l2_dev); 534e6938cc1SHelen Koike pm_runtime_disable(&pdev->dev); 535e6938cc1SHelen Koike return ret; 536e6938cc1SHelen Koike } 537e6938cc1SHelen Koike 538e6938cc1SHelen Koike static int rkisp1_remove(struct platform_device *pdev) 539e6938cc1SHelen Koike { 540e6938cc1SHelen Koike struct rkisp1_device *rkisp1 = platform_get_drvdata(pdev); 541e6938cc1SHelen Koike 542e6938cc1SHelen Koike v4l2_async_notifier_unregister(&rkisp1->notifier); 543e6938cc1SHelen Koike v4l2_async_notifier_cleanup(&rkisp1->notifier); 544e6938cc1SHelen Koike 545e6938cc1SHelen Koike rkisp1_params_unregister(rkisp1); 546e6938cc1SHelen Koike rkisp1_stats_unregister(rkisp1); 547e6938cc1SHelen Koike rkisp1_capture_devs_unregister(rkisp1); 548e6938cc1SHelen Koike rkisp1_resizer_devs_unregister(rkisp1); 549e6938cc1SHelen Koike rkisp1_isp_unregister(rkisp1); 550e6938cc1SHelen Koike 551e6938cc1SHelen Koike media_device_unregister(&rkisp1->media_dev); 552e6938cc1SHelen Koike v4l2_device_unregister(&rkisp1->v4l2_dev); 553e6938cc1SHelen Koike 554e6938cc1SHelen Koike pm_runtime_disable(&pdev->dev); 555e6938cc1SHelen Koike 556e6938cc1SHelen Koike debugfs_remove_recursive(rkisp1->debug.debugfs_dir); 557e6938cc1SHelen Koike return 0; 558e6938cc1SHelen Koike } 559e6938cc1SHelen Koike 560e6938cc1SHelen Koike static struct platform_driver rkisp1_drv = { 561e6938cc1SHelen Koike .driver = { 562e6938cc1SHelen Koike .name = RKISP1_DRIVER_NAME, 563e6938cc1SHelen Koike .of_match_table = of_match_ptr(rkisp1_of_match), 564e6938cc1SHelen Koike .pm = &rkisp1_pm_ops, 565e6938cc1SHelen Koike }, 566e6938cc1SHelen Koike .probe = rkisp1_probe, 567e6938cc1SHelen Koike .remove = rkisp1_remove, 568e6938cc1SHelen Koike }; 569e6938cc1SHelen Koike 570e6938cc1SHelen Koike module_platform_driver(rkisp1_drv); 571e6938cc1SHelen Koike MODULE_DESCRIPTION("Rockchip ISP1 platform driver"); 572e6938cc1SHelen Koike MODULE_LICENSE("Dual MIT/GPL"); 573