761 lines · c
1// SPDX-License-Identifier: (GPL-2.0+ OR MIT)2/*3 * Rockchip ISP1 Driver - Base driver4 *5 * Copyright (C) 2019 Collabora, Ltd.6 *7 * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd.8 * Copyright (C) 2017 Rockchip Electronics Co., Ltd.9 */10 11#include <linux/clk.h>12#include <linux/interrupt.h>13#include <linux/mfd/syscon.h>14#include <linux/module.h>15#include <linux/of.h>16#include <linux/of_graph.h>17#include <linux/platform_device.h>18#include <linux/pinctrl/consumer.h>19#include <linux/pm_runtime.h>20#include <media/v4l2-fwnode.h>21#include <media/v4l2-mc.h>22 23#include "rkisp1-common.h"24#include "rkisp1-csi.h"25 26/*27 * ISP Details28 * -----------29 *30 * ISP Comprises with:31 * MIPI serial camera interface32 * Image Signal Processing33 * Many Image Enhancement Blocks34 * Crop35 * Resizer36 * RBG display ready image37 * Image Rotation38 *39 * ISP Block Diagram40 * -----------------41 * rkisp1-resizer.c rkisp1-capture.c42 * |====================| |=======================|43 * rkisp1-isp.c Main Picture Path44 * |==========================| |===============================================|45 * +-----------+ +--+--+--+--+ +--------+ +--------+ +-----------+46 * | | | | | | | | | | | | |47 * +--------+ |\ | | | | | | | -->| Crop |->| RSZ |------------->| |48 * | MIPI |--->| \ | | | | | | | | | | | | | |49 * +--------+ | | | | |IE|IE|IE|IE| | +--------+ +--------+ | Memory |50 * |MUX|--->| ISP |->|0 |1 |2 |3 |---+ | Interface |51 * +--------+ | | | | | | | | | | +--------+ +--------+ +--------+ | |52 * |Parallel|--->| / | | | | | | | | | | | | | | | |53 * +--------+ |/ | | | | | | | -->| Crop |->| RSZ |->| RGB |->| |54 * | | | | | | | | | | | | Rotate | | |55 * +-----------+ +--+--+--+--+ +--------+ +--------+ +--------+ +-----------+56 * ^57 * +--------+ | |===============================================|58 * | DMA |------------------------------------+ Self Picture Path59 * +--------+60 *61 * rkisp1-stats.c rkisp1-params.c62 * |===============| |===============|63 * +---------------+ +---------------+64 * | | | |65 * | ISP | | ISP |66 * | | | |67 * +---------------+ +---------------+68 *69 *70 * Media Topology71 * --------------72 *73 * +----------+ +----------+74 * | Sensor 1 | | Sensor X |75 * ------------ ... ------------76 * | 0 | | 0 |77 * +----------+ +----------+78 * | |79 * \----\ /----/80 * | |81 * v v82 * +-------------+83 * | 0 |84 * ---------------85 * | CSI-2 RX |86 * --------------- +-----------+87 * | 1 | | params |88 * +-------------+ | (output) |89 * | +-----------+90 * v |91 * +------+------+ |92 * | 0 | 1 |<---------+93 * |------+------|94 * | ISP |95 * |------+------|96 * +-------------| 2 | 3 |----------+97 * | +------+------+ |98 * | | |99 * v v v100 * +- ---------+ +-----------+ +-----------+101 * | 0 | | 0 | | stats |102 * ------------- ------------- | (capture) |103 * | Resizer | | Resizer | +-----------+104 * ------------| ------------|105 * | 1 | | 1 |106 * +-----------+ +-----------+107 * | |108 * v v109 * +-----------+ +-----------+110 * | selfpath | | mainpath |111 * | (capture) | | (capture) |112 * +-----------+ +-----------+113 */114 115struct rkisp1_isr_data {116 const char *name;117 irqreturn_t (*isr)(int irq, void *ctx);118 u32 line_mask;119};120 121/* ----------------------------------------------------------------------------122 * Sensor DT bindings123 */124 125static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier,126 struct v4l2_subdev *sd,127 struct v4l2_async_connection *asc)128{129 struct rkisp1_device *rkisp1 =130 container_of(notifier, struct rkisp1_device, notifier);131 struct rkisp1_sensor_async *s_asd =132 container_of(asc, struct rkisp1_sensor_async, asd);133 int source_pad;134 int ret;135 136 s_asd->sd = sd;137 138 source_pad = media_entity_get_fwnode_pad(&sd->entity, s_asd->source_ep,139 MEDIA_PAD_FL_SOURCE);140 if (source_pad < 0) {141 dev_err(rkisp1->dev, "failed to find source pad for %s\n",142 sd->name);143 return source_pad;144 }145 146 if (s_asd->port == 0)147 return rkisp1_csi_link_sensor(rkisp1, sd, s_asd, source_pad);148 149 ret = media_create_pad_link(&sd->entity, source_pad,150 &rkisp1->isp.sd.entity,151 RKISP1_ISP_PAD_SINK_VIDEO,152 !s_asd->index ? MEDIA_LNK_FL_ENABLED : 0);153 if (ret) {154 dev_err(rkisp1->dev, "failed to link source pad of %s\n",155 sd->name);156 return ret;157 }158 159 return 0;160}161 162static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier)163{164 struct rkisp1_device *rkisp1 =165 container_of(notifier, struct rkisp1_device, notifier);166 167 return v4l2_device_register_subdev_nodes(&rkisp1->v4l2_dev);168}169 170static void rkisp1_subdev_notifier_destroy(struct v4l2_async_connection *asc)171{172 struct rkisp1_sensor_async *rk_asd =173 container_of(asc, struct rkisp1_sensor_async, asd);174 175 fwnode_handle_put(rk_asd->source_ep);176}177 178static const struct v4l2_async_notifier_operations rkisp1_subdev_notifier_ops = {179 .bound = rkisp1_subdev_notifier_bound,180 .complete = rkisp1_subdev_notifier_complete,181 .destroy = rkisp1_subdev_notifier_destroy,182};183 184static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)185{186 struct v4l2_async_notifier *ntf = &rkisp1->notifier;187 struct fwnode_handle *fwnode = dev_fwnode(rkisp1->dev);188 struct fwnode_handle *ep;189 unsigned int index = 0;190 int ret = 0;191 192 v4l2_async_nf_init(ntf, &rkisp1->v4l2_dev);193 194 ntf->ops = &rkisp1_subdev_notifier_ops;195 196 fwnode_graph_for_each_endpoint(fwnode, ep) {197 struct fwnode_handle *port;198 struct v4l2_fwnode_endpoint vep = { };199 struct rkisp1_sensor_async *rk_asd;200 struct fwnode_handle *source;201 u32 reg = 0;202 203 /* Select the bus type based on the port. */204 port = fwnode_get_parent(ep);205 fwnode_property_read_u32(port, "reg", ®);206 fwnode_handle_put(port);207 208 switch (reg) {209 case 0:210 /* MIPI CSI-2 port */211 if (!rkisp1_has_feature(rkisp1, MIPI_CSI2)) {212 dev_err(rkisp1->dev,213 "internal CSI must be available for port 0\n");214 ret = -EINVAL;215 break;216 }217 218 vep.bus_type = V4L2_MBUS_CSI2_DPHY;219 break;220 221 case 1:222 /*223 * Parallel port. The bus-type property in DT is224 * mandatory for port 1, it will be used to determine if225 * it's PARALLEL or BT656.226 */227 vep.bus_type = V4L2_MBUS_UNKNOWN;228 break;229 }230 231 /* Parse the endpoint and validate the bus type. */232 ret = v4l2_fwnode_endpoint_parse(ep, &vep);233 if (ret) {234 dev_err(rkisp1->dev, "failed to parse endpoint %pfw\n",235 ep);236 break;237 }238 239 if (vep.base.port == 1) {240 if (vep.bus_type != V4L2_MBUS_PARALLEL &&241 vep.bus_type != V4L2_MBUS_BT656) {242 dev_err(rkisp1->dev,243 "port 1 must be parallel or BT656\n");244 ret = -EINVAL;245 break;246 }247 }248 249 /* Add the async subdev to the notifier. */250 source = fwnode_graph_get_remote_endpoint(ep);251 if (!source) {252 dev_err(rkisp1->dev,253 "endpoint %pfw has no remote endpoint\n",254 ep);255 ret = -ENODEV;256 break;257 }258 259 rk_asd = v4l2_async_nf_add_fwnode(ntf, source,260 struct rkisp1_sensor_async);261 if (IS_ERR(rk_asd)) {262 fwnode_handle_put(source);263 ret = PTR_ERR(rk_asd);264 break;265 }266 267 rk_asd->index = index++;268 rk_asd->source_ep = source;269 rk_asd->mbus_type = vep.bus_type;270 rk_asd->port = vep.base.port;271 272 if (vep.bus_type == V4L2_MBUS_CSI2_DPHY) {273 rk_asd->mbus_flags = vep.bus.mipi_csi2.flags;274 rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes;275 } else {276 rk_asd->mbus_flags = vep.bus.parallel.flags;277 }278 279 dev_dbg(rkisp1->dev, "registered ep id %d, bus type %u, %u lanes\n",280 vep.base.id, rk_asd->mbus_type, rk_asd->lanes);281 }282 283 if (ret) {284 fwnode_handle_put(ep);285 v4l2_async_nf_cleanup(ntf);286 return ret;287 }288 289 if (!index)290 dev_dbg(rkisp1->dev, "no remote subdevice found\n");291 292 ret = v4l2_async_nf_register(ntf);293 if (ret) {294 v4l2_async_nf_cleanup(ntf);295 return ret;296 }297 298 return 0;299}300 301/* ----------------------------------------------------------------------------302 * Power303 */304 305static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)306{307 struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);308 309 rkisp1->irqs_enabled = false;310 /* Make sure the IRQ handler will see the above */311 mb();312 313 /*314 * Wait until any running IRQ handler has returned. The IRQ handler315 * may get called even after this (as it's a shared interrupt line)316 * but the 'irqs_enabled' flag will make the handler return immediately.317 */318 for (unsigned int il = 0; il < ARRAY_SIZE(rkisp1->irqs); ++il) {319 if (rkisp1->irqs[il] == -1)320 continue;321 322 /* Skip if the irq line is the same as previous */323 if (il == 0 || rkisp1->irqs[il - 1] != rkisp1->irqs[il])324 synchronize_irq(rkisp1->irqs[il]);325 }326 327 clk_bulk_disable_unprepare(rkisp1->clk_size, rkisp1->clks);328 return pinctrl_pm_select_sleep_state(dev);329}330 331static int __maybe_unused rkisp1_runtime_resume(struct device *dev)332{333 struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);334 int ret;335 336 ret = pinctrl_pm_select_default_state(dev);337 if (ret)338 return ret;339 ret = clk_bulk_prepare_enable(rkisp1->clk_size, rkisp1->clks);340 if (ret)341 return ret;342 343 rkisp1->irqs_enabled = true;344 /* Make sure the IRQ handler will see the above */345 mb();346 347 return 0;348}349 350static const struct dev_pm_ops rkisp1_pm_ops = {351 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,352 pm_runtime_force_resume)353 SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL)354};355 356/* ----------------------------------------------------------------------------357 * Core358 */359 360static int rkisp1_create_links(struct rkisp1_device *rkisp1)361{362 unsigned int dev_count = rkisp1_path_count(rkisp1);363 unsigned int i;364 int ret;365 366 if (rkisp1_has_feature(rkisp1, MIPI_CSI2)) {367 /* Link the CSI receiver to the ISP. */368 ret = media_create_pad_link(&rkisp1->csi.sd.entity,369 RKISP1_CSI_PAD_SRC,370 &rkisp1->isp.sd.entity,371 RKISP1_ISP_PAD_SINK_VIDEO,372 MEDIA_LNK_FL_ENABLED);373 if (ret)374 return ret;375 }376 377 /* create ISP->RSZ->CAP links */378 for (i = 0; i < dev_count; i++) {379 struct media_entity *resizer =380 &rkisp1->resizer_devs[i].sd.entity;381 struct media_entity *capture =382 &rkisp1->capture_devs[i].vnode.vdev.entity;383 384 ret = media_create_pad_link(&rkisp1->isp.sd.entity,385 RKISP1_ISP_PAD_SOURCE_VIDEO,386 resizer, RKISP1_RSZ_PAD_SINK,387 MEDIA_LNK_FL_ENABLED);388 if (ret)389 return ret;390 391 ret = media_create_pad_link(resizer, RKISP1_RSZ_PAD_SRC,392 capture, 0,393 MEDIA_LNK_FL_ENABLED |394 MEDIA_LNK_FL_IMMUTABLE);395 if (ret)396 return ret;397 }398 399 /* params links */400 ret = media_create_pad_link(&rkisp1->params.vnode.vdev.entity, 0,401 &rkisp1->isp.sd.entity,402 RKISP1_ISP_PAD_SINK_PARAMS,403 MEDIA_LNK_FL_ENABLED |404 MEDIA_LNK_FL_IMMUTABLE);405 if (ret)406 return ret;407 408 /* 3A stats links */409 return media_create_pad_link(&rkisp1->isp.sd.entity,410 RKISP1_ISP_PAD_SOURCE_STATS,411 &rkisp1->stats.vnode.vdev.entity, 0,412 MEDIA_LNK_FL_ENABLED |413 MEDIA_LNK_FL_IMMUTABLE);414}415 416static void rkisp1_entities_unregister(struct rkisp1_device *rkisp1)417{418 if (rkisp1_has_feature(rkisp1, MIPI_CSI2))419 rkisp1_csi_unregister(rkisp1);420 rkisp1_params_unregister(rkisp1);421 rkisp1_stats_unregister(rkisp1);422 rkisp1_capture_devs_unregister(rkisp1);423 rkisp1_resizer_devs_unregister(rkisp1);424 rkisp1_isp_unregister(rkisp1);425}426 427static int rkisp1_entities_register(struct rkisp1_device *rkisp1)428{429 int ret;430 431 ret = rkisp1_isp_register(rkisp1);432 if (ret)433 goto error;434 435 ret = rkisp1_resizer_devs_register(rkisp1);436 if (ret)437 goto error;438 439 ret = rkisp1_capture_devs_register(rkisp1);440 if (ret)441 goto error;442 443 ret = rkisp1_stats_register(rkisp1);444 if (ret)445 goto error;446 447 ret = rkisp1_params_register(rkisp1);448 if (ret)449 goto error;450 451 if (rkisp1_has_feature(rkisp1, MIPI_CSI2)) {452 ret = rkisp1_csi_register(rkisp1);453 if (ret)454 goto error;455 }456 457 ret = rkisp1_create_links(rkisp1);458 if (ret)459 goto error;460 461 return 0;462 463error:464 rkisp1_entities_unregister(rkisp1);465 return ret;466}467 468static irqreturn_t rkisp1_isr(int irq, void *ctx)469{470 irqreturn_t ret = IRQ_NONE;471 472 /*473 * Call rkisp1_capture_isr() first to handle the frame that474 * potentially completed using the current frame_sequence number before475 * it is potentially incremented by rkisp1_isp_isr() in the vertical476 * sync.477 */478 479 if (rkisp1_capture_isr(irq, ctx) == IRQ_HANDLED)480 ret = IRQ_HANDLED;481 482 if (rkisp1_isp_isr(irq, ctx) == IRQ_HANDLED)483 ret = IRQ_HANDLED;484 485 if (rkisp1_csi_isr(irq, ctx) == IRQ_HANDLED)486 ret = IRQ_HANDLED;487 488 return ret;489}490 491static const char * const px30_isp_clks[] = {492 "isp",493 "aclk",494 "hclk",495 "pclk",496};497 498static const struct rkisp1_isr_data px30_isp_isrs[] = {499 { "isp", rkisp1_isp_isr, BIT(RKISP1_IRQ_ISP) },500 { "mi", rkisp1_capture_isr, BIT(RKISP1_IRQ_MI) },501 { "mipi", rkisp1_csi_isr, BIT(RKISP1_IRQ_MIPI) },502};503 504static const struct rkisp1_info px30_isp_info = {505 .clks = px30_isp_clks,506 .clk_size = ARRAY_SIZE(px30_isp_clks),507 .isrs = px30_isp_isrs,508 .isr_size = ARRAY_SIZE(px30_isp_isrs),509 .isp_ver = RKISP1_V12,510 .features = RKISP1_FEATURE_MIPI_CSI2511 | RKISP1_FEATURE_SELF_PATH512 | RKISP1_FEATURE_DUAL_CROP513 | RKISP1_FEATURE_BLS,514 .max_width = 3264,515 .max_height = 2448,516};517 518static const char * const rk3399_isp_clks[] = {519 "isp",520 "aclk",521 "hclk",522};523 524static const struct rkisp1_isr_data rk3399_isp_isrs[] = {525 { NULL, rkisp1_isr, BIT(RKISP1_IRQ_ISP) | BIT(RKISP1_IRQ_MI) | BIT(RKISP1_IRQ_MIPI) },526};527 528static const struct rkisp1_info rk3399_isp_info = {529 .clks = rk3399_isp_clks,530 .clk_size = ARRAY_SIZE(rk3399_isp_clks),531 .isrs = rk3399_isp_isrs,532 .isr_size = ARRAY_SIZE(rk3399_isp_isrs),533 .isp_ver = RKISP1_V10,534 .features = RKISP1_FEATURE_MIPI_CSI2535 | RKISP1_FEATURE_SELF_PATH536 | RKISP1_FEATURE_DUAL_CROP537 | RKISP1_FEATURE_BLS,538 .max_width = 4416,539 .max_height = 3312,540};541 542static const char * const imx8mp_isp_clks[] = {543 "isp",544 "hclk",545 "aclk",546};547 548static const struct rkisp1_isr_data imx8mp_isp_isrs[] = {549 { NULL, rkisp1_isr, BIT(RKISP1_IRQ_ISP) | BIT(RKISP1_IRQ_MI) },550};551 552static const struct rkisp1_info imx8mp_isp_info = {553 .clks = imx8mp_isp_clks,554 .clk_size = ARRAY_SIZE(imx8mp_isp_clks),555 .isrs = imx8mp_isp_isrs,556 .isr_size = ARRAY_SIZE(imx8mp_isp_isrs),557 .isp_ver = RKISP1_V_IMX8MP,558 .features = RKISP1_FEATURE_MAIN_STRIDE559 | RKISP1_FEATURE_DMA_34BIT560 | RKISP1_FEATURE_COMPAND,561 .max_width = 4096,562 .max_height = 3072,563};564 565static const struct of_device_id rkisp1_of_match[] = {566 {567 .compatible = "rockchip,px30-cif-isp",568 .data = &px30_isp_info,569 },570 {571 .compatible = "rockchip,rk3399-cif-isp",572 .data = &rk3399_isp_info,573 },574 {575 .compatible = "fsl,imx8mp-isp",576 .data = &imx8mp_isp_info,577 },578 {},579};580MODULE_DEVICE_TABLE(of, rkisp1_of_match);581 582static int rkisp1_probe(struct platform_device *pdev)583{584 const struct rkisp1_info *info;585 struct device *dev = &pdev->dev;586 struct rkisp1_device *rkisp1;587 struct v4l2_device *v4l2_dev;588 unsigned int i;589 u64 dma_mask;590 int ret, irq;591 u32 cif_id;592 593 rkisp1 = devm_kzalloc(dev, sizeof(*rkisp1), GFP_KERNEL);594 if (!rkisp1)595 return -ENOMEM;596 597 info = of_device_get_match_data(dev);598 rkisp1->info = info;599 600 dev_set_drvdata(dev, rkisp1);601 rkisp1->dev = dev;602 603 dma_mask = rkisp1_has_feature(rkisp1, DMA_34BIT) ? DMA_BIT_MASK(34) :604 DMA_BIT_MASK(32);605 606 ret = dma_set_mask_and_coherent(dev, dma_mask);607 if (ret)608 return ret;609 610 mutex_init(&rkisp1->stream_lock);611 612 rkisp1->base_addr = devm_platform_ioremap_resource(pdev, 0);613 if (IS_ERR(rkisp1->base_addr))614 return PTR_ERR(rkisp1->base_addr);615 616 for (unsigned int il = 0; il < ARRAY_SIZE(rkisp1->irqs); ++il)617 rkisp1->irqs[il] = -1;618 619 for (i = 0; i < info->isr_size; i++) {620 irq = info->isrs[i].name621 ? platform_get_irq_byname(pdev, info->isrs[i].name)622 : platform_get_irq(pdev, i);623 if (irq < 0)624 return irq;625 626 for (unsigned int il = 0; il < ARRAY_SIZE(rkisp1->irqs); ++il) {627 if (info->isrs[i].line_mask & BIT(il))628 rkisp1->irqs[il] = irq;629 }630 631 ret = devm_request_irq(dev, irq, info->isrs[i].isr, IRQF_SHARED,632 dev_driver_string(dev), dev);633 if (ret) {634 dev_err(dev, "request irq failed: %d\n", ret);635 return ret;636 }637 }638 639 for (i = 0; i < info->clk_size; i++)640 rkisp1->clks[i].id = info->clks[i];641 ret = devm_clk_bulk_get(dev, info->clk_size, rkisp1->clks);642 if (ret)643 return ret;644 rkisp1->clk_size = info->clk_size;645 646 if (info->isp_ver == RKISP1_V_IMX8MP) {647 unsigned int id;648 649 rkisp1->gasket = syscon_regmap_lookup_by_phandle_args(dev->of_node,650 "fsl,blk-ctrl",651 1, &id);652 if (IS_ERR(rkisp1->gasket)) {653 ret = PTR_ERR(rkisp1->gasket);654 dev_err(dev, "failed to get gasket: %d\n", ret);655 return ret;656 }657 658 rkisp1->gasket_id = id;659 }660 661 pm_runtime_enable(&pdev->dev);662 663 ret = pm_runtime_resume_and_get(&pdev->dev);664 if (ret)665 goto err_pm_runtime_disable;666 667 cif_id = rkisp1_read(rkisp1, RKISP1_CIF_VI_ID);668 dev_dbg(rkisp1->dev, "CIF_ID 0x%08x\n", cif_id);669 670 pm_runtime_put(&pdev->dev);671 672 rkisp1->media_dev.hw_revision = info->isp_ver;673 strscpy(rkisp1->media_dev.model, RKISP1_DRIVER_NAME,674 sizeof(rkisp1->media_dev.model));675 rkisp1->media_dev.dev = &pdev->dev;676 strscpy(rkisp1->media_dev.bus_info, RKISP1_BUS_INFO,677 sizeof(rkisp1->media_dev.bus_info));678 media_device_init(&rkisp1->media_dev);679 680 v4l2_dev = &rkisp1->v4l2_dev;681 v4l2_dev->mdev = &rkisp1->media_dev;682 strscpy(v4l2_dev->name, RKISP1_DRIVER_NAME, sizeof(v4l2_dev->name));683 684 ret = v4l2_device_register(rkisp1->dev, &rkisp1->v4l2_dev);685 if (ret)686 goto err_media_dev_cleanup;687 688 ret = media_device_register(&rkisp1->media_dev);689 if (ret) {690 dev_err(dev, "Failed to register media device: %d\n", ret);691 goto err_unreg_v4l2_dev;692 }693 694 if (rkisp1->info->features & RKISP1_FEATURE_MIPI_CSI2) {695 ret = rkisp1_csi_init(rkisp1);696 if (ret)697 goto err_unreg_media_dev;698 }699 700 ret = rkisp1_entities_register(rkisp1);701 if (ret)702 goto err_cleanup_csi;703 704 ret = rkisp1_subdev_notifier_register(rkisp1);705 if (ret)706 goto err_unreg_entities;707 708 rkisp1_debug_init(rkisp1);709 710 return 0;711 712err_unreg_entities:713 rkisp1_entities_unregister(rkisp1);714err_cleanup_csi:715 if (rkisp1_has_feature(rkisp1, MIPI_CSI2))716 rkisp1_csi_cleanup(rkisp1);717err_unreg_media_dev:718 media_device_unregister(&rkisp1->media_dev);719err_unreg_v4l2_dev:720 v4l2_device_unregister(&rkisp1->v4l2_dev);721err_media_dev_cleanup:722 media_device_cleanup(&rkisp1->media_dev);723err_pm_runtime_disable:724 pm_runtime_disable(&pdev->dev);725 return ret;726}727 728static void rkisp1_remove(struct platform_device *pdev)729{730 struct rkisp1_device *rkisp1 = platform_get_drvdata(pdev);731 732 v4l2_async_nf_unregister(&rkisp1->notifier);733 v4l2_async_nf_cleanup(&rkisp1->notifier);734 735 rkisp1_entities_unregister(rkisp1);736 if (rkisp1_has_feature(rkisp1, MIPI_CSI2))737 rkisp1_csi_cleanup(rkisp1);738 rkisp1_debug_cleanup(rkisp1);739 740 media_device_unregister(&rkisp1->media_dev);741 v4l2_device_unregister(&rkisp1->v4l2_dev);742 743 media_device_cleanup(&rkisp1->media_dev);744 745 pm_runtime_disable(&pdev->dev);746}747 748static struct platform_driver rkisp1_drv = {749 .driver = {750 .name = RKISP1_DRIVER_NAME,751 .of_match_table = of_match_ptr(rkisp1_of_match),752 .pm = &rkisp1_pm_ops,753 },754 .probe = rkisp1_probe,755 .remove_new = rkisp1_remove,756};757 758module_platform_driver(rkisp1_drv);759MODULE_DESCRIPTION("Rockchip ISP1 platform driver");760MODULE_LICENSE("Dual MIT/GPL");761