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", ®);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