brintos

brintos / linux-shallow public Read only

0
0
Text · 20.4 KiB · dd114ab Raw
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", &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