brintos

brintos / linux-shallow public Read only

0
0
Text · 38.6 KiB · 5f10bb4 Raw
1603 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * S5P/EXYNOS4 SoC series camera host interface media device driver4 *5 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.6 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>7 */8 9#include <linux/bug.h>10#include <linux/clk.h>11#include <linux/clk-provider.h>12#include <linux/device.h>13#include <linux/errno.h>14#include <linux/i2c.h>15#include <linux/kernel.h>16#include <linux/list.h>17#include <linux/module.h>18#include <linux/of.h>19#include <linux/of_platform.h>20#include <linux/of_graph.h>21#include <linux/pinctrl/consumer.h>22#include <linux/platform_device.h>23#include <linux/pm_runtime.h>24#include <linux/types.h>25#include <linux/slab.h>26#include <media/v4l2-async.h>27#include <media/v4l2-ctrls.h>28#include <media/v4l2-fwnode.h>29#include <media/media-device.h>30#include <media/drv-intf/exynos-fimc.h>31 32#include "media-dev.h"33#include "fimc-core.h"34#include "fimc-is.h"35#include "fimc-lite.h"36#include "mipi-csis.h"37 38/* Set up image sensor subdev -> FIMC capture node notifications. */39static void __setup_sensor_notification(struct fimc_md *fmd,40					struct v4l2_subdev *sensor,41					struct v4l2_subdev *fimc_sd)42{43	struct fimc_source_info *src_inf;44	struct fimc_sensor_info *md_si;45	unsigned long flags;46 47	src_inf = v4l2_get_subdev_hostdata(sensor);48	if (!src_inf || WARN_ON(fmd == NULL))49		return;50 51	md_si = source_to_sensor_info(src_inf);52	spin_lock_irqsave(&fmd->slock, flags);53	md_si->host = v4l2_get_subdevdata(fimc_sd);54	spin_unlock_irqrestore(&fmd->slock, flags);55}56 57/**58 * fimc_pipeline_prepare - update pipeline information with subdevice pointers59 * @p: fimc pipeline60 * @me: media entity terminating the pipeline61 *62 * Caller holds the graph mutex.63 */64static void fimc_pipeline_prepare(struct fimc_pipeline *p,65					struct media_entity *me)66{67	struct fimc_md *fmd = entity_to_fimc_mdev(me);68	struct v4l2_subdev *sd;69	struct v4l2_subdev *sensor = NULL;70	int i;71 72	for (i = 0; i < IDX_MAX; i++)73		p->subdevs[i] = NULL;74 75	while (1) {76		struct media_pad *pad = NULL;77 78		/* Find remote source pad */79		for (i = 0; i < me->num_pads; i++) {80			struct media_pad *spad = &me->pads[i];81			if (!(spad->flags & MEDIA_PAD_FL_SINK))82				continue;83			pad = media_pad_remote_pad_first(spad);84			if (pad)85				break;86		}87 88		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))89			break;90		sd = media_entity_to_v4l2_subdev(pad->entity);91 92		switch (sd->grp_id) {93		case GRP_ID_SENSOR:94			sensor = sd;95			fallthrough;96		case GRP_ID_FIMC_IS_SENSOR:97			p->subdevs[IDX_SENSOR] = sd;98			break;99		case GRP_ID_CSIS:100			p->subdevs[IDX_CSIS] = sd;101			break;102		case GRP_ID_FLITE:103			p->subdevs[IDX_FLITE] = sd;104			break;105		case GRP_ID_FIMC:106			p->subdevs[IDX_FIMC] = sd;107			break;108		case GRP_ID_FIMC_IS:109			p->subdevs[IDX_IS_ISP] = sd;110			break;111		default:112			break;113		}114		me = &sd->entity;115		if (me->num_pads == 1)116			break;117	}118 119	if (sensor && p->subdevs[IDX_FIMC])120		__setup_sensor_notification(fmd, sensor, p->subdevs[IDX_FIMC]);121}122 123/**124 * __subdev_set_power - change power state of a single subdev125 * @sd: subdevice to change power state for126 * @on: 1 to enable power or 0 to disable127 *128 * Return result of s_power subdev operation or -ENXIO if sd argument129 * is NULL. Return 0 if the subdevice does not implement s_power.130 */131static int __subdev_set_power(struct v4l2_subdev *sd, int on)132{133	int *use_count;134	int ret;135 136	if (sd == NULL)137		return -ENXIO;138 139	use_count = &sd->entity.use_count;140	if (on && (*use_count)++ > 0)141		return 0;142	else if (!on && (*use_count == 0 || --(*use_count) > 0))143		return 0;144	ret = v4l2_subdev_call(sd, core, s_power, on);145 146	return ret != -ENOIOCTLCMD ? ret : 0;147}148 149/**150 * fimc_pipeline_s_power - change power state of all pipeline subdevs151 * @p: fimc device terminating the pipeline152 * @on: true to power on, false to power off153 *154 * Needs to be called with the graph mutex held.155 */156static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool on)157{158	static const u8 seq[2][IDX_MAX - 1] = {159		{ IDX_IS_ISP, IDX_SENSOR, IDX_CSIS, IDX_FLITE },160		{ IDX_CSIS, IDX_FLITE, IDX_SENSOR, IDX_IS_ISP },161	};162	int i, ret = 0;163 164	if (p->subdevs[IDX_SENSOR] == NULL)165		return -ENXIO;166 167	for (i = 0; i < IDX_MAX - 1; i++) {168		unsigned int idx = seq[on][i];169 170		ret = __subdev_set_power(p->subdevs[idx], on);171 172 173		if (ret < 0 && ret != -ENXIO)174			goto error;175	}176	return 0;177error:178	for (; i >= 0; i--) {179		unsigned int idx = seq[on][i];180		__subdev_set_power(p->subdevs[idx], !on);181	}182	return ret;183}184 185/**186 * __fimc_pipeline_enable - enable power of all pipeline subdevs187 *			    and the sensor clock188 * @ep: video pipeline structure189 * @fmd: fimc media device190 *191 * Called with the graph mutex held.192 */193static int __fimc_pipeline_enable(struct exynos_media_pipeline *ep,194				  struct fimc_md *fmd)195{196	struct fimc_pipeline *p = to_fimc_pipeline(ep);197	int ret;198 199	/* Enable PXLASYNC clock if this pipeline includes FIMC-IS */200	if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) {201		ret = clk_prepare_enable(fmd->wbclk[CLK_IDX_WB_B]);202		if (ret < 0)203			return ret;204	}205 206	ret = fimc_pipeline_s_power(p, 1);207	if (!ret)208		return 0;209 210	if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP])211		clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);212 213	return ret;214}215 216/**217 * __fimc_pipeline_open - update the pipeline information, enable power218 *                        of all pipeline subdevs and the sensor clock219 * @ep: fimc device terminating the pipeline220 * @me: media entity to start graph walk with221 * @prepare: true to walk the current pipeline and acquire all subdevs222 *223 * Called with the graph mutex held.224 */225static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,226				struct media_entity *me, bool prepare)227{228	struct fimc_md *fmd = entity_to_fimc_mdev(me);229	struct fimc_pipeline *p = to_fimc_pipeline(ep);230	struct v4l2_subdev *sd;231 232	if (WARN_ON(p == NULL || me == NULL))233		return -EINVAL;234 235	if (prepare)236		fimc_pipeline_prepare(p, me);237 238	sd = p->subdevs[IDX_SENSOR];239	if (sd == NULL) {240		pr_warn("%s(): No sensor subdev\n", __func__);241		/*242		 * Pipeline open cannot fail so as to make it possible243		 * for the user space to configure the pipeline.244		 */245		return 0;246	}247 248	return __fimc_pipeline_enable(ep, fmd);249}250 251/**252 * __fimc_pipeline_close - disable the sensor clock and pipeline power253 * @ep: fimc device terminating the pipeline254 *255 * Disable power of all subdevs and turn the external sensor clock off.256 */257static int __fimc_pipeline_close(struct exynos_media_pipeline *ep)258{259	struct fimc_pipeline *p = to_fimc_pipeline(ep);260	struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL;261	struct fimc_md *fmd;262	int ret;263 264	if (sd == NULL) {265		pr_warn("%s(): No sensor subdev\n", __func__);266		return 0;267	}268 269	ret = fimc_pipeline_s_power(p, 0);270 271	fmd = entity_to_fimc_mdev(&sd->entity);272 273	/* Disable PXLASYNC clock if this pipeline includes FIMC-IS */274	if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP])275		clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);276 277	return ret == -ENXIO ? 0 : ret;278}279 280/**281 * __fimc_pipeline_s_stream - call s_stream() on pipeline subdevs282 * @ep: video pipeline structure283 * @on: passed as the s_stream() callback argument284 */285static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)286{287	static const u8 seq[2][IDX_MAX] = {288		{ IDX_FIMC, IDX_SENSOR, IDX_IS_ISP, IDX_CSIS, IDX_FLITE },289		{ IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP },290	};291	struct fimc_pipeline *p = to_fimc_pipeline(ep);292	enum fimc_subdev_index sd_id;293	int i, ret = 0;294 295	if (p->subdevs[IDX_SENSOR] == NULL) {296		struct fimc_md *fmd;297		struct v4l2_subdev *sd = p->subdevs[IDX_CSIS];298 299		if (!sd)300			sd = p->subdevs[IDX_FIMC];301 302		if (!sd) {303			/*304			 * If neither CSIS nor FIMC was set up,305			 * it's impossible to have any sensors306			 */307			return -ENODEV;308		}309 310		fmd = entity_to_fimc_mdev(&sd->entity);311 312		if (!fmd->user_subdev_api) {313			/*314			 * Sensor must be already discovered if we315			 * aren't in the user_subdev_api mode316			 */317			return -ENODEV;318		}319 320		/* Get pipeline sink entity */321		if (p->subdevs[IDX_FIMC])322			sd_id = IDX_FIMC;323		else if (p->subdevs[IDX_IS_ISP])324			sd_id = IDX_IS_ISP;325		else if (p->subdevs[IDX_FLITE])326			sd_id = IDX_FLITE;327		else328			return -ENODEV;329 330		/*331		 * Sensor could have been linked between open and STREAMON -332		 * check if this is the case.333		 */334		fimc_pipeline_prepare(p, &p->subdevs[sd_id]->entity);335 336		if (p->subdevs[IDX_SENSOR] == NULL)337			return -ENODEV;338 339		ret = __fimc_pipeline_enable(ep, fmd);340		if (ret < 0)341			return ret;342 343	}344 345	for (i = 0; i < IDX_MAX; i++) {346		unsigned int idx = seq[on][i];347 348		ret = v4l2_subdev_call(p->subdevs[idx], video, s_stream, on);349 350		if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)351			goto error;352	}353 354	return 0;355error:356	fimc_pipeline_s_power(p, !on);357	for (; i >= 0; i--) {358		unsigned int idx = seq[on][i];359		v4l2_subdev_call(p->subdevs[idx], video, s_stream, !on);360	}361	return ret;362}363 364/* Media pipeline operations for the FIMC/FIMC-LITE video device driver */365static const struct exynos_media_pipeline_ops fimc_pipeline_ops = {366	.open		= __fimc_pipeline_open,367	.close		= __fimc_pipeline_close,368	.set_stream	= __fimc_pipeline_s_stream,369};370 371static struct exynos_media_pipeline *fimc_md_pipeline_create(372						struct fimc_md *fmd)373{374	struct fimc_pipeline *p;375 376	p = kzalloc(sizeof(*p), GFP_KERNEL);377	if (!p)378		return NULL;379 380	list_add_tail(&p->list, &fmd->pipelines);381 382	p->ep.ops = &fimc_pipeline_ops;383	return &p->ep;384}385 386static void fimc_md_pipelines_free(struct fimc_md *fmd)387{388	while (!list_empty(&fmd->pipelines)) {389		struct fimc_pipeline *p;390 391		p = list_entry(fmd->pipelines.next, typeof(*p), list);392		list_del(&p->list);393		kfree(p);394	}395}396 397static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,398				   struct device_node *ep)399{400	int index = fmd->num_sensors;401	struct fimc_source_info *pd = &fmd->sensor[index].pdata;402	struct device_node *rem, *np;403	struct v4l2_async_connection *asd;404	struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };405	int ret;406 407	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &endpoint);408	if (ret) {409		of_node_put(ep);410		return ret;411	}412 413	if (WARN_ON(endpoint.base.port == 0) || index >= FIMC_MAX_SENSORS) {414		of_node_put(ep);415		return -EINVAL;416	}417 418	pd->mux_id = (endpoint.base.port - 1) & 0x1;419 420	rem = of_graph_get_remote_port_parent(ep);421	if (rem == NULL) {422		v4l2_info(&fmd->v4l2_dev, "Remote device at %pOF not found\n",423							ep);424		of_node_put(ep);425		return 0;426	}427 428	if (fimc_input_is_parallel(endpoint.base.port)) {429		if (endpoint.bus_type == V4L2_MBUS_PARALLEL)430			pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_601;431		else432			pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_656;433		pd->flags = endpoint.bus.parallel.flags;434	} else if (fimc_input_is_mipi_csi(endpoint.base.port)) {435		/*436		 * MIPI CSI-2: only input mux selection and437		 * the sensor's clock frequency is needed.438		 */439		pd->sensor_bus_type = FIMC_BUS_TYPE_MIPI_CSI2;440	} else {441		v4l2_err(&fmd->v4l2_dev, "Wrong port id (%u) at node %pOF\n",442			 endpoint.base.port, rem);443	}444	/*445	 * For FIMC-IS handled sensors, that are placed under i2c-isp device446	 * node, FIMC is connected to the FIMC-IS through its ISP Writeback447	 * input. Sensors are attached to the FIMC-LITE hostdata interface448	 * directly or through MIPI-CSIS, depending on the external media bus449	 * used. This needs to be handled in a more reliable way, not by just450	 * checking parent's node name.451	 */452	np = of_get_parent(rem);453	of_node_put(rem);454 455	if (of_node_name_eq(np, "i2c-isp"))456		pd->fimc_bus_type = FIMC_BUS_TYPE_ISP_WRITEBACK;457	else458		pd->fimc_bus_type = pd->sensor_bus_type;459	of_node_put(np);460 461	if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) {462		of_node_put(ep);463		return -EINVAL;464	}465 466	asd = v4l2_async_nf_add_fwnode_remote(&fmd->subdev_notifier,467					      of_fwnode_handle(ep),468					      struct v4l2_async_connection);469 470	of_node_put(ep);471 472	if (IS_ERR(asd))473		return PTR_ERR(asd);474 475	fmd->sensor[index].asd = asd;476	fmd->num_sensors++;477 478	return 0;479}480 481/* Parse port node and register as a sub-device any sensor specified there. */482static int fimc_md_parse_port_node(struct fimc_md *fmd,483				   struct device_node *port)484{485	struct device_node *ep;486	int ret;487 488	for_each_child_of_node(port, ep) {489		ret = fimc_md_parse_one_endpoint(fmd, ep);490		if (ret < 0) {491			of_node_put(ep);492			return ret;493		}494	}495 496	return 0;497}498 499/* Register all SoC external sub-devices */500static int fimc_md_register_sensor_entities(struct fimc_md *fmd)501{502	struct device_node *parent = fmd->pdev->dev.of_node;503	struct device_node *ports = NULL;504	struct device_node *node;505	int ret;506 507	/*508	 * Runtime resume one of the FIMC entities to make sure509	 * the sclk_cam clocks are not globally disabled.510	 */511	if (!fmd->pmf)512		return -ENXIO;513 514	ret = pm_runtime_resume_and_get(fmd->pmf);515	if (ret < 0)516		return ret;517 518	fmd->num_sensors = 0;519 520	/* Attach sensors linked to MIPI CSI-2 receivers */521	for_each_available_child_of_node(parent, node) {522		struct device_node *port;523 524		if (!of_node_name_eq(node, "csis"))525			continue;526		/* The csis node can have only port subnode. */527		port = of_get_next_child(node, NULL);528		if (!port)529			continue;530 531		ret = fimc_md_parse_port_node(fmd, port);532		of_node_put(port);533		if (ret < 0) {534			of_node_put(node);535			goto cleanup;536		}537	}538 539	/* Attach sensors listed in the parallel-ports node */540	ports = of_get_child_by_name(parent, "parallel-ports");541	if (!ports)542		goto rpm_put;543 544	for_each_child_of_node(ports, node) {545		ret = fimc_md_parse_port_node(fmd, node);546		if (ret < 0) {547			of_node_put(node);548			goto cleanup;549		}550	}551	of_node_put(ports);552 553rpm_put:554	pm_runtime_put(fmd->pmf);555	return 0;556 557cleanup:558	of_node_put(ports);559	v4l2_async_nf_cleanup(&fmd->subdev_notifier);560	pm_runtime_put(fmd->pmf);561	return ret;562}563 564static int __of_get_csis_id(struct device_node *np)565{566	u32 reg = 0;567 568	np = of_get_child_by_name(np, "port");569	if (!np)570		return -EINVAL;571	of_property_read_u32(np, "reg", &reg);572	of_node_put(np);573	return reg - FIMC_INPUT_MIPI_CSI2_0;574}575 576/*577 * MIPI-CSIS, FIMC and FIMC-LITE platform devices registration.578 */579static int register_fimc_lite_entity(struct fimc_md *fmd,580				     struct fimc_lite *fimc_lite)581{582	struct v4l2_subdev *sd;583	struct exynos_media_pipeline *ep;584	int ret;585 586	if (WARN_ON(fimc_lite->index >= FIMC_LITE_MAX_DEVS ||587		    fmd->fimc_lite[fimc_lite->index]))588		return -EBUSY;589 590	sd = &fimc_lite->subdev;591	sd->grp_id = GRP_ID_FLITE;592 593	ep = fimc_md_pipeline_create(fmd);594	if (!ep)595		return -ENOMEM;596 597	v4l2_set_subdev_hostdata(sd, ep);598 599	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);600	if (!ret)601		fmd->fimc_lite[fimc_lite->index] = fimc_lite;602	else603		v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.LITE%d\n",604			 fimc_lite->index);605	return ret;606}607 608static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc)609{610	struct v4l2_subdev *sd;611	struct exynos_media_pipeline *ep;612	int ret;613 614	if (WARN_ON(fimc->id >= FIMC_MAX_DEVS || fmd->fimc[fimc->id]))615		return -EBUSY;616 617	sd = &fimc->vid_cap.subdev;618	sd->grp_id = GRP_ID_FIMC;619 620	ep = fimc_md_pipeline_create(fmd);621	if (!ep)622		return -ENOMEM;623 624	v4l2_set_subdev_hostdata(sd, ep);625 626	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);627	if (!ret) {628		if (!fmd->pmf && fimc->pdev)629			fmd->pmf = &fimc->pdev->dev;630		fmd->fimc[fimc->id] = fimc;631		fimc->vid_cap.user_subdev_api = fmd->user_subdev_api;632	} else {633		v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",634			 fimc->id, ret);635	}636	return ret;637}638 639static int register_csis_entity(struct fimc_md *fmd,640				struct platform_device *pdev,641				struct v4l2_subdev *sd)642{643	struct device_node *node = pdev->dev.of_node;644	int id, ret;645 646	id = node ? __of_get_csis_id(node) : max(0, pdev->id);647 648	if (WARN_ON(id < 0 || id >= CSIS_MAX_ENTITIES))649		return -ENOENT;650 651	if (WARN_ON(fmd->csis[id].sd))652		return -EBUSY;653 654	sd->grp_id = GRP_ID_CSIS;655	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);656	if (!ret)657		fmd->csis[id].sd = sd;658	else659		v4l2_err(&fmd->v4l2_dev,660			 "Failed to register MIPI-CSIS.%d (%d)\n", id, ret);661	return ret;662}663 664static int register_fimc_is_entity(struct fimc_md *fmd, struct fimc_is *is)665{666	struct v4l2_subdev *sd = &is->isp.subdev;667	struct exynos_media_pipeline *ep;668	int ret;669 670	/* Allocate pipeline object for the ISP capture video node. */671	ep = fimc_md_pipeline_create(fmd);672	if (!ep)673		return -ENOMEM;674 675	v4l2_set_subdev_hostdata(sd, ep);676 677	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);678	if (ret) {679		v4l2_err(&fmd->v4l2_dev,680			 "Failed to register FIMC-ISP (%d)\n", ret);681		return ret;682	}683 684	fmd->fimc_is = is;685	return 0;686}687 688static int fimc_md_register_platform_entity(struct fimc_md *fmd,689					    struct platform_device *pdev,690					    int plat_entity)691{692	struct device *dev = &pdev->dev;693	int ret = -EPROBE_DEFER;694	void *drvdata;695 696	/* Lock to ensure dev->driver won't change. */697	device_lock(dev);698 699	if (!dev->driver || !try_module_get(dev->driver->owner))700		goto dev_unlock;701 702	drvdata = dev_get_drvdata(dev);703	/* Some subdev didn't probe successfully id drvdata is NULL */704	if (drvdata) {705		switch (plat_entity) {706		case IDX_FIMC:707			ret = register_fimc_entity(fmd, drvdata);708			break;709		case IDX_FLITE:710			ret = register_fimc_lite_entity(fmd, drvdata);711			break;712		case IDX_CSIS:713			ret = register_csis_entity(fmd, pdev, drvdata);714			break;715		case IDX_IS_ISP:716			ret = register_fimc_is_entity(fmd, drvdata);717			break;718		default:719			ret = -ENODEV;720		}721	}722 723	module_put(dev->driver->owner);724dev_unlock:725	device_unlock(dev);726	if (ret == -EPROBE_DEFER)727		dev_info(&fmd->pdev->dev, "deferring %s device registration\n",728			dev_name(dev));729	else if (ret < 0)730		dev_err(&fmd->pdev->dev, "%s device registration failed (%d)\n",731			dev_name(dev), ret);732	return ret;733}734 735/* Register FIMC, FIMC-LITE and CSIS media entities */736static int fimc_md_register_platform_entities(struct fimc_md *fmd,737					      struct device_node *parent)738{739	struct device_node *node;740	int ret = 0;741 742	for_each_available_child_of_node(parent, node) {743		struct platform_device *pdev;744		int plat_entity = -1;745 746		pdev = of_find_device_by_node(node);747		if (!pdev)748			continue;749 750		/* If driver of any entity isn't ready try all again later. */751		if (of_node_name_eq(node, CSIS_OF_NODE_NAME))752			plat_entity = IDX_CSIS;753		else if (of_node_name_eq(node, FIMC_IS_OF_NODE_NAME))754			plat_entity = IDX_IS_ISP;755		else if (of_node_name_eq(node, FIMC_LITE_OF_NODE_NAME))756			plat_entity = IDX_FLITE;757		else if (of_node_name_eq(node, FIMC_OF_NODE_NAME) &&758			 !of_property_read_bool(node, "samsung,lcd-wb"))759			plat_entity = IDX_FIMC;760 761		if (plat_entity >= 0)762			ret = fimc_md_register_platform_entity(fmd, pdev,763							plat_entity);764		put_device(&pdev->dev);765		if (ret < 0) {766			of_node_put(node);767			break;768		}769	}770 771	return ret;772}773 774static void fimc_md_unregister_entities(struct fimc_md *fmd)775{776	int i;777 778	for (i = 0; i < FIMC_MAX_DEVS; i++) {779		struct fimc_dev *dev = fmd->fimc[i];780		if (dev == NULL)781			continue;782		v4l2_device_unregister_subdev(&dev->vid_cap.subdev);783		dev->vid_cap.ve.pipe = NULL;784		fmd->fimc[i] = NULL;785	}786	for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {787		struct fimc_lite *dev = fmd->fimc_lite[i];788		if (dev == NULL)789			continue;790		v4l2_device_unregister_subdev(&dev->subdev);791		dev->ve.pipe = NULL;792		fmd->fimc_lite[i] = NULL;793	}794	for (i = 0; i < CSIS_MAX_ENTITIES; i++) {795		if (fmd->csis[i].sd == NULL)796			continue;797		v4l2_device_unregister_subdev(fmd->csis[i].sd);798		fmd->csis[i].sd = NULL;799	}800 801	if (fmd->fimc_is)802		v4l2_device_unregister_subdev(&fmd->fimc_is->isp.subdev);803 804	v4l2_info(&fmd->v4l2_dev, "Unregistered all entities\n");805}806 807/**808 * __fimc_md_create_fimc_sink_links - create links to all FIMC entities809 * @fmd: fimc media device810 * @source: the source entity to create links to all fimc entities from811 * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null812 * @pad: the source entity pad index813 * @link_mask: bitmask of the fimc devices for which link should be enabled814 */815static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,816					    struct media_entity *source,817					    struct v4l2_subdev *sensor,818					    int pad, int link_mask)819{820	struct fimc_source_info *si = NULL;821	struct media_entity *sink;822	unsigned int flags = 0;823	int i, ret = 0;824 825	if (sensor) {826		si = v4l2_get_subdev_hostdata(sensor);827		/* Skip direct FIMC links in the logical FIMC-IS sensor path */828		if (si && si->fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK)829			ret = 1;830	}831 832	for (i = 0; !ret && i < FIMC_MAX_DEVS; i++) {833		if (!fmd->fimc[i])834			continue;835		/*836		 * Some FIMC variants are not fitted with camera capture837		 * interface. Skip creating a link from sensor for those.838		 */839		if (!fmd->fimc[i]->variant->has_cam_if)840			continue;841 842		flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0;843 844		sink = &fmd->fimc[i]->vid_cap.subdev.entity;845		ret = media_create_pad_link(source, pad, sink,846					      FIMC_SD_PAD_SINK_CAM, flags);847		if (ret)848			return ret;849 850		/* Notify FIMC capture subdev entity */851		ret = media_entity_call(sink, link_setup, &sink->pads[0],852					&source->pads[pad], flags);853		if (ret)854			break;855 856		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]\n",857			  source->name, flags ? '=' : '-', sink->name);858	}859 860	for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {861		if (!fmd->fimc_lite[i])862			continue;863 864		sink = &fmd->fimc_lite[i]->subdev.entity;865		ret = media_create_pad_link(source, pad, sink,866					       FLITE_SD_PAD_SINK, 0);867		if (ret)868			return ret;869 870		/* Notify FIMC-LITE subdev entity */871		ret = media_entity_call(sink, link_setup, &sink->pads[0],872					&source->pads[pad], 0);873		if (ret)874			break;875 876		v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]\n",877			  source->name, sink->name);878	}879	return 0;880}881 882/* Create links from FIMC-LITE source pads to other entities */883static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)884{885	struct media_entity *source, *sink;886	int i, ret = 0;887 888	for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {889		struct fimc_lite *fimc = fmd->fimc_lite[i];890 891		if (fimc == NULL)892			continue;893 894		source = &fimc->subdev.entity;895		sink = &fimc->ve.vdev.entity;896		/* FIMC-LITE's subdev and video node */897		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA,898					       sink, 0, 0);899		if (ret)900			break;901		/* Link from FIMC-LITE to IS-ISP subdev */902		sink = &fmd->fimc_is->isp.subdev.entity;903		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP,904					       sink, 0, 0);905		if (ret)906			break;907	}908 909	return ret;910}911 912/* Create FIMC-IS links */913static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)914{915	struct fimc_isp *isp = &fmd->fimc_is->isp;916	struct media_entity *source, *sink;917	int i, ret;918 919	source = &isp->subdev.entity;920 921	for (i = 0; i < FIMC_MAX_DEVS; i++) {922		if (fmd->fimc[i] == NULL)923			continue;924 925		/* Link from FIMC-IS-ISP subdev to FIMC */926		sink = &fmd->fimc[i]->vid_cap.subdev.entity;927		ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,928					       sink, FIMC_SD_PAD_SINK_FIFO, 0);929		if (ret)930			return ret;931	}932 933	/* Link from FIMC-IS-ISP subdev to fimc-is-isp.capture video node */934	sink = &isp->video_capture.ve.vdev.entity;935 936	/* Skip this link if the fimc-is-isp video node driver isn't built-in */937	if (sink->num_pads == 0)938		return 0;939 940	return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA,941					sink, 0, 0);942}943 944/**945 * fimc_md_create_links - create default links between registered entities946 * @fmd: fimc media device947 *948 * Parallel interface sensor entities are connected directly to FIMC capture949 * entities. The sensors using MIPI CSIS bus are connected through immutable950 * link with CSI receiver entity specified by mux_id. Any registered CSIS951 * entity has a link to each registered FIMC capture entity. Enabled links952 * are created by default between each subsequent registered sensor and953 * subsequent FIMC capture entity. The number of default active links is954 * determined by the number of available sensors or FIMC entities,955 * whichever is less.956 */957static int fimc_md_create_links(struct fimc_md *fmd)958{959	struct v4l2_subdev *csi_sensors[CSIS_MAX_ENTITIES] = { NULL };960	struct v4l2_subdev *sensor, *csis;961	struct fimc_source_info *pdata;962	struct media_entity *source, *sink;963	int i, pad, fimc_id = 0, ret = 0;964	u32 flags, link_mask = 0;965 966	for (i = 0; i < fmd->num_sensors; i++) {967		if (fmd->sensor[i].subdev == NULL)968			continue;969 970		sensor = fmd->sensor[i].subdev;971		pdata = v4l2_get_subdev_hostdata(sensor);972		if (!pdata)973			continue;974 975		source = NULL;976 977		switch (pdata->sensor_bus_type) {978		case FIMC_BUS_TYPE_MIPI_CSI2:979			if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,980				"Wrong CSI channel id: %d\n", pdata->mux_id))981				return -EINVAL;982 983			csis = fmd->csis[pdata->mux_id].sd;984			if (WARN(csis == NULL,985				 "MIPI-CSI interface specified but s5p-csis module is not loaded!\n"))986				return -EINVAL;987 988			pad = sensor->entity.num_pads - 1;989			ret = media_create_pad_link(&sensor->entity, pad,990					      &csis->entity, CSIS_PAD_SINK,991					      MEDIA_LNK_FL_IMMUTABLE |992					      MEDIA_LNK_FL_ENABLED);993			if (ret)994				return ret;995 996			v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]\n",997				  sensor->entity.name, csis->entity.name);998 999			source = NULL;1000			csi_sensors[pdata->mux_id] = sensor;1001			break;1002 1003		case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656:1004			source = &sensor->entity;1005			pad = 0;1006			break;1007 1008		default:1009			v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n",1010				 pdata->sensor_bus_type);1011			return -EINVAL;1012		}1013		if (source == NULL)1014			continue;1015 1016		link_mask = 1 << fimc_id++;1017		ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor,1018						       pad, link_mask);1019	}1020 1021	for (i = 0; i < CSIS_MAX_ENTITIES; i++) {1022		if (fmd->csis[i].sd == NULL)1023			continue;1024 1025		source = &fmd->csis[i].sd->entity;1026		pad = CSIS_PAD_SOURCE;1027		sensor = csi_sensors[i];1028 1029		link_mask = 1 << fimc_id++;1030		ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor,1031						       pad, link_mask);1032	}1033 1034	/* Create immutable links between each FIMC's subdev and video node */1035	flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;1036	for (i = 0; i < FIMC_MAX_DEVS; i++) {1037		if (!fmd->fimc[i])1038			continue;1039 1040		source = &fmd->fimc[i]->vid_cap.subdev.entity;1041		sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity;1042 1043		ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE,1044					      sink, 0, flags);1045		if (ret)1046			break;1047	}1048 1049	ret = __fimc_md_create_flite_source_links(fmd);1050	if (ret < 0)1051		return ret;1052 1053	if (fmd->use_isp)1054		ret = __fimc_md_create_fimc_is_links(fmd);1055 1056	return ret;1057}1058 1059/*1060 * The peripheral sensor and CAM_BLK (PIXELASYNCMx) clocks management.1061 */1062static void fimc_md_put_clocks(struct fimc_md *fmd)1063{1064	int i = FIMC_MAX_CAMCLKS;1065 1066	while (--i >= 0) {1067		if (IS_ERR(fmd->camclk[i].clock))1068			continue;1069		clk_put(fmd->camclk[i].clock);1070		fmd->camclk[i].clock = ERR_PTR(-EINVAL);1071	}1072 1073	/* Writeback (PIXELASYNCMx) clocks */1074	for (i = 0; i < FIMC_MAX_WBCLKS; i++) {1075		if (IS_ERR(fmd->wbclk[i]))1076			continue;1077		clk_put(fmd->wbclk[i]);1078		fmd->wbclk[i] = ERR_PTR(-EINVAL);1079	}1080}1081 1082static int fimc_md_get_clocks(struct fimc_md *fmd)1083{1084	struct device *dev = &fmd->pdev->dev;1085	char clk_name[32];1086	struct clk *clock;1087	int i, ret = 0;1088 1089	for (i = 0; i < FIMC_MAX_CAMCLKS; i++)1090		fmd->camclk[i].clock = ERR_PTR(-EINVAL);1091 1092	for (i = 0; i < FIMC_MAX_CAMCLKS; i++) {1093		snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i);1094		clock = clk_get(dev, clk_name);1095 1096		if (IS_ERR(clock)) {1097			dev_err(dev, "Failed to get clock: %s\n", clk_name);1098			ret = PTR_ERR(clock);1099			break;1100		}1101		fmd->camclk[i].clock = clock;1102	}1103	if (ret)1104		fimc_md_put_clocks(fmd);1105 1106	if (!fmd->use_isp)1107		return 0;1108	/*1109	 * For now get only PIXELASYNCM1 clock (Writeback B/ISP),1110	 * leave PIXELASYNCM0 out for the LCD Writeback driver.1111	 */1112	fmd->wbclk[CLK_IDX_WB_A] = ERR_PTR(-EINVAL);1113 1114	for (i = CLK_IDX_WB_B; i < FIMC_MAX_WBCLKS; i++) {1115		snprintf(clk_name, sizeof(clk_name), "pxl_async%u", i);1116		clock = clk_get(dev, clk_name);1117		if (IS_ERR(clock)) {1118			v4l2_err(&fmd->v4l2_dev, "Failed to get clock: %s\n",1119				  clk_name);1120			ret = PTR_ERR(clock);1121			break;1122		}1123		fmd->wbclk[i] = clock;1124	}1125	if (ret)1126		fimc_md_put_clocks(fmd);1127 1128	return ret;1129}1130 1131static int __fimc_md_modify_pipeline(struct media_entity *entity, bool enable)1132{1133	struct exynos_video_entity *ve;1134	struct fimc_pipeline *p;1135	struct video_device *vdev;1136	int ret;1137 1138	vdev = media_entity_to_video_device(entity);1139	if (vdev->entity.use_count == 0)1140		return 0;1141 1142	ve = vdev_to_exynos_video_entity(vdev);1143	p = to_fimc_pipeline(ve->pipe);1144	/*1145	 * Nothing to do if we are disabling the pipeline, some link1146	 * has been disconnected and p->subdevs array is cleared now.1147	 */1148	if (!enable && p->subdevs[IDX_SENSOR] == NULL)1149		return 0;1150 1151	if (enable)1152		ret = __fimc_pipeline_open(ve->pipe, entity, true);1153	else1154		ret = __fimc_pipeline_close(ve->pipe);1155 1156	if (ret == 0 && !enable)1157		memset(p->subdevs, 0, sizeof(p->subdevs));1158 1159	return ret;1160}1161 1162/* Locking: called with entity->graph_obj.mdev->graph_mutex mutex held. */1163static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable,1164				      struct media_graph *graph)1165{1166	struct media_entity *entity_err = entity;1167	int ret;1168 1169	/*1170	 * Walk current graph and call the pipeline open/close routine for each1171	 * opened video node that belongs to the graph of entities connected1172	 * through active links. This is needed as we cannot power on/off the1173	 * subdevs in random order.1174	 */1175	media_graph_walk_start(graph, entity);1176 1177	while ((entity = media_graph_walk_next(graph))) {1178		if (!is_media_entity_v4l2_video_device(entity))1179			continue;1180 1181		ret  = __fimc_md_modify_pipeline(entity, enable);1182 1183		if (ret < 0)1184			goto err;1185	}1186 1187	return 0;1188 1189err:1190	media_graph_walk_start(graph, entity_err);1191 1192	while ((entity_err = media_graph_walk_next(graph))) {1193		if (!is_media_entity_v4l2_video_device(entity_err))1194			continue;1195 1196		__fimc_md_modify_pipeline(entity_err, !enable);1197 1198		if (entity_err == entity)1199			break;1200	}1201 1202	return ret;1203}1204 1205static int fimc_md_link_notify(struct media_link *link, unsigned int flags,1206				unsigned int notification)1207{1208	struct media_graph *graph =1209		&container_of(link->graph_obj.mdev, struct fimc_md,1210			      media_dev)->link_setup_graph;1211	struct media_entity *sink = link->sink->entity;1212	int ret = 0;1213 1214	/* Before link disconnection */1215	if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) {1216		ret = media_graph_walk_init(graph,1217						   link->graph_obj.mdev);1218		if (ret)1219			return ret;1220		if (!(flags & MEDIA_LNK_FL_ENABLED))1221			ret = __fimc_md_modify_pipelines(sink, false, graph);1222#if 01223		else1224			/* TODO: Link state change validation */1225#endif1226	/* After link activation */1227	} else if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH) {1228		if (link->flags & MEDIA_LNK_FL_ENABLED)1229			ret = __fimc_md_modify_pipelines(sink, true, graph);1230		media_graph_walk_cleanup(graph);1231	}1232 1233	return ret ? -EPIPE : 0;1234}1235 1236static const struct media_device_ops fimc_md_ops = {1237	.link_notify = fimc_md_link_notify,1238};1239 1240static ssize_t subdev_conf_mode_show(struct device *dev,1241				     struct device_attribute *attr, char *buf)1242{1243	struct fimc_md *fmd = dev_get_drvdata(dev);1244 1245	if (fmd->user_subdev_api)1246		return strscpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE);1247 1248	return strscpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);1249}1250 1251static ssize_t subdev_conf_mode_store(struct device *dev,1252				      struct device_attribute *attr,1253				      const char *buf, size_t count)1254{1255	struct fimc_md *fmd = dev_get_drvdata(dev);1256	bool subdev_api;1257	int i;1258 1259	if (!strcmp(buf, "vid-dev\n"))1260		subdev_api = false;1261	else if (!strcmp(buf, "sub-dev\n"))1262		subdev_api = true;1263	else1264		return count;1265 1266	fmd->user_subdev_api = subdev_api;1267	for (i = 0; i < FIMC_MAX_DEVS; i++)1268		if (fmd->fimc[i])1269			fmd->fimc[i]->vid_cap.user_subdev_api = subdev_api;1270	return count;1271}1272/*1273 * This device attribute is to select video pipeline configuration method.1274 * There are following valid values:1275 *  vid-dev - for V4L2 video node API only, subdevice will be configured1276 *  by the host driver.1277 *  sub-dev - for media controller API, subdevs must be configured in user1278 *  space before starting streaming.1279 */1280static DEVICE_ATTR_RW(subdev_conf_mode);1281 1282static int cam_clk_prepare(struct clk_hw *hw)1283{1284	struct cam_clk *camclk = to_cam_clk(hw);1285 1286	if (camclk->fmd->pmf == NULL)1287		return -ENODEV;1288 1289	return pm_runtime_resume_and_get(camclk->fmd->pmf);1290}1291 1292static void cam_clk_unprepare(struct clk_hw *hw)1293{1294	struct cam_clk *camclk = to_cam_clk(hw);1295 1296	if (camclk->fmd->pmf == NULL)1297		return;1298 1299	pm_runtime_put_sync(camclk->fmd->pmf);1300}1301 1302static const struct clk_ops cam_clk_ops = {1303	.prepare = cam_clk_prepare,1304	.unprepare = cam_clk_unprepare,1305};1306 1307static void fimc_md_unregister_clk_provider(struct fimc_md *fmd)1308{1309	struct cam_clk_provider *cp = &fmd->clk_provider;1310	unsigned int i;1311 1312	if (cp->of_node)1313		of_clk_del_provider(cp->of_node);1314 1315	for (i = 0; i < cp->num_clocks; i++)1316		clk_unregister(cp->clks[i]);1317}1318 1319static int fimc_md_register_clk_provider(struct fimc_md *fmd)1320{1321	struct cam_clk_provider *cp = &fmd->clk_provider;1322	struct device *dev = &fmd->pdev->dev;1323	int i, ret;1324 1325	for (i = 0; i < FIMC_MAX_CAMCLKS; i++) {1326		struct cam_clk *camclk = &cp->camclk[i];1327		struct clk_init_data init;1328		const char *p_name;1329 1330		ret = of_property_read_string_index(dev->of_node,1331					"clock-output-names", i, &init.name);1332		if (ret < 0)1333			break;1334 1335		p_name = __clk_get_name(fmd->camclk[i].clock);1336 1337		/* It's safe since clk_register() will duplicate the string. */1338		init.parent_names = &p_name;1339		init.num_parents = 1;1340		init.ops = &cam_clk_ops;1341		init.flags = CLK_SET_RATE_PARENT;1342		camclk->hw.init = &init;1343		camclk->fmd = fmd;1344 1345		cp->clks[i] = clk_register(NULL, &camclk->hw);1346		if (IS_ERR(cp->clks[i])) {1347			dev_err(dev, "failed to register clock: %s (%ld)\n",1348					init.name, PTR_ERR(cp->clks[i]));1349			ret = PTR_ERR(cp->clks[i]);1350			goto err;1351		}1352		cp->num_clocks++;1353	}1354 1355	if (cp->num_clocks == 0) {1356		dev_warn(dev, "clk provider not registered\n");1357		return 0;1358	}1359 1360	cp->clk_data.clks = cp->clks;1361	cp->clk_data.clk_num = cp->num_clocks;1362	cp->of_node = dev->of_node;1363	ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,1364				  &cp->clk_data);1365	if (ret == 0)1366		return 0;1367err:1368	fimc_md_unregister_clk_provider(fmd);1369	return ret;1370}1371 1372static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,1373				 struct v4l2_subdev *subdev,1374				 struct v4l2_async_connection *asd)1375{1376	struct fimc_md *fmd = notifier_to_fimc_md(notifier);1377	struct fimc_sensor_info *si = NULL;1378	int i;1379 1380	/* Find platform data for this sensor subdev */1381	for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++)1382		if (fmd->sensor[i].asd == asd)1383			si = &fmd->sensor[i];1384 1385	if (si == NULL)1386		return -EINVAL;1387 1388	v4l2_set_subdev_hostdata(subdev, &si->pdata);1389 1390	if (si->pdata.fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK)1391		subdev->grp_id = GRP_ID_FIMC_IS_SENSOR;1392	else1393		subdev->grp_id = GRP_ID_SENSOR;1394 1395	si->subdev = subdev;1396 1397	v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n",1398		  subdev->name, fmd->num_sensors);1399 1400	fmd->num_sensors++;1401 1402	return 0;1403}1404 1405static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)1406{1407	struct fimc_md *fmd = notifier_to_fimc_md(notifier);1408	int ret;1409 1410	mutex_lock(&fmd->media_dev.graph_mutex);1411 1412	ret = fimc_md_create_links(fmd);1413	if (ret < 0)1414		goto unlock;1415 1416	ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);1417unlock:1418	mutex_unlock(&fmd->media_dev.graph_mutex);1419	if (ret < 0)1420		return ret;1421 1422	return media_device_register(&fmd->media_dev);1423}1424 1425static const struct v4l2_async_notifier_operations subdev_notifier_ops = {1426	.bound = subdev_notifier_bound,1427	.complete = subdev_notifier_complete,1428};1429 1430static int fimc_md_probe(struct platform_device *pdev)1431{1432	struct device *dev = &pdev->dev;1433	struct v4l2_device *v4l2_dev;1434	struct pinctrl *pinctrl;1435	struct fimc_md *fmd;1436	int ret;1437 1438	fmd = devm_kzalloc(dev, sizeof(*fmd), GFP_KERNEL);1439	if (!fmd)1440		return -ENOMEM;1441 1442	ret = of_platform_populate(dev->of_node, NULL, NULL, dev);1443	if (ret < 0)1444		return -ENOMEM;1445 1446	spin_lock_init(&fmd->slock);1447	INIT_LIST_HEAD(&fmd->pipelines);1448	fmd->pdev = pdev;1449 1450	strscpy(fmd->media_dev.model, "Samsung S5P FIMC",1451		sizeof(fmd->media_dev.model));1452	fmd->media_dev.ops = &fimc_md_ops;1453	fmd->media_dev.dev = dev;1454 1455	v4l2_dev = &fmd->v4l2_dev;1456	v4l2_dev->mdev = &fmd->media_dev;1457	v4l2_dev->notify = fimc_sensor_notify;1458	strscpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));1459 1460	fmd->use_isp = fimc_md_is_isp_available(dev->of_node);1461	fmd->user_subdev_api = true;1462 1463	media_device_init(&fmd->media_dev);1464 1465	ret = v4l2_device_register(dev, &fmd->v4l2_dev);1466	if (ret < 0) {1467		v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);1468		goto err_md;1469	}1470 1471	ret = fimc_md_get_clocks(fmd);1472	if (ret)1473		goto err_v4l2dev;1474 1475	pinctrl = devm_pinctrl_get(dev);1476	if (IS_ERR(pinctrl))1477		dev_dbg(dev, "Failed to get pinctrl: %pe\n", pinctrl);1478 1479	platform_set_drvdata(pdev, fmd);1480 1481	v4l2_async_nf_init(&fmd->subdev_notifier, &fmd->v4l2_dev);1482 1483	ret = fimc_md_register_platform_entities(fmd, dev->of_node);1484	if (ret)1485		goto err_clk;1486 1487	ret = fimc_md_register_sensor_entities(fmd);1488	if (ret)1489		goto err_m_ent;1490 1491	ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);1492	if (ret)1493		goto err_cleanup;1494	/*1495	 * FIMC platform devices need to be registered before the sclk_cam1496	 * clocks provider, as one of these devices needs to be activated1497	 * to enable the clock.1498	 */1499	ret = fimc_md_register_clk_provider(fmd);1500	if (ret < 0) {1501		v4l2_err(v4l2_dev, "clock provider registration failed\n");1502		goto err_attr;1503	}1504 1505	if (fmd->num_sensors > 0) {1506		fmd->subdev_notifier.ops = &subdev_notifier_ops;1507		fmd->num_sensors = 0;1508 1509		ret = v4l2_async_nf_register(&fmd->subdev_notifier);1510		if (ret)1511			goto err_clk_p;1512	}1513 1514	return 0;1515 1516err_clk_p:1517	fimc_md_unregister_clk_provider(fmd);1518err_attr:1519	device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);1520err_cleanup:1521	v4l2_async_nf_cleanup(&fmd->subdev_notifier);1522err_m_ent:1523	fimc_md_unregister_entities(fmd);1524err_clk:1525	fimc_md_put_clocks(fmd);1526err_v4l2dev:1527	v4l2_device_unregister(&fmd->v4l2_dev);1528err_md:1529	media_device_cleanup(&fmd->media_dev);1530	return ret;1531}1532 1533static void fimc_md_remove(struct platform_device *pdev)1534{1535	struct fimc_md *fmd = platform_get_drvdata(pdev);1536 1537	if (!fmd)1538		return;1539 1540	fimc_md_unregister_clk_provider(fmd);1541	v4l2_async_nf_unregister(&fmd->subdev_notifier);1542	v4l2_async_nf_cleanup(&fmd->subdev_notifier);1543 1544	v4l2_device_unregister(&fmd->v4l2_dev);1545	device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);1546	fimc_md_unregister_entities(fmd);1547	fimc_md_pipelines_free(fmd);1548	media_device_unregister(&fmd->media_dev);1549	media_device_cleanup(&fmd->media_dev);1550	fimc_md_put_clocks(fmd);1551}1552 1553static const struct platform_device_id fimc_driver_ids[] __always_unused = {1554	{ .name = "s5p-fimc-md" },1555	{ },1556};1557MODULE_DEVICE_TABLE(platform, fimc_driver_ids);1558 1559static const struct of_device_id fimc_md_of_match[] = {1560	{ .compatible = "samsung,fimc" },1561	{ },1562};1563MODULE_DEVICE_TABLE(of, fimc_md_of_match);1564 1565static struct platform_driver fimc_md_driver = {1566	.probe		= fimc_md_probe,1567	.remove_new	= fimc_md_remove,1568	.driver = {1569		.of_match_table = of_match_ptr(fimc_md_of_match),1570		.name		= "s5p-fimc-md",1571	}1572};1573 1574static int __init fimc_md_init(void)1575{1576	int ret;1577 1578	request_module("s5p-csis");1579	ret = fimc_register_driver();1580	if (ret)1581		return ret;1582 1583	ret = platform_driver_register(&fimc_md_driver);1584	if (ret)1585		fimc_unregister_driver();1586 1587	return ret;1588}1589 1590static void __exit fimc_md_exit(void)1591{1592	platform_driver_unregister(&fimc_md_driver);1593	fimc_unregister_driver();1594}1595 1596module_init(fimc_md_init);1597module_exit(fimc_md_exit);1598 1599MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");1600MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");1601MODULE_LICENSE("GPL");1602MODULE_VERSION("2.0.1");1603